【问题标题】:Can log4net output Json?log4net可以输出Json吗?
【发布时间】:2017-01-29 18:53:22
【问题描述】:

我见过一些 log4net 的扩展,它们声称为日志文件创建 json,但格式永远不是有效的 json,这意味着集合不是在数组中,也不是逗号分隔的。是我用错了还是没有办法将log4net与json一起使用?

<appender name="SessionFileAppender" type="log4net.Appender.FileAppender">
  <file value="Session.log" />
  <appendToFile value="false" />
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  <layout type='log4net.Layout.SerializedLayout, log4net.Ext.Json'>
    <decorator type='log4net.Layout.Decorators.StandardTypesDecorator, log4net.Ext.Json' />
    <default />
    <remove value='message' />
    <member value='message:messageobject' />
  </layout>
</appender>

输出是:

{"date":"2017-01-29T13:45:50.7345813-05:00","level":"DEBUG","appname":"MyApp.vshost.exe","logger":"MainWindow","thread":"9","ndc":"(null)","message":"Loading new UI instance"}
{"date":"2017-01-29T13:45:50.7380842-05:00","level":"DEBUG","appname":"MyApp.vshost.exe","logger":"MainWindow","thread":"9","ndc":"(null)","message":"Loading internal localization file"}
{"date":"2017-01-29T13:45:50.7510970-05:00","level":"DEBUG","appname":"MyApp.vshost.exe","logger":"MainWindow","thread":"9","ndc":"(null)","message":"Initializing UI"}

这很接近,但不是真正有效的 json。

【问题讨论】:

  • 您的输出看起来像是有效的 JSON 行格式:jsonlines.org

标签: c# json wpf log4net


【解决方案1】:

下载log4net.Ext.Json nuget package

将以下配置设置添加到 app.config/web.config 文件中

<log4net>
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
  <file value="logs\log-file-name.json" />
  <rollingStyle value="Date" />
  <datePattern value="yyyy-MM-dd" />
  <PreserveLogFileNameExtension value="true" />
  <staticLogFileName value="false" />
  <appendToFile value="true" />
  <maxSizeRollBackups value="10" />
  <dateTimeStrategy 
  type="log4net.Appender.RollingFileAppender+UniversalDateTime" />

  <!--text formatted log4net logging-->
  <!--<layout type="log4net.Layout.PatternLayout">
    --><!--check conversion patterns from 
   https://logging.apache.org/log4net/--><!--
    --><!--<conversionPattern value="%utcdate{ABSOLUTE} UTC %c{1} - %m%n" 
  />--><!--
    <conversionPattern value="%date [%thread] %-5level %logger - 
  %message%newline" />
  </layout>-->

  <!--json formatted log4net logging-->
  <layout type="log4net.Layout.SerializedLayout, log4net.Ext.Json">
    <decorator type="log4net.Layout.Decorators.StandardTypesDecorator, 
  log4net.Ext.Json" />
    <member value="date:date" />
    <member value="level:level" />
    <member value="logger:logger" />
    <member value="message:messageObject" />
    <member value="exception:exception" />
  </layout>
</appender>
<root>
  <!--Options are "ALL", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" and 
"OFF".-->
  <level value="DEBUG" />
  <appender-ref ref="RollingFile" />
</root>
</log4net>

这是一个使用 ninject 的示例调用

Kernel = new StandardKernel(); 
Kernel.Bind<ILog>().ToMethod(c => 
LogManager.GetLogger(typeof(YourClassName))).InSingletonScope();
var log = Kernel.Get<ILog>();
log.debug("testing log4net json");

【讨论】:

    【解决方案2】:

    解决方案足够基本,我编写了自己的Appender 将数据存储在集合中,然后根据需要使用 Json.net 序列化集合。这也使我能够在应用程序中查看日志并绑定到它,因此获得额外奖励。

    public class CollectionAppender : AppenderSkeleton
    {
        public static ObservableCollection<LogItem> logData = new ObservableCollection<LogItem>();
        protected override void Append(LoggingEvent loggingEvent)
        {
            logData.Add(new LogItem(loggingEvent));
        }
    }
    
    public class LogItem
    {
        public string Logger { get; private set; }
        public string Level { get; private set; }
        public string Message { get; private set; }
        public DateTime Timestamp { get; private set; }
        public Exception ExceptionData { get; private set; }
    
        public bool ShouldSerializeExceptionData() //This keeps things tidy when using Json.net for non exemption entries.
        {
            return ExceptionData != null;
        }
    
        public LogItem(LoggingEvent data)
        {
            Logger = data.LoggerName;
            Level = data.Level.DisplayName;
            Message = data.RenderedMessage;
            Timestamp = data.TimeStamp;
            ExceptionData = data.ExceptionObject;
        }
    }
    

    【讨论】:

    • 这是一个不错的解决方案! log4net 是否仍在积极维护中,如果有它会很好 - 可能会激怒贡献者?
    • 我在测试场景中使用了这种方法。如果这就是您所需要的,那就足够简单了。
    【解决方案3】:

    它将每一行输出为单独的 JSON 记录,就像它使用 1 行日志一样。 您可以逐行解析,或者您可以在每个 } 之后添加周围的 [] 和一个逗号,这样就可以了。

    【讨论】:

    • 如果事后我仍然需要迭代和重新解析文件,那么它有点违背了目的。
    • 你是对的@Wobbles,但即使对他们来说也有点困难,因为记录了打开-写入-关闭流,所以我认为维护 json 格式会很棘手,除非文件在内存中并且每次写入记录时都会被覆盖。
    • 没有考虑,看看有没有办法直接序列化 ILog 集合然后根据需要
    • 如果您没有找到解决方案并且您使用的是 c# 或 JS,那么我建议您添加 [ 和 ] 并将所有 ( } ) 替换为 ( }, ) 并且它会起作用只有一个解析,很重,但会成功。 @Wobbles
    • 可以在appender级别实现。 log4net.Ext.Json 用作单个日志事件的布局。如果您按照@MoustafaS 的建议进行字符串替换,请在每个新行之前放置逗号而不是},因为图形可以嵌套,或者数据可能包含},而默认情况下会转义新行。
    猜你喜欢
    • 2015-04-04
    • 2016-04-01
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多