Nlog、Log4Net 的一个小扩展(增加自定义LEVEL)

匿名 (未验证) 提交于 2019-12-02 22:10:10

因公司ELK监控分析日志的需要,需要区分进程运行状态日志以及错误日志,以便能够根据日志级别(level)进行不同策略的预警,而现有的Nlog、Log4Net都没有Process这样的level,故针对这两个日志框架做了一些扩展,实现了自定义PROCESS LEVEL,因代码不多,故直接贴代码,有疑问的或好的建议可以下方评论留言交流,谢谢!

NlogExtend.cs:(Nlog的扩展)文件代码内容如下:

    public static class NlogExtend     {         public static void Process(this ILogger logger, string message = "RUNNING")         {             var logEventInfo = new LogEventInfo(LogLevel.Trace, logger.Name, message);             logEventInfo.Properties["custLevel"] = Tuple.Create(9, "Process");             logger.Log(logEventInfo);         }     }      [LayoutRenderer("levelx")]     public class LevelExLayoutRenderer : LevelLayoutRenderer     {          protected override void Append(StringBuilder builder, LogEventInfo logEvent)         {             if (logEvent.Level == LogLevel.Trace && logEvent.Properties.ContainsKey("custLevel"))             {                 var custLevel = logEvent.Properties["custLevel"] as Tuple<int, string>;                 if (custLevel == null)                 {                     throw new InvalidCastException("Invalid Cast Tuple<int, string>");                 }                  switch (this.Format)                 {                     case LevelFormat.Name:                         builder.Append(custLevel.Item2);                         break;                     case LevelFormat.FirstCharacter:                         builder.Append(custLevel.Item2[0]);                         break;                     case LevelFormat.Ordinal:                         builder.Append(custLevel.Item1);                         break;                 }             }             else             {                 base.Append(builder, logEvent);             }         }     } 

用法如下:

config文件:(用levelx取代原来的level即可)

  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">     <targets async="true">       <target name="file" xsi:type="File" fileName="${basedir}/Logs/${shortdate}.log" layout="[${date:format=yyyy-MM-dd HH\:mm\:ss.fff}]  ${levelx:uppercase=true}  ${processname}  Thread-${threadid}  ${processname}  ${message}  Stack:${stacktrace}" archiveFileName="${basedir}/Logs/Archives/log.{#}.log" archiveEvery="Day" archiveNumbering="DateAndSequence" archiveAboveSize="10485760" archiveDateFormat="yyyyMMdd" maxArchiveFiles="30" concurrentWrites="true" keepFileOpen="false" />     </targets>     <rules>       <logger name="*" minlevel="Trace" writeTo="file" />     </rules>   </nlog>代

代码中输出PROCESS日志:

    /// <summary>     /// 基于NLOG框架的日志工具类     /// </summary>     public static class LogUtil     {         private readonly static ILogger logger = null;          static LogUtil()         {             NLog.Config.ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("levelx", typeof(WMSNWPP.LevelExLayoutRenderer));//注册自定义的布局生成器,这样config文件中的levelx才能生效             logger = LogManager.GetCurrentClassLogger();         }          public static void Info(string msg)         {             try             {                 logger.Info(msg);             }             catch             { }         }          public static void Error(Exception ex)         {             try             {                 logger.Error(ex);             }             catch             { }         }           public static void Error(string msg)         {             try             {                 Log(LogLevel.Error, msg);             }             catch             { }         }          public static void Warn(string msg)         {             try             {                 logger.Warn(msg);             }             catch             { }         }          public static void Log(LogLevel level, string msg)         {             try             {                 logger.Log(level, msg);             }             catch             { }         }          public static void Process(string message = "RUNNING")         {             try             {                 logger.Process(message);             }             catch             { }         }      }     //调用写Process进程日志 LogUtil.Process(); 

Log4NetExtend.cs:(Nlog的扩展)文件代码内容如下:

    /// <summary>     /// Log4Net扩展(扩展一个Process的LOG LEVEL,以便定时输出进程运行日志)     /// Author:Zuowenjun     /// Date:2018-4-25     /// </summary>     public static class Log4NetExtend     {         public static readonly log4net.Core.Level ProcessLevel = new log4net.Core.Level(10001, "PROCESS");          private static void AddProcessLevel(log4net.ILog log)         {             if (!log.Logger.Repository.LevelMap.AllLevels.Contains(ProcessLevel))             {                 log.Logger.Repository.LevelMap.Add(ProcessLevel);             }         }          public static void Process(this log4net.ILog log, string message)         {             AddProcessLevel(log);             log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType,                 ProcessLevel, message, null);         }          public static void ProcessFormat(this log4net.ILog log, string message, params object[] args)         {             AddProcessLevel(log);             string formattedMessage = string.Format(message, args);             log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType,                 ProcessLevel, formattedMessage, null);         }     }      /// <summary>     /// 输出当前进程名转换器     /// </summary>     public class ProcessPatternConvert : PatternLayoutConverter     {         private readonly static string processName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;         protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent)         {             writer.Write(processName);//输出当前进程名         }     }      public class CustomPatternLayout : log4net.Layout.PatternLayout     {         public CustomPatternLayout()         {             this.AddConverter("proc", typeof(ProcessPatternConvert));         }     } 

 log4net相对于Nlog好一点,可以通过New Level的构造函数自定义一个新的level实例,但也不好的地方,就是没有默认的显示进程名字,故需要自定义ProcessPatternConvert、CustomPatternLayout,通过CustomPatternLayout的构造函数把ProcessPatternConvert布局转换器类添加到布局转换器集合,这样config中就可以配置proc,以便输出进程名,config配置如下:

  <log4net>     <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">       <!--日志路径-->       <param name="File" value="Logs\" />       <!--是否是向文件中追加日志-->       <param name="AppendToFile" value="true" />       <!--log保留天数-->       <param name="MaxSizeRollBackups" value="30" />       <!--日志文件名是否是固定不变的-->       <param name="StaticLogFileName" value="false" />       <!--日志文件名格式为:2008-08-31.log-->       <param name="DatePattern" value="yyyyMMdd".log"" />       <!--当日志文件达到10MB,则产生新的日志文件-->       <maximumFileSize value="10MB"/>       <!--日志根据日期\文件大小滚动-->       <param name="RollingStyle" value="Composite" />       <!--最小锁定模型以允许多个进程可以写入同一个文件-->       <param name="lockingModel" type="log4net.Appender.FileAppender+MinimalLock" />       <layout type="KyAutoTimingExecSystem.CommonLib.CustomPatternLayout">         <param name="Header" value="[Begin] " />         <param name="Footer" value="[End] " />         <param name="ConversionPattern" value="[%d]  %5p  %proc Thread-%t  %m%n  Stack:%stacktrace{10}%n" />       </layout>     </appender>     <root>       <level value="ALL" />       <appender-ref ref="RollingLogFileAppender" />     </root>   </log4net> 

 代码使用如下:

public static ILog Logger = LogManager.GetLogger("KyAutoTimingExecSystem"); Logger.Process(msg); 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!