はじめに
前回messagetemplates-csharp
というMessageTemplate
を扱えるようにするライブラリを紹介しました。
今回はMS製のMicrosoft.Extensions.Logging
というLoggingライブラリについて紹介したいと思います。(Microsoft.Extensions.Logging
はMessageTemplate
に対応しています)
概要
Microsoft.Extensions.Logging
はMS製のLoggingパッケージです。構造化ロギングに対応しており、コンソールへのテキスト・Jsonなどへの出力を行うことができます。
.NET は、アプリケーションの動作の監視と問題の診断に役立つ、ILogger API を介した高パフォーマンスで構造化されたログ記録をサポートしています。 さまざまなログ プロバイダーを構成することで、ログをさまざまな宛先に書き込むことができます。 基本的なログ プロバイダーは組み込みであり、多くのサードパーティ プロバイダーも利用できます。
環境
Rider2023.3.3
Microsoft.Extensions.Logging v8.0.0
Microsoft.Extensions.Logging.Console v8.0.0
インストール
NuGet
からMicrosoft.Extensions.Logging
をインストールします。
また使用したいプロバイダー(出力先)ごとにパッケージを追加する必要があります。今回はコンソールに出力するサンプルのみ紹介するので以下のパッケージを追加でインストールします。
Microsoft.Extensions.Logging.Console
Getting Started
まずはシンプルなコードから使い方を学んでいきます。
using Microsoft.Extensions.Logging; namespace SampleConsole; public static class Program { public static void Main(string[] args) { using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole()); ILogger logger = factory.CreateLogger("Program"); logger.LogInformation("Hello World! Logging is {Description}.", "fun"); } }
LoggerFactory.Create
ILoggerFactory
のインスタンスを生成します。引数のconfigure
を利用してログメッセージが送信される出力先(プロバイダー)が設定します。
// LogLevel.Information以上のメッセージをコンソールに出力するよう設定する using ILoggerFactory factory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Information).AddConsole());
またSetMinimumLevel(LogLevel.〇〇)
のように指定したLogLovel
以上のログのみ出力するような設定ができます。LogLevel
については後述します。
Unity LoggingのLoggerConfig
を用いたLogger
生成に少し似ていますね。(Unityの場合はFactoryを確か生成しませんが)
ILoggerFactory.CreateLogger
ILogger
のインスタンスを生成します。
ILogger logger = factory.CreateLogger("Program");
引数のcategoryName
によってメッセージのカテゴリ分けがされます。例えばConsole
の場合はProgram
に設定するとinfo: Program[0]
みたいな文字列が先頭に表示されるようになります。ログを検索またはフィルター処理するときに、同じクラス (またはカテゴリ) のログ メッセージをグループ化するために使用されます。
// 出力例 info: Program[0] Hello World! Logging is fun. info: Program[0] Hello World! Logging is sad. info: Program[0] Hello World! Logging is joy.
ILogger.Log〇〇
Microsoft.Extensions.Logging
には以下のLogLevel
が設定されています。詳細はこちらから。
public enum LogLevel { Trace, Debug, Information, Warning, Error, Critical, None, }
これらに対応したログメソッドがあります。(None
はないです)
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Trace).AddConsole()); ILogger logger = factory.CreateLogger("Program"); logger.LogTrace("Hello World! Logging is {Description}.", "fun"); logger.LogDebug("Hello World! Logging is {Description}.", "fun"); logger.LogInformation("Hello World! Logging is {Description}.", "fun"); logger.LogWarning("Hello World! Logging is {Description}.", "fun"); logger.LogError("Hello World! Logging is {Description}.", "fun"); logger.LogCritical("Hello World! Logging is {Description}.", "fun");
MessageTemplateについて
ILogger.Log〇〇
メソッドはMessageTemplate
に対応しています。これによって構造化ロギングを実現しています。
// ILogger.LogInformation public static void LogInformation(this ILogger logger, string? message, params object?[] args)
// Jsonとして出力したサンプル using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddJsonConsole()); ILogger logger = factory.CreateLogger("Program"); // コンソールへの出力 : {"EventId":0,"LogLevel":"Information","Category":"Program","Message":"User alice logged in from 123.45.67.89","State":{"Message":"User alice logged in from 123.45.67.89","username":"alice","ip_address":"123.45.67.89","{OriginalFormat}":"User {username} logged in from {ip_address}"}} logger.LogInformation("User {username} logged in from {ip_address}", "alice", "123.45.67.89");
MessageTemplate
の詳細は以下に記載したので気になる方はチェックしてみてください。
www.hanachiru-blog.com
ログのカテゴリ名(categoryName)について
最初の例では文字列で指定していましたが、ジェネリクスを用いて型名を指定した方が推奨されています。
C# でのログ記録 - .NET | Microsoft Learn
public class Program { public static void Main(string[] args) { using ILoggerFactory factory = LoggerFactory.Create(builder => builder.SetMinimumLevel(LogLevel.Trace).AddJsonConsole()); // 型を指定する ILogger logger = factory.CreateLogger<Program>(); logger.LogInformation("User {username} logged in from {ip_address}", "alice", "123.45.67.89"); } }
EventIdについて
ILogger.Log〇〇
メソッドの引数にイベント識別子(EventId
)を指定することができます。
public static void Main(string[] args) { using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddJsonConsole()); ILogger logger = factory.CreateLogger<Program>(); // Text : info: SampleConsole.Program[1] User alice logged in from 123.45.67.89 // Json : {"EventId":1,"LogLevel":"Information","Category":"SampleConsole.Program","Message":"User alice logged in from 123.45.67.89","State":{"Message":"User alice logged in from 123.45.67.89","username":"alice","ip_address":"123.45.67.89","{OriginalFormat}":"User {username} logged in from {ip_address}"}} logger.LogInformation(new EventId(1, "sample"), "User {username} logged in from {ip_address}", "alice", "123.45.67.89"); }
categoryName
に近い概念ですが、Logメソッドに対して割り振ることができます。
C# でのログ記録 - .NET | Microsoft Learn
さいごに
OpenTelemetry .NET
を用いることでログの出力先をOpenTelemetry
に対応できるそうです。この辺結構気になっているので、また後ほど記事を書きたいと思っています。