项目开发中,咱们或多或少会使用诸如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"); }