最近在使用log4net的时候有一个简单的需求,就是自定义个格式化输出符。这个输出符是专门用来帮我记录下业务ID、业务类型的。好比,“businessID:328593,businessType: orderID”。相似这样的输出日志。这些日志会被elk agent提取送到日志中心ES中,用来进行辅助排障。app
简单的看了下log4net的PatternLayout和PatternConverter两个对象的做用,实现起来也是很是方便的。log4net有一组global的PatternLayout,这些全局的格式化对象是默认构造的时候就存在了,咱们只须要提供对咱们来讲特殊场景的实现便可。ide
你所使用的全部常规的格式化输出都在全局的注册了。咱们来实现本身的特殊用途的PatternLayout和PatternConverter,除此以外你还须要一个日志信息的载体对象,这里我使用BusinessIDLog类来存放。this
using System.IO; using log4net.Layout.Pattern; using log4net.Core; namespace log4net.appender.demo { public class BusinessIDPatternConvert : PatternLayoutConverter { protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) { var businessID = loggingEvent.MessageObject as BusinessIDLog; if (businessID == null) return; writer.Write(string.Format(" businessID:{0},businessType:{1}", businessID.ID,businessID.BusinessType)); } } }
在log4net里面,每个特殊的格式符都是一个converter。明白了这个就很容易理解为何配置一个格式化的字符串就能够获得本身的想要的文本。spa
namespace log4net.appender.demo { public class BusinessIDPatternLayout : log4net.Layout.PatternLayout { public BusinessIDPatternLayout() { this.AddConverter("businessID", typeof(BusinessIDPatternConvert)); } } }
实现一个PatternLayout就能够接管全部的格式化。这里的this.AddConverter,是将咱们的businessID的Converter放入当前instance的做用域内。它不是全局的,而是当前实例局部的。日志
而后在你的log4net的配置文件中配置你自定义的PatternLayout。orm
<!--日志格式-->
<layout type="log4net.appender.demo.BusinessIDPatternLayout">
<conversionPattern value="%date [%t]%-5level %c [%businessID] %n"/>
</layout>对象
用户使用的时候须要传入BusinessIDLog对象,要否则咱们的Converter对象没法获取到数据对象。blog
namespace log4net.appender.demo { class Program { static void Main(string[] args) { var loger = LogManager.GetLogger(typeof(Program)); loger.Info(new BusinessIDLog() { ID = "25434535", BusinessType = "orderID" }); } } }
这样就OK了。作用域
是否是很方便。字符串