複雑なオブジェクトのログ

OpenTelemetry .NET で複雑なオブジェクトをログに記録する方法を学びます

Getting Started with OpenTelemetry .NET Logs - Console ガイドでは、プリミティブなデータ型をログに記録する方法を学びました。 このガイドでは、複雑なオブジェクトをログに記録する方法を紹介します。

.NET での複雑なオブジェクトのログ

複雑なオブジェクトのログは、.NET 8.0 で LogPropertiesAttribute を通じて導入されました。 この属性と対応するコード生成ロジックは、Microsoft.Extensions.Telemetry.Abstractions という拡張パッケージによって提供されています。

前提条件

実装手順

1. 必要なパッケージのインストール

Microsoft.Extensions.Telemetry.Abstractions パッケージをインストールします。

dotnet add package Microsoft.Extensions.Telemetry.Abstractions

2. 複雑なデータ型の定義

複雑なオブジェクトを表す構造体を作成します。

public struct FoodRecallNotice
{
    public string? BrandName { get; set; }
    public string? ProductDescription { get; set; }
    public string? ProductType { get; set; }
    public string? RecallReasonDescription { get; set; }
    public string? CompanyName { get; set; }
}

3. LogPropertiesAttribute を使用したロガー拡張メソッドの作成

ILogger に対して拡張メソッドを定義します。

using Microsoft.Extensions.Logging;

internal static partial class LoggerExtensions
{
    [LoggerMessage(LogLevel.Critical)]
    public static partial void FoodRecallNotice(
        this ILogger logger,
        [LogProperties(OmitReferenceName = true)] in FoodRecallNotice foodRecallNotice);
}

[LogProperties(OmitReferenceName = true)] 属性は、ソースジェネレーターに以下を指示します。

  • FoodRecallNotice のすべてのプロパティを個別のログ属性として含める
  • 属性キーから参照名(パラメーター名)を省略する

4. 複雑なオブジェクトのログ記録

複雑なオブジェクトのインスタンスを作成し、ログに記録します。

// 複雑なオブジェクトを作成
var foodRecallNotice = new FoodRecallNotice
{
    BrandName = "Contoso",
    ProductDescription = "Salads",
    ProductType = "Food & Beverages",
    RecallReasonDescription = "due to a possible health risk from Listeria monocytogenes",
    CompanyName = "Contoso Fresh Vegetables, Inc.",
};

// 複雑なオブジェクトをログに記録
logger.FoodRecallNotice(foodRecallNotice);

5. アプリケーションの実行

たとえば dotnet run を使用してアプリケーションを実行すると、コンソールに以下のようなログ出力が表示されます。

LogRecord.Timestamp:               2024-01-12T19:01:16.0604084Z
LogRecord.CategoryName:            Program
LogRecord.Severity:                Fatal
LogRecord.SeverityText:            Critical
LogRecord.FormattedMessage:
LogRecord.Body:
LogRecord.Attributes (Key:Value):
    CompanyName: Contoso Fresh Vegetables, Inc.
    RecallReasonDescription: due to a possible health risk from Listeria monocytogenes
    ProductType: Food & Beverages
    ProductDescription: Salads
    BrandName: Contoso
LogRecord.EventId:                 252550133
LogRecord.EventName:               FoodRecallNotice

FoodRecallNotice オブジェクトの各プロパティが、ログレコード内の個別の属性として表示されていることに注目してください。

LogPropertiesAttribute のオプション

LogPropertiesAttribute には、プロパティがログにどのように含まれるかを制御するいくつかのオプションがあります。

  • OmitReferenceName: true に設定すると、属性キーからパラメーター名が省略されます。 上の例では、属性キーは「foodRecallNotice.BrandName」ではなく、プロパティ名のみ(たとえば「BrandName」)になっています。

  • IncludeProperties: どのプロパティを含めるかを指定するために使用します。 指定しない場合、すべてのプロパティが含まれます。

  • ExcludeProperties: ログから除外するプロパティを指定するために使用します。

  • IncludeSensitive: true に設定すると、[Sensitive] 属性でマークされたプロパティがログに含まれます。 デフォルトは false です。

完全な例

すべてをまとめた完全な例を以下に示します。

using System;
using Microsoft.Extensions.Logging;
using OpenTelemetry;
using OpenTelemetry.Logs;

// 複雑なオブジェクトの定義
public struct FoodRecallNotice
{
    public string? BrandName { get; set; }
    public string? ProductDescription { get; set; }
    public string? ProductType { get; set; }
    public string? RecallReasonDescription { get; set; }
    public string? CompanyName { get; set; }
}

// ロガー拡張メソッド
internal static partial class LoggerExtensions
{
    [LoggerMessage(LogLevel.Critical)]
    public static partial void FoodRecallNotice(
        this ILogger logger,
        [LogProperties(OmitReferenceName = true)] in FoodRecallNotice foodRecallNotice);
}

// メインプログラム
class Program
{
    static void Main(string[] args)
    {
        // OpenTelemetry を使用してロガーファクトリを作成
        using var loggerFactory = LoggerFactory.Create(builder =>
        {
            builder.AddOpenTelemetry(options =>
            {
                options.AddConsoleExporter();
            });
        });

        // ロガーインスタンスを取得
        var logger = loggerFactory.CreateLogger<Program>();

        // 複雑なオブジェクトを作成
        var foodRecallNotice = new FoodRecallNotice
        {
            BrandName = "Contoso",
            ProductDescription = "Salads",
            ProductType = "Food & Beverages",
            RecallReasonDescription = "due to a possible health risk from Listeria monocytogenes",
            CompanyName = "Contoso Fresh Vegetables, Inc.",
        };

        // 複雑なオブジェクトをログに記録
        logger.FoodRecallNotice(foodRecallNotice);

        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}

さらに学ぶ