ログをJSONで出力する(log4net)

仕事ではlog4netを使用してアプリケーションログを出力しています。
今までは独自のテキスト形式で出力することが多かったのですが、
構造化を意識する必要性もあり、log4net.Ext.Jsonを使用してJSONで出力することにしました。

configは以下のような感じ。

<log4net>
  <appender name="JsonFileAppender" type="log4net.Appender.RollingFileAppender">
    <param name="File" value="./../Log/Application.log" />
    <param name="StaticLogFileName" value="false" />
    <param name="AppendToFile" value="true" />
    <param name="RollingStyle" value="Size" />
    <param name="MaxSizeRollBackups" value="8" />
    <param name="MaximumFileSize" value="10MB" />
    <param name="Encoding" value="utf-8" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <layout type="log4net.Layout.SerializedLayout, log4net.Ext.Json">
      <decorator type="log4net.Ext.Json.Serializers.Newtonsoft.NewtonsoftDecorator, log4net.Ext.Json.Serializers.Newtonsoft" />
      <renderer type="log4net.ObjectRenderer.JsonObjectRenderer, log4net.Ext.Json">
        <factory type="log4net.Ext.Json.Serializers.Newtonsoft.NewtonsoftFactory, log4net.Ext.Json.Serializers.Newtonsoft" />
      </renderer>
      <default />
      <remove value="message" />
      <remove value="ndc" />
      <member value="message:messageobject" />
    </layout>
  </appender>
  <root>
    <level value="ALL" />
    <appender-ref ref="JsonFileAppender" />
  </root>
</log4net>

で、以下みたいな感じでインスタンスを直接渡してあげると、内部でJSONにSerializeされてログに書き込まれます。
※本当はクラスを作った方がよかったのですが、面倒だったので、このサンプルでは匿名型としておきます。

logger.Info(new {
    RequestUri = actionContext.Request.RequestUri,
    HttpMethod = actionContext.Request.Method.Method
});

エラーログなんかもExceptionクラスのインスタンスをそのまま渡してしまっています。

try {
    ・・・
}
catch (e) {
    logger.Error(e);
    throw;
}

分析したりする際にはログファイルを社内ローカルサーバーのMongoDBにインポートして使用しています。
仕事の都合上、オンプレミスとクラウド(Azure)両方に対応する必要があったので、
Azureの場合には、ApplicationInsightsAppenderを使ってApplication Insightsにログを出力しているのですが、
Application InsightsのWeb API経由で、ログをファイルに書き出すバッチを組んで定期的に実行するようにしており、
結果的にはオンプレミスでもAzureでも同じようにMongoDBに格納されるようにしています。
※Azureの場合、ログに書き出される日時がUTCになってしまうので、ファイルに書き出す際にJSTに変換したりもしています。
※MongoDBにインポートする際に、エラーログが含まれていたらメール通知させたりもしています。

もうちょっとスマートな方法があれば今後、改善していきたいと思います。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください