• WebForm应用log4net记录错误日志——使用线程列队写入


    我的项目结构如下图:

    日志帮助类库需要log4net包:工具—NuGet包管理器—管理解决方案NuGet程序包

    线程日志帮助类 FlashLogger.cs 代码

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading;
    using System.Web;
    using log4net;
    using log4net.Config;
    
    namespace FlashLog
    {
        public sealed class FlashLogger
        {
            /// <summary>
            /// 记录消息Queue
            /// </summary>
            private readonly ConcurrentQueue<FlashLogMessage> _que;
    
            /// <summary>
            /// 信号
            /// </summary>
            private readonly ManualResetEvent _mre;
    
            /// <summary>
            /// 日志
            /// </summary>
            private readonly ILog _log;
    
            /// <summary>
            /// 日志
            /// </summary>
            private static FlashLogger _flashLog = new FlashLogger();
    
    
            private FlashLogger()
            {
                var configFile = new FileInfo(HttpContext.Current.Server.MapPath("~/log4net.config"));
                if (!configFile.Exists)
                {
                    throw new Exception("未配置log4net配置文件!");
                }
    
                // 设置日志配置文件路径
                XmlConfigurator.Configure(configFile);
    
                _que = new ConcurrentQueue<FlashLogMessage>();
                _mre = new ManualResetEvent(false);
                _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            }
    
            /// <summary>
            /// 实现单例
            /// </summary>
            /// <returns></returns>
            public static FlashLogger Instance()
            {
                return _flashLog;
            }
    
            /// <summary>
            /// 另一个线程记录日志,只在程序初始化时调用一次
            /// </summary>
            public void Register()
            {
                Thread t = new Thread(new ThreadStart(WriteLog));
                t.IsBackground = false;
                t.Start();
            }
    
            /// <summary>
            /// 从队列中写日志至磁盘
            /// </summary>
            private void WriteLog()
            {
                while (true)
                {
                    // 等待信号通知
                    _mre.WaitOne();
    
                    FlashLogMessage msg;
                    // 判断是否有内容需要如磁盘 从列队中获取内容,并删除列队中的内容
                    while (_que.Count > 0 && _que.TryDequeue(out msg))
                    {
                        // 判断日志等级,然后写日志
                        switch (msg.Level)
                        {
                            case FlashLogLevel.Debug:
                                _log.Debug(msg.Message, msg.Exception);
                                break;
                            case FlashLogLevel.Info:
                                _log.Info(msg.Message, msg.Exception);
                                break;
                            case FlashLogLevel.Error:
                                _log.Error(msg.Message, msg.Exception);
                                break;
                            case FlashLogLevel.Warn:
                                _log.Warn(msg.Message, msg.Exception);
                                break;
                            case FlashLogLevel.Fatal:
                                _log.Fatal(msg.Message, msg.Exception);
                                break;
                        }
                    }
    
                    // 重新设置信号
                    _mre.Reset();
                    Thread.Sleep(1);
                }
            }
    
    
            /// <summary>
            /// 写日志
            /// </summary>
            /// <param name="message">日志文本</param>
            /// <param name="level">等级</param>
            /// <param name="ex">Exception</param>
            public void EnqueueMessage(string message, FlashLogLevel level, Exception ex = null)
            {
                if ((level == FlashLogLevel.Debug && _log.IsDebugEnabled)
                 || (level == FlashLogLevel.Error && _log.IsErrorEnabled)
                 || (level == FlashLogLevel.Fatal && _log.IsFatalEnabled)
                 || (level == FlashLogLevel.Info && _log.IsInfoEnabled)
                 || (level == FlashLogLevel.Warn && _log.IsWarnEnabled))
                {
                    _que.Enqueue(new FlashLogMessage
                    {
                        Message = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff") + "]
    " + message,
                        Level = level,
                        Exception = ex
                    });
    
                    // 通知线程往磁盘中写日志
                    _mre.Set();
                }
            }
    
            public static void Debug(string msg, Exception ex = null)
            {
                Instance().EnqueueMessage(msg, FlashLogLevel.Debug, ex);
            }
    
            public static void Error(string msg, Exception ex = null)
            {
                Instance().EnqueueMessage(msg, FlashLogLevel.Error, ex);
            }
    
            public static void Fatal(string msg, Exception ex = null)
            {
                Instance().EnqueueMessage(msg, FlashLogLevel.Fatal, ex);
            }
    
            public static void Info(string msg, Exception ex = null)
            {
                Instance().EnqueueMessage(msg, FlashLogLevel.Info, ex);
            }
    
            public static void Warn(string msg, Exception ex = null)
            {
                Instance().EnqueueMessage(msg, FlashLogLevel.Warn, ex);
            }
    
        }
        /// <summary>
        /// 日志等级
        /// </summary>
        public enum FlashLogLevel
        {
            Debug,
            Info,
            Error,
            Warn,
            Fatal
        }
        /// <summary>
        /// 日志内容
        /// </summary>
        public class FlashLogMessage
        {
            public string Message { get; set; }
            public FlashLogLevel Level { get; set; }
            public Exception Exception { get; set; }
    
        }
    }
    View Code

    WebForm项目创建:

    1.需要引用线程日志类库 FlashLog

    2.添加log4net配置文件 log4net.config,实现了数据库及文件记录日志

    CREATE TABLE ErrorLog
    (
        dtDate DATETIME,
        sThread NVARCHAR(100),
        sLevel NVARCHAR(100),
        sLogger NVARCHAR(500),
        sMessage NVARCHAR(500), 
        sException NTEXT
    ) 
    View Code
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
          <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
      </configSections>
      <log4net debug="false">
        <!-- 将日志信息写入SQL Server数据库-->
        <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
          <bufferSize value="1" />
          <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
          <connectionString value="SERVER=服务器;DATABASE=数据库;UID=用户名;PWD=密码;Connect Timeout=15;" />
          <commandText value="INSERT INTO ErrorLog ([dtDate],[sThread],[sLevel],[sLogger],[sMessage],[sException]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" />
          <parameter>
            <parameterName value="@log_date" />
            <dbType value="DateTime" />
            <layout type="log4net.Layout.RawTimeStampLayout" />
          </parameter>
          <parameter>
            <parameterName value="@thread" />
            <dbType value="String" />
            <size value="100" />
            <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%t" />
            </layout>
          </parameter>
          <parameter>
            <parameterName value="@log_level" />
            <dbType value="String" />
            <size value="200" />
            <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%p" />
            </layout>
          </parameter>
          <parameter>
            <parameterName value="@logger" />
            <dbType value="String" />
            <size value="500" />
            <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%logger" />
            </layout>
          </parameter>
          <parameter>
            <parameterName value="@message" />
            <dbType value="String" />
            <size value="3000" />
            <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%m" />
            </layout>
          </parameter>
          <parameter>
            <parameterName value="@exception" />
            <dbType value="String" />
            <layout type="log4net.Layout.ExceptionLayout" />
          </parameter>
        </appender>
    
        <!-- 将日志信息写入到项目日志文件 -->
        <appender name="LogToFile" type="log4net.Appender.RollingFileAppender">
          <encoding value="utf-8" />
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <file value="Logs" />
          <datePattern value="yyyy.MM.dd'.log'" />
          <staticLogFileName value="false" />
          <appendToFile value="true" />
          <rollingStyle value="Composite" />
          <maxSizeRollBackups value="10" />
          <maximumFileSize value="50MB" />
          <layout type="log4net.Layout.PatternLayout">
            <ConversionPattern value="%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message %newline" />
          </layout>
        </appender>
        
        <!--设置根目录,添加appenders并设置默认日志等级 -->
        <root>
          <level value="All" />
          <appender-ref ref="ADONetAppender" />
          <appender-ref ref="LogToFile"/>
        </root>
      </log4net>
    
    </configuration>
    View Code

    3.需要添加全局应用程序类 Global.asax

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.SessionState;
    
    namespace LogWeb
    {
        public class Global : System.Web.HttpApplication
        {
            protected void Application_Start(object sender, EventArgs e)
            {
                // 在应用程序启动时运行的代码
                FlashLog.FlashLogger.Instance().Register();
            }
        }
    }
    View Code

    4.实例应用:访问无效域名时记录错误日志

                    try
                    {
                        string checkTonkenUrl = "http://url.abcde.com";
                        WebRequest wRequest = WebRequest.Create(checkTonkenUrl);
                        wRequest.Method = "GET";
                        wRequest.ContentType = "text/html;charset=UTF-8";
                        WebResponse wResponse = wRequest.GetResponse();
                        Stream stream = wResponse.GetResponseStream();
                        StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8);
                        string str = reader.ReadToEnd();   //url返回的值
                    }
                    catch (Exception ex)
                    {
                        FlashLogger.Error("Error", ex);
                    }
    View Code

    到此,log4net日志配置完成。

    相关程序源码可以点击此处下载:链接: https://pan.baidu.com/s/1bu29Ba9zxyAs-oAmdaSI-A 密码: upw2

    另外附上自己整理的.net Core WebAPI 应用log4net,大家可以看下源码:链接: https://pan.baidu.com/s/14wOIi1je0a02blM7_zlASg 密码: gd9b

  • 相关阅读:
    可爱的中国电信 请问我们的电脑还属于我们自己吗?
    了解客户的需求,写出的代码或许才是最优秀的............
    DELPHI DATASNAP 入门操作(3)简单的主从表的简单更新【含简单事务处理】
    用数组公式获取字符在字符串中最后出现的位置
    在ehlib的DBGridEh控件中使用过滤功能(可以不用 MemTableEh 控件 适用ehlib 5.2 ehlib 5.3)
    格式化json返回的时间
    ExtJs中使用Ajax赋值给全局变量异常解决方案
    java compiler level does not match the version of the installed java project facet (转)
    收集的资料(六)ASP.NET编程中的十大技巧
    收集的资料共享出来(五)Asp.Net 权限解决办法
  • 原文地址:https://www.cnblogs.com/wsk198726/p/9548293.html
Copyright © 2020-2023  润新知