欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-13 23:36:01
我的项目结构如下图: 日志帮助类库需要log4net包:工具—NuGet包管理器—管理解决方案NuGet程序包 线程日志帮助类 FlashLogger.cs 代码 using System; using System.Collections.Concurrent; using System.Coll ......

我的项目结构如下图:

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

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

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

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

WebForm应用log4net记录错误日志——使用线程列队写入
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") + "]\r\n" + 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,实现了数据库及文件记录日志

WebForm应用log4net记录错误日志——使用线程列队写入
create table errorlog
(
    dtdate datetime,
    sthread nvarchar(100),
    slevel nvarchar(100),
    slogger nvarchar(500),
    smessage nvarchar(500), 
    sexception ntext
) 
view code
WebForm应用log4net记录错误日志——使用线程列队写入
<?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

WebForm应用log4net记录错误日志——使用线程列队写入
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.实例应用:访问无效域名时记录错误日志

WebForm应用log4net记录错误日志——使用线程列队写入
                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

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

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

到此,log4net日志配置完成。

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

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