32

Serilog には、次の例に示すように、オブジェクトを分解する便利な方法があります。

logger.Debug(exception, "This is an {Exception} text", exception);
logger.Debug(exception, "This is an {@Exception} structure", exception);

最初の行では、ロガーが (ToString() を呼び出すことによって) 例外をプレーン テキストとしてログに記録し、2 行目では、ロガーが例外プロパティを個別のフィールドとして書き込みます。しかし、このオーバーロードはどうですか:

logger.Debug(exception, "This is an exception", exception);

これは最初の引数として例外を受け取り、常に文字列として書き込まれます。私が可能にしたいのは、構造化された方法で例外のロギングを有効にすることです。これを実現するために Serilog を構成することは可能ですか?

アップデート。この質問は、例外のログ記録の別の側面につながると思います: レンダリングされたテキスト メッセージにすべての例外プロパティを書き込まずに (Elasticsearch のようなリッチ シンクに構造化された方法でログに記録されるように)、メッセージが例外プロパティで強化されるようにするにはどうすればよいでしょうか (そのため、平文のロガーは大量の例外の詳細で埋め尽くされることはありません)。

4

3 に答える 3

37

Serilog.Exceptionsログの例外の詳細と、Exception.ToString() に出力されないカスタム プロパティを参照してください

このライブラリには、最も一般的な例外タイプの追加プロパティを処理するカスタム コードが含まれており、例外が Serilog.Exceptions によって内部的にサポートされていない場合にのみ、リフレクションを使用して追加情報を取得します。

NuGet パッケージを追加してから、次のようにエンリッチャーを追加します。

using Serilog;
using Serilog.Exceptions;

ILogger logger = new LoggerConfiguration()
    .Enrich.WithExceptionDetails()
    .WriteTo.Sink(new RollingFileSink(
        @"C:\logs",
        new JsonFormatter(renderMessage: true))
    .CreateLogger();

JSON ログは、詳細な例外情報とカスタム例外プロパティで補完されるようになりました。EntityFramework から DbEntityValidationException をログに記録するとどうなるかの例を次に示します (この例外は、 に含まれていない深くネストされたカスタム プロパティを持つことで有名です.ToString())。

try
{
    ...
}
catch (DbEntityValidationException exception)
{
    logger.Error(exception, "Hello World");
}

上記のコードは、次のログを記録します。

{
  "Timestamp": "2015-12-07T12:26:24.0557671+00:00",
  "Level": "Error",
  "MessageTemplate": "Hello World",
  "RenderedMessage": "Hello World",
  "Exception": "System.Data.Entity.Validation.DbEntityValidationException: Message",
  "Properties": {
    "ExceptionDetail": {
      "EntityValidationErrors": [
        {
          "Entry": null,
          "ValidationErrors": [
            {
              "PropertyName": "PropertyName",
              "ErrorMessage": "PropertyName is Required.",
              "Type": "System.Data.Entity.Validation.DbValidationError"
            }
          ],
          "IsValid": false,
          "Type": "System.Data.Entity.Validation.DbEntityValidationResult"
        }
      ],
      "Message": "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.",
      "Data": {},
      "InnerException": null,
      "TargetSite": null,
      "StackTrace": null,
      "HelpLink": null,
      "Source": null,
      "HResult": -2146232032,
      "Type": "System.Data.Entity.Validation.DbEntityValidationException"
    },
    "Source": "418169ff-e65f-456e-8b0d-42a0973c3577"
  }
}

Serilog.Exceptionsは .NET Standard をサポートし、リフレクションなしで多くの一般的な例外タイプをサポートしていますが、さらに追加したいと考えているため、お気軽に貢献してください。

重要なヒント - 人間が読めるスタック トレース

Ben.Demystifier NuGet パッケージを使用して、人間が判読できる例外のスタック トレースを取得するか、 Serilog を使用している場合はserilog-enrichers-demystify NuGet パッケージを使用できます。

于 2015-12-07T12:37:52.730 に答える
25

これについて議論しているフォーラム スレッドがあり、いくつかの解決策が提示されています。Thomas Bolon は、 Gist で見つけることができる「例外破壊」拡張機能を作成しました。

この場合、次の構文のみを使用します。

logger.Debug(exception, "This is an exception");

書式文字列に例外を追加する必要はありません。

例外がテキスト シンクに確実に出力されるようにする{Exception}には、 が出力テンプレートに含まれていることを確認してください。標準の組み込みのものにはすでにこれがあります。

outputTemplate: "{Timestamp} [{Level}] {Message}{NewLine}{Exception}";
于 2014-08-15T19:45:36.187 に答える
3

これは完全に避けるべきです。ElasticSearch と Serilog はどちらも、任意のオブジェクトをシリアル化することを念頭に置いて設計されていません。競合する形状のオブジェクトをログに記録すると、ElasticSearch でマッピング例外が発生します。NuGet で ElasticSearch シンクを使用している場合、マッピングの競合を引き起こすものはすべて失われます。また、Serilog は循環関係を処理しないため、深さリミッターのセルフログ エラーが発生します。ディクショナリに分解し、これを Serilog に渡すことでこれに対処しようとするプロジェクトがありますが、それでもログが乱雑になり、例外がマッピングされます。

セリログ: https://nblumhardt.com/2016/02/serilog-tip-dont-serialize-arbitrary-objects/

例外で役立つと思われるものに基づいて、例外プロパティのログ記録について具体的に説明するのが最善であることがわかりました。

于 2016-07-20T00:44:58.210 に答える