Nlog、Log4Net 的一个小扩展(增加自定义LEVEL)
因公司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);
}
}
}
因Nlog的LogLevel不允许直接通过继承或New 构造函数来创建一个新的Level,故只能采取把自定义的level写入到LogEventInfo的扩展属性中,然后再自定义一个继承自LevelLayoutRenderer的布局生成器类,就OK了
用法如下:
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();
说完了Nlog,再来说一下Log4Net的扩展实现。
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);
好了,就介绍到这里,没有什么高大上的技术分享,只是一点对框架扩展的总结,举一反三,可以扩展其它方面。
Nlog、Log4Net 的一个小扩展(增加自定义LEVEL)的更多相关文章
- jquery的一个小扩展,读取URL里的参数
/* *扩展jquery的功能: *读取url中参数的功能,方法的参数是要获取的URL里键; *使用前要先导入jquery.js文件. * */ (function ($) { $.getUrlPar ...
- Log4net的一个小例子
最近想学习下log4net,写了个很简短的使用例子.用少的代码,可以保证程序运行起来. 配置文件: <configSections> <section name="log4 ...
- dapper的一个小扩展以支持dataset
废话不多,直接上方法 public static DataSet ExecuteDataSet(this IDbConnection cnn, IDbDataAdapter adapter, stri ...
- 【视频】从零开始编写第一个PHP扩展
Rango会讲解在Linux下从零开始写一个PHP扩展,并编译安装到PHP里,一直到执行扩展中的函数.包含的内容有: 为什么要开发PHP扩展 ext_skel工具的使用 修改config.m4 php ...
- android小知识之自定义通知(toast)
Toast是较为熟悉的通知,但默认方式比较单调,可以根据自己的需求自定义,在统一UI风格的时候可以单独拿出来做一个工具类来使用. 下面我在Fragment中定义的一个按键弹出自定义Toast,在Act ...
- 在WPS绿色版中增加自定义皮肤
在WPS绿色版中增加自定义皮肤小俊的博客:http://xiaojun911.com/WPS绿色版:http://xiaojun911.com/xiazai/469.html小俊精简的WPS2016 ...
- gnome3增加自定义程序快捷方式
gnome3增加自定义程序快捷方式 1. 安装alacarte 在命令行输入下列命令安装alacarte程序 yum -y install alacarte 安装完毕后,在命令行输入下 ...
- 我的第一个php扩展
一.进入php源码包,找到ext文件夹 cd /owndata/software/php-5.4.13/ext 文件夹下放的都是php的相关扩展模块 二.生成自己的扩展文件夹和相关文件 php支持开发 ...
- Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架
本文首先介绍了什么是Apache Thrift,接着介绍了Thrift的安装部署及如何利用Thrift来实现一个简单的RPC应用,并简单的探究了一下Thrift的内部实现原理,最后给出一个基于Thri ...
随机推荐
- 一. 优化小程序自身的Storage
小程序中的存储只有 Storage ,特性如下: 上限为 10MB 以用户纬度隔离,同一个设备,A 无法访问 B 用户的数据. 持久缓存,只有在用户关掉小程序才会删除,如果空间不足,会进行 LRU , ...
- 打包java程序生成exe
打包java程序生成exe 目标 我们知道c++的控制台程序编译运行以后就会生成一个exe可执行文件,在电脑上可以直接双击运行,但是java是跨平台的语言,编译运行以后的字节码文件.class是和平台 ...
- NOIP-接水问题
题目描述 学校里有一个水房,水房里一共装有m个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1. 现在有n名同学准备接水,他们的初始接水顺序已经确定.将这些同学按接水顺序从1到n编号,i号同学 ...
- 使用POST下载文件
一直以来,JS都没有比较好的可以直接处理二进制的方法.而Blob的存在,允许我们可以通过JS直接操作二进制数据.一.下载util.fetchDownload= function (opt,data) ...
- Go语言基础之结构体
Go语言基础之结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 类型别名和自定义类型 自定义类型 在G ...
- js数组和对象相等判断、拷贝详解(结合几个现象讲解引用数据类型的趣事)
序言 最近遇到几个js引用数据类型造成的bug,今天结合bug详细分析一下,避免以后再犯,也希望能帮大家提个醒,强化js基本功. 目录 1.浅拷贝.深拷贝,解决变量赋值相互影响问题 2.判断2个数组. ...
- python爬虫第三天
DebugLog实战 有时候我们需要在程序运行时,一边运行一边打印调试日志.此时需要开启DebugLog. 如何开启: 首先将debugleve ...
- js与jq基础记录
1.在js传递参数中含加号(+)的处理方式: 只需要把js中传过去的+号替换成base64 编码 %2B:encodeURI(str).replace(/\+/g,'%2B'). 2.随机产生8位随机 ...
- HBuilder git合作-代码同步
1. 以下场景的操作都是同样的,包括:新建了文件.删除了文件.独占式修改文件(即不存在多人同时修改一个文件的情况) 提交 项目修改完成后,选中项目,右键Team->Commit 一般是选择Com ...
- B4 and After: Managing Hierarchy, Partitioning, and Asymmetry for Availability and Scale in Google’s Sofware-Defined WAN
B4及之后:为谷歌软件定义WAN的可用性和扩展管理层次化.划分和不对称 本文为SIGCOMM 2018会议论文,由谷歌提供. 笔者翻译了该论文.由于时间仓促,且笔者英文能力有限,错误之处在所难免:欢迎 ...