最近在使用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了。作用域
是否是很方便。字符串