• 使用log4net记录本地日志及自定义扩展输出


    简单介绍一下log4net的主要组成,详细说明可以参考https://blog.csdn.net/binnygoal/article/details/79557746

    1.Logger

    Logger是直接和应用程序交互的组件,是负责日志的记录者,可以同时存在多个Logger,然后由它引用的Appender记录到指定的媒介,并由Layout控制输出格式。

    2.Appender

    Appender用来定义日志的输出方式,即提供记录介质,如记录到数据库,记录到本地文件,输出到控制台等等。

    3.Layout

    Layout用于控制Appender的输出格式(格式化记录数据),可以是线性的也可以是XML。

    4.Filter

    Filter负责记录筛选,可以过滤掉Appender输出的内容。

    总体流程:Logger发出记录信息,Appender接到信息,根据内部的Layout配置对记录信息格式化,然后根据Filter对记录信息进行筛选,最后将其记录到指定介质中。

    简单配置log4net

    第一步:在项目中添加log4net.dll的引用;

    第二步:配置log4net.config文件;

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
      </configSections>
      <log4net>
        <logger name="ErrorLogger">
          <level value="WARN" />
          <appender-ref ref="ErrorAppender" />
        </logger>
        <logger name="DebugLogger">
          <level value="DEBUG" />
          <appender-ref ref="DebugAppender" />      
        </logger>    
        <logger name="InfoLogger">
          <level value="INFO" />
          <appender-ref ref="InfoAppender" />
        </logger>    
        <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
          <!--日志文件路径,文件夹不存在则新建 -->
          <file value="D://THS//logs//" />
          <!--是否追加到文件-->
          <appendToFile value="true" />
          <!--记录日志写入文件时,不锁定文本文件,防止多线程时不能写Log,官方说线程非安全-->
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <!--最多产生的日志文件数,超过则只保留最新的n+1个-->
          <maxSizeRollBackups value="1" />
          <!--每个文件的大小,只在混合方式与文件大小方式下使用,超出大小后在所有文件名后自动增加正整数重新命名,数字最大的最早写入,没带数字最晚写入-->
          <maximumFileSize value="256MB" />
          <!--是否只写到一个文件中-->
          <staticLogFileName value="false"/>
          <!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
          <rollingStyle value="Composite" />
          <!--是否保存日志文件的扩展名-->
          <preserveLogFileNameExtension value="true" />
          <!--按日期产生文件夹,文件名固定。注意&quot; 的位置-->      
          <datePattern value="yyyy-MM-dd/&quot;SysInfo.log&quot;" />
          <!--记录的格式。一般用log4net.Layout.PatternLayout布局-->
          <!--此处用继承了log4net.Layout.PatternLayout的自定义布局,LogTest.Log为命名空间。%Property{LineLocation}、%Property{Method}等是自定义的输出-->
          <layout type="LogTest.Log.Z_PatternLayout">
            <conversionPattern value="日志时间:%Property{Time} %n记录方法:[%thread]%Property{Method} Line:%Property{LineLocation} %n日志信息:%Property{Message} %n%n" />
          </layout>
          <!--过滤设置,LevelRangeFilter为使用的过滤器。-->
          <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="INFO" />
            <param name="LevelMax" value="INFO" />
          </filter>      
        </appender>    
        <appender name="DebugAppender" type="log4net.Appender.RollingFileAppender">
          <file value="D://THS//logs//" />
          <appendToFile value="true" />
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <maxSizeRollBackups value="30" />
          <staticLogFileName value="false"/>
          <rollingStyle value="Date" />
          <preserveLogFileNameExtension value="true" />
          <datePattern value="yyyy-MM-dd/&quot;SysDebug.log&quot;" />
          <layout type="LogTest.Log.Z_PatternLayout">
            <conversionPattern value="日志时间:%Property{Time} %n记录方法:[%thread]%Property{Method} Line:%Property{LineLocation} %n日志信息:%Property{Message} %n%n" />
          </layout>
          <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="DEBUG" />
            <param name="LevelMax" value="DEBUG" />
          </filter>
        </appender>   
        <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
          <file value="D://THS//logs//" />
          <appendToFile value="true" />
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <maxSizeRollBackups value="30" />
          <staticLogFileName value="false"/>
          <rollingStyle value="Date" />
          <preserveLogFileNameExtension value="true" />
          <datePattern value="yyyy-MM-dd/&quot;SysError.log&quot;" />
          <layout type="LogTest.Log.Z_PatternLayout">
            <conversionPattern value="日志时间:%Property{Time} %n日志级别:%-5level %n记录方法:[%thread]%Property{Method} Line:%Property{LineLocation} %n日志信息:%Property{Message} %n异常信息:%exception %n%n" />
          </layout>
          <filter type="log4net.Filter.LevelRangeFilter">
            <param name="LevelMin" value="WARN" />
            <param name="LevelMax" value="FATAL" />
          </filter>
        </appender>  
      </log4net>
    </configuration>

     注意,注意,注意:修改log4net.config文件属性“复制到输出目录”为“始终复制”,否则不会生成日志文件夹;

    第三步:如果是使用自动以配置文件,则在AssemblyInfo.cs中添加关联配置文件代码

    // 使用配置文件log4net.config,监视改变
    [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config", Watch = true)]

    如果是在默认App.config文件中配置log4net,则可以直接在Program.cs中的Main方法中添加:

    log4net.Config.XmlConfigurator.Configure();

    第四步:自定义扩展输出,通过继承log4net.Layout.PatternLayout类,使用log4net.Core.LoggingEvent类的方法得到了要输出的LogEntity类的名称,然后通过反射得到各个属性的值,使用PatternLayout类AddConverter方法传入得到的值。注意Appender中的Layout type要引用用到的类的命名空间以及类名。

    1.创建LogEntity实体类(自定义输出属性)

    namespace LogTest.Log
    {
        public class Z_LogEntity
        {
            /// <summary>
            /// 引发日志事件的行号
            /// </summary>
            public string LineLocation { get; set; }
    
            /// <summary>
            /// 应用程序提供给日志事件的消息
            /// </summary>
            public string Message { get; set; }
    
            /// <summary>
            /// 引发日志事件的方法(包括类名和方法名)
            /// </summary>
            public string Method { get; set; }
    
            /// <summary>
            /// 引发日志事件的时间(格式化)
            /// </summary>
            public string Time { get; set; }
        }
    }

    2.继承PatternLayoutConvert重写转换器

    using log4net.Core;
    using log4net.Layout.Pattern;
    using System.IO;
    using System.Reflection;
    
    namespace LogTest.Log
    {
        public class Z_PatternConvert : PatternLayoutConverter
        {
            protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
            {
                if (Option != null)
                    // 写入指定键的值
                    WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent));
                else
                    // 写入所有关键值对
                    WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties());
            }
    
            /// <summary>
            /// 通过反射获取传入的日志对象的某个属性
            /// </summary>
            private object LookupProperty(string property, LoggingEvent loggingEvent)
            {
                object propertyValue = string.Empty;
                PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);
    
                if (propertyInfo != null)
                    propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);
    
                return propertyValue;
            }
        }
    }

    3.继承PatternLayout,添加转换器到实例中

    using log4net.Layout;
    
    namespace LogTest.Log
    {
        public class Z_PatternLayout : PatternLayout
        {
            public Z_PatternLayout()
            {
                this.AddConverter("Property", typeof(Z_PatternConvert));
            }
        }
    }

    第五步:编写LogHelper类

    using System;
    using System.Diagnostics;
    using System.Runtime.CompilerServices;
    
    namespace LogTest.Log
    {
        public class LogHelper
        {
            /// <summary>
            ///  静态只读实例化对象DebugLogger
            /// </summary>
            public static readonly log4net.ILog DebugLog = log4net.LogManager.GetLogger("DebugLogger");
    
            /// <summary>
            ///  静态只读实例化对象ErrorLogger
            /// </summary>
            public static readonly log4net.ILog ErrorLog = log4net.LogManager.GetLogger("ErrorLogger");
    
            /// <summary>
            /// 静态只读实例化对象InfoLogger
            /// </summary>
            public static readonly log4net.ILog InfoLog = log4net.LogManager.GetLogger("InfoLogger");
    
            private static Z_LogEntity logEntity = new Z_LogEntity();
    
            public static Z_LogEntity BuildLogEntity(string message, [CallerLineNumber] int lineNum = 0, [CallerMemberName] string method = "")
            {
                logEntity.Time = DateTime.Now.ToString("HH:mm:ss:fff");
                logEntity.Message = message;
                logEntity.LineLocation = lineNum.ToString();
                logEntity.Method = (new StackTrace()).GetFrame(1).GetMethod().ReflectedType.Name + "." + method;
                return logEntity;
            }
    
            public static void WriteInfo(Z_LogEntity logEntity)
            {
                try
                {
                    if (InfoLog.IsInfoEnabled)
                    {
                        InfoLog.Info(logEntity);
                    }
                }
                catch { }
            }
    
            public static void WriteDebug(Z_LogEntity logEntity)
            {
                try
                {
                    if (DebugLog.IsDebugEnabled)
                    {
                        DebugLog.Debug(logEntity);
                    }
                }
                catch { }
            }
    
            public static void WriteWarn(Z_LogEntity logEntity)
            {
                try
                {
                    if (ErrorLog.IsWarnEnabled)
                    {
                        ErrorLog.Warn(logEntity);
                    }
                }
                catch { }
            }
    
            public static void WriteWarn(Z_LogEntity logEntity, Exception ex)
            {
                try
                {
                    if (ErrorLog.IsWarnEnabled)
                    {
                        ErrorLog.Warn(logEntity, ex);
                    }
                }
                catch { }
            }
    
            public static void WriteError(Z_LogEntity logEntity)
            {
                try
                {
                    if (ErrorLog.IsErrorEnabled)
                    {
                        ErrorLog.Error(logEntity);
                    }
                }
                catch { }
            }
    
            public static void WriteError(Z_LogEntity logEntity, Exception ex)
            {
                try
                {
                    if (ErrorLog.IsErrorEnabled)
                    {
                        ErrorLog.Error(logEntity, ex);
                    }
                }
                catch { }
            }
    
            public static void WriteFatal(Z_LogEntity logEntity)
            {
                try
                {
                    if (ErrorLog.IsFatalEnabled)
                    {
                        ErrorLog.Fatal(logEntity);
                    }
                }
                catch { }
            }
    
            public static void WriteFatal(Z_LogEntity logEntity, Exception ex)
            {
                try
                {
                    if (ErrorLog.IsFatalEnabled)
                    {
                        ErrorLog.Fatal(logEntity, ex);
                    }
                }
                catch { }
            }
        }
    }

    第六步:程序中使用

    // 记录Info级别数据
    LogHelper.WriteInfo(LogHelper.BuildLogEntity("程序运行记录写入!"));
    
    // 记录Debug级别数据
    LogHelper.WriteDebug(LogHelper.BuildLogEntity("调试信息数据写入!"));
    
    // 记录Warn级别数据
    LogHelper.WriteWarn(LogHelper.BuildLogEntity("警告数据写入!"),new Exception("对应的错误信息!"));
    
    // 记录Error级别数据
     LogHelper.WriteError(LogHelper.BuildLogEntity("一般错误数据写入!"), new Exception("对应的错误信息!"));
    
    // 记录Fatal级别数据
    LogHelper.WriteFatal(LogHelper.BuildLogEntity("致命错误数据写入!"), new Exception("对应的错误信息!"));
  • 相关阅读:
    Lily.Core.FileDataProvider文件管理使用范例。
    CruiseControl.NET,Nant持续集成(1)
    如何为当前进程设置环境变量?
    unix时间戳与datetime的转换函数
    Mac 平台下功能强大的Shimo软件使用指南
    如何解决源码包安装时的依赖性问题
    《Linux企业应用案例精解》一书配套视频发布
    ZoneMinder配置与使用
    网站优化IIS7下静态文件的优化
    WIN7常用功能的介绍
  • 原文地址:https://www.cnblogs.com/zhengzc/p/11138566.html
Copyright © 2020-2023  润新知