項目開發中,咱們或多或少會使用諸如NLog,Log4Net,Kafka+ELK等等日誌套件;git
基於關注點分離原則,業務開發的時候不該該關注日誌具體實現;而且後續能方便切換其餘日誌套件;github
這裏先實現基於文件的日誌服務,在下一篇將實現基於Kafka+ELK;c#
具體源碼:MasterChiefapp
Nuget:Install-Package MasterChief.DotNet.Core.Logdebug
歡迎Star,歡迎Issues;日誌
/// <summary> /// 日誌記錄接口 /// </summary> public interface ILogService { #region Methods /// <summary> /// Debug記錄 /// </summary> /// <param name="message">日誌信息</param> void Debug(string message); /// <summary> /// Debug記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> void Debug(string message, Exception ex); /// <summary> /// Error記錄 /// </summary> /// <param name="message">日誌信息</param> void Error(string message); /// <summary> /// Error記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> void Error(string message, Exception ex); /// <summary> /// Fatal記錄 /// </summary> /// <param name="message">日誌信息</param> void Fatal(string message); /// <summary> /// Fatal記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> void Fatal(string message, Exception ex); /// <summary> /// Info記錄 /// </summary> /// <param name="message">日誌信息</param> void Info(string message); /// <summary> /// Info記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> void Info(string message, Exception ex); /// <summary> /// Warn記錄 /// </summary> /// <param name="message">日誌信息</param> void Warn(string message); /// <summary> /// Warn記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> void Warn(string message, Exception ex); #endregion Methods }
/// <summary> /// 基於Log4Net的文件日誌記錄 /// </summary> public sealed class FileLogService : ILogService { #region Constructors static FileLogService() { DebugLogger = LogManager.GetLogger(DebugLoggerName); InfoLogger = LogManager.GetLogger(InfoLoggerName); WarnLogger = LogManager.GetLogger(WarnLoggerName); ErrorLogger = LogManager.GetLogger(ErrorLoggerName); FatalLogger = LogManager.GetLogger(FatalLoggerName); } #endregion Constructors #region Fields /// <summary> /// The debug logger name /// </summary> public const string DebugLoggerName = "DEBUG_FileLogger"; /// <summary> /// The error logger name /// </summary> public const string ErrorLoggerName = "ERROR_FileLogger"; /// <summary> /// The fatal logger name /// </summary> public const string FatalLoggerName = "FATAL_FileLogger"; /// <summary> /// The information logger name /// </summary> public const string InfoLoggerName = "INFO_FileLogger"; /// <summary> /// The warn logger name /// </summary> public const string WarnLoggerName = "WARN_FileLogger"; /// <summary> /// The debug logger /// </summary> public static readonly ILog DebugLogger; /// <summary> /// The error logger /// </summary> public static readonly ILog ErrorLogger; /// <summary> /// The fatal logger /// </summary> public static readonly ILog FatalLogger; /// <summary> /// The information logger /// </summary> public static readonly ILog InfoLogger; /// <summary> /// The warn logger /// </summary> public static readonly ILog WarnLogger; #endregion Fields #region Methods /// <summary> /// Debug記錄 /// </summary> /// <param name="message">日誌信息</param> public void Debug(string message) { if (DebugLogger.IsDebugEnabled) DebugLogger.Debug(message); } /// <summary> /// Debug記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> public void Debug(string message, Exception ex) { if (DebugLogger.IsDebugEnabled) DebugLogger.Debug(message, ex); } /// <summary> /// Error記錄 /// </summary> /// <param name="message">日誌信息</param> public void Error(string message) { if (ErrorLogger.IsErrorEnabled) ErrorLogger.Error(message); } /// <summary> /// Error記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> public void Error(string message, Exception ex) { if (ErrorLogger.IsErrorEnabled) ErrorLogger.Error(message, ex); } /// <summary> /// Fatal記錄 /// </summary> /// <param name="message">日誌信息</param> public void Fatal(string message) { if (FatalLogger.IsFatalEnabled) FatalLogger.Fatal(message); } /// <summary> /// Fatal記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> public void Fatal(string message, Exception ex) { if (FatalLogger.IsFatalEnabled) FatalLogger.Fatal(message, ex); } /// <summary> /// Info記錄 /// </summary> /// <param name="message">日誌信息</param> public void Info(string message) { if (InfoLogger.IsInfoEnabled) InfoLogger.Info(message); } /// <summary> /// Info記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> public void Info(string message, Exception ex) { if (InfoLogger.IsInfoEnabled) InfoLogger.Info(message, ex); } /// <summary> /// Warn記錄 /// </summary> /// <param name="message">日誌信息</param> public void Warn(string message) { if (WarnLogger.IsWarnEnabled) WarnLogger.Warn(message); } /// <summary> /// Warn記錄 /// </summary> /// <param name="message">日誌信息</param> /// <param name="ex">異常信息</param> public void Warn(string message, Exception ex) { if (WarnLogger.IsWarnEnabled) WarnLogger.Warn(message, ex); } #endregion Methods }
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler" /> </configSections> <log4net> <!-- FileLogger --> <logger name="FATAL_FileLogger"> <level value="ALL" /> <appender-ref ref="FATAL_FileAppender" /> </logger> <logger name="ERROR_FileLogger"> <level value="ALL" /> <appender-ref ref="ERROR_FileAppender" /> </logger> <logger name="WARN_FileLogger"> <level value="ALL" /> <appender-ref ref="WARN_FileAppender" /> </logger> <logger name="INFO_FileLogger"> <level value="ALL" /> <appender-ref ref="INFO_FileAppender" /> </logger> <logger name="DEBUG_FileLogger"> <level value="ALL" /> <appender-ref ref="DEBUG_FileAppender" /> </logger> <!-- AdoNetLogger --> <!--<logger name="AdoNetLogger"> <level value="ALL" /> <appender-ref ref="AdoNetAppender" /> </logger>--> <!-- ConsoleLogger --> <logger name="ConsoleLogger"> <level value="ALL" /> <appender-ref ref="ColoredConsoleAppender" /> </logger> <!--使用Rolling方式記錄日誌按照日來記錄日誌--> <appender name="FATAL_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\FATAL\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="ERROR_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\ERROR\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="WARN_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\WARN\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="INFO_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\INFO\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="DEBUG_FileAppender" type="log4net.Appender.RollingFileAppender"> <!--文件名,能夠相對路徑,也能夠絕對路徑,這裏只給定了文件夾--> <file value=".\log\\DEBUG\\" /> <!--是否增長文件--> <appendToFile value="true" /> <maxSizeRollBackups value="5" /> <!--日誌追加類型,Date爲按日期增長文件,Size爲按大小--> <rollingStyle value="Date" /> <!--最小鎖定模型以容許多個進程能夠寫入同一個文件,解決文件獨佔問題--> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <!--最大文件大小--> <maximumFileSize value="10MB" /> <!--文件命名格式,非日期參數化要進行轉義,如自定義文件後綴--> <datePattern value="yyyyMM\\yyyy-MM-dd".log"" /> <!--是否固定文件名--> <staticLogFileName value="false" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level %newline事件來源:%logger%newline日誌內容:%message%newline" /> </layout> </appender> <!--使用AdoNetAppender方式記錄日誌按照日來記錄日誌--> <!--<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> <bufferSize value="1" /> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <connectionString value="DATABASE=Sample;SERVER=.\SQLEXPRESS;UID=sa;PWD=sasa;Connect Timeout=15;" /> <commandText value="INSERT INTO [Log4Net] ([Date],[Host],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@log_date, @host, @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="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%thread" /> </layout> </parameter> <parameter> <parameterName value="@host" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%property{log4net:HostName}" /> </layout> </parameter> <parameter> <parameterName value="@log_level" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%level" /> </layout> </parameter> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter> <parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message" /> </layout> </parameter> <parameter> <parameterName value="@exception" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.ExceptionLayout" /> </parameter> </appender>--> <!--使用ConsoleAppender方式記錄日誌按照日來記錄日誌--> <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> <mapping> <level value="INFO" /> <foreColor value="White, HighIntensity" /> <backColor value="Green" /> </mapping> <mapping> <level value="DEBUG" /> <foreColor value="White, HighIntensity" /> <backColor value="Blue" /> </mapping> <mapping> <level value="WARN" /> <foreColor value="Yellow, HighIntensity" /> <backColor value="Purple" /> </mapping> <mapping> <level value="ERROR" /> <foreColor value="Yellow, HighIntensity" /> <backColor value="Red" /> </mapping> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="---------------------------------------------------%newline發生時間:%date %newline事件級別:%-5level%newline事件來源:%logger%newline事件行號:%line%newline日誌內容:%message%newline" /> </layout> </appender> <appender name="UdpAppender" type="log4net.Appender.UdpAppender"> <remoteAddress value="127.0.0.1" /> <remotePort value="7071" /> <layout type="log4net.Layout.XmlLayoutSchemaLog4j" /> </appender> <root> <appender-ref ref="UdpAppender" /> </root> </log4net> </configuration>
private IKernel _kernel = null; private ILogService _logService = null; [TestInitialize] public void SetUp() { _kernel = new StandardKernel(new LogModule()); Assert.IsNotNull(_kernel); _logService = _kernel.Get<ILogService>(); } [TestMethod()] public void DebugTest() { _logService.Debug("DebugTest"); }