zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    WC2021 游记
    TC11054
    P5904
    CF741D
    CF1467 题解
    [CTSC2008]网络管理 [树剖+整体二分]
    [HNOI2015]接水果[整体二分]
    [SDOI2010]粟粟的书架 [主席树]
    整体二分的一些见解[整体二分学习笔记]
    P2710 数列[fhq treap]
  • 原文地址:https://www.cnblogs.com/wsk198726/p/9548293.html
Copyright © 2011-2022 走看看