使用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("對應的錯誤信息!"));

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM