events
.NET でカスタム ログ プロバイダーを実装する
一般的なログのニーズに使用できるログ プロバイダーは、数多くあります。 使用可能なプロバイダーの 1 つがアプリケーションのニーズに合わない場合は、カスタム ILoggerProvider の実装が必要になる場合があります。 この記事では、コンソールでログを色分けするために使用できるカスタム ログ プロバイダーを実装する方法について説明します。
ヒント
カスタム ログ プロバイダーのサンプル ソース コードは、Docs GitHub リポジトリで入手できます。 詳細については、「GitHub の .NET Docs - コンソールのカスタム ログ」を参照してください。
サンプルでは、次の構成の種類を使用して、ログ レベルとイベント ID ごとに異なる色のコンソール エントリを作成します。
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLoggerConfiguration
{
public int EventId { get; set; }
public Dictionary<LogLevel, ConsoleColor> LogLevelToColorMap { get; set; } = new()
{
[LogLevel.Information] = ConsoleColor.Green
};
}
上記のコードでは、既定のレベルが Information
に設定され、色が Green
に設定され、EventId
が暗黙的に 0
されます。
ILogger
実装カテゴリ名は、通常、ログ ソースです。 たとえば、ロガーが作成される型は次のようになります。
using Microsoft.Extensions.Logging;
public sealed class ColorConsoleLogger(
string name,
Func<ColorConsoleLoggerConfiguration> getCurrentConfig) : ILogger
{
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => default!;
public bool IsEnabled(LogLevel logLevel) =>
getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel);
public void Log<TState>(
LogLevel logLevel,
EventId eventId,
TState state,
Exception? exception,
Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}
ColorConsoleLoggerConfiguration config = getCurrentConfig();
if (config.EventId == 0 || config.EventId == eventId.Id)
{
ConsoleColor originalColor = Console.ForegroundColor;
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.WriteLine($"[{eventId.Id,2}: {logLevel,-12}]");
Console.ForegroundColor = originalColor;
Console.Write($" {name} - ");
Console.ForegroundColor = config.LogLevelToColorMap[logLevel];
Console.Write($"{formatter(state, exception)}");
Console.ForegroundColor = originalColor;
Console.WriteLine();
}
}
}
上記のコード:
- カテゴリ名ごとにロガー インスタンスを作成します。
IsEnabled
で_getCurrentConfig().LogLevelToColorMap.ContainsKey(logLevel)
をチェックし、各logLevel
に一意のロガーが含まれるようにします。 この実装では、ログ レベルごとに、ログに明示的な構成エントリが必要です。
Log
は任意のコンシューマーによって呼び出すことができるため、ILogger.Log 実装内で ILogger.IsEnabled を呼び出すのが良い方法であり、以前に確認されたことは保証されません。 IsEnabled
メソッドは、ほとんどの実装で非常に高速である必要があります。
TState state,
Exception? exception,
ロガーは、name
と現在の構成を返す Func<ColorConsoleLoggerConfiguration>
でインスタンス化されます。これにより、IOptionsMonitor<TOptions>.OnChange コールバックを介して監視された構成値の更新が処理されます。
重要
ILogger.Log 実装では、config.EventId
値が設定されているかどうかを確認します。 config.EventId
が設定されていない場合、または正確な logEntry.EventId
と一致する場合、ロガーはカラーでログに記録します。
ILoggerProvider
オブジェクトは、ロガー インスタンスの作成を担当します。 カテゴリごとにロガー インスタンスを作成する必要はありませんが、NLog や log4net などの一部のロガーには適しています。 この方法では、次の例のように、カテゴリごとに異なるログ出力ターゲットを選択できます。
using System.Collections.Concurrent;
using System.Runtime.Versioning;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
{
private readonly IDisposable? _onChangeToken;
private ColorConsoleLoggerConfiguration _currentConfig;
private readonly ConcurrentDictionary<string, ColorConsoleLogger> _loggers =
new(StringComparer.OrdinalIgnoreCase);
public ColorConsoleLoggerProvider(
IOptionsMonitor<ColorConsoleLoggerConfiguration> config)
{
_currentConfig = config.CurrentValue;
_onChangeToken = config.OnChange(updatedConfig => _currentConfig = updatedConfig);
}
public ILogger CreateLogger(string categoryName) =>
_loggers.GetOrAdd(categoryName, name => new ColorConsoleLogger(name, GetCurrentConfig));
private ColorConsoleLoggerConfiguration GetCurrentConfig() => _currentConfig;
public void Dispose()
{
_loggers.Clear();
_onChangeToken?.Dispose();
}
}
上記のコードでは、CreateLogger カテゴリ名ごとに ColorConsoleLogger
の単一のインスタンスを作成し、ConcurrentDictionary<TKey,TValue>
に格納します。 さらに、基になる ColorConsoleLoggerConfiguration
オブジェクトへの変更を更新するには、IOptionsMonitor<TOptions> インターフェイスが必要です。
ColorConsoleLogger
の構成を制御するには、そのプロバイダーにエイリアスを定義します。
[UnsupportedOSPlatform("browser")]
[ProviderAlias("ColorConsole")]
public sealed class ColorConsoleLoggerProvider : ILoggerProvider
ColorConsoleLoggerProvider
クラスは、次の 2 つのクラス スコープ属性を定義します。
- UnsupportedOSPlatformAttribute:
ColorConsoleLogger
型は"browser"
ではサポートされていません。 - ProviderAliasAttribute: 構成セクションでは、
"ColorConsole"
キーを使用してオプションを定義できます。
構成は、任意の有効な 構成プロバイダーで指定できます。 次の appsettings.json ファイルについて考えてみます。
{
"Logging": {
"ColorConsole": {
"LogLevelToColorMap": {
"Information": "DarkGreen",
"Warning": "Cyan",
"Error": "Red"
}
}
}
}
これにより、ログ レベルが次の値に構成されます。
- LogLevel.Information: ConsoleColor.DarkGreen
- LogLevel.Warning: ConsoleColor.Cyan
- LogLevel.Error: ConsoleColor.Red
Information ログ レベルは DarkGreenに設定され、ColorConsoleLoggerConfiguration
オブジェクトで設定された既定値がオーバーライドされます。
慣例により、依存関係の挿入のためのサービスの登録は、アプリケーションのスタートアップ ルーチンの一部として行われます。 登録は、Program
クラスで行われるか、Startup
クラスに委任できます。 この例では、Program.csから直接登録します。
カスタム ログ プロバイダーと対応するロガーを追加するには、HostingHostBuilderExtensions.ConfigureLogging(IHostBuilder, Action<ILoggingBuilder>)から ILoggingBuilder を含む ILoggerProvider を追加します。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddColorConsoleLogger(configuration =>
{
// Replace warning value from appsettings.json of "Cyan"
configuration.LogLevelToColorMap[LogLevel.Warning] = ConsoleColor.DarkCyan;
// Replace warning value from appsettings.json of "Red"
configuration.LogLevelToColorMap[LogLevel.Error] = ConsoleColor.DarkRed;
});
using IHost host = builder.Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogDebug(1, "Does this line get hit?"); // Not logged
logger.LogInformation(3, "Nothing to see here."); // Logs in ConsoleColor.DarkGreen
logger.LogWarning(5, "Warning... that was odd."); // Logs in ConsoleColor.DarkCyan
logger.LogError(7, "Oops, there was an error."); // Logs in ConsoleColor.DarkRed
logger.LogTrace(5, "== 120."); // Not logged
await host.RunAsync();
ILoggingBuilder
は、1 つ以上の ILogger
インスタンスを作成します。 ILogger
インスタンスは、情報をログに記録するためにフレームワークによって使用されます。
appsettings.json ファイルの構成は、次の値をオーバーライドします。
慣例により、ILoggingBuilder
の拡張メソッドを使用してカスタム プロバイダーを登録します。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Configuration;
public static class ColorConsoleLoggerExtensions
{
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder)
{
builder.AddConfiguration();
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<ILoggerProvider, ColorConsoleLoggerProvider>());
LoggerProviderOptions.RegisterProviderOptions
<ColorConsoleLoggerConfiguration, ColorConsoleLoggerProvider>(builder.Services);
return builder;
}
public static ILoggingBuilder AddColorConsoleLogger(
this ILoggingBuilder builder,
Action<ColorConsoleLoggerConfiguration> configure)
{
builder.AddColorConsoleLogger();
builder.Services.Configure(configure);
return builder;
}
}
この単純なアプリケーションを実行すると、次の図のような色の出力がコンソール ウィンドウにレンダリングされます。
.NET に関するフィードバック
.NET はオープンソース プロジェクトです。 フィードバックを提供するにはリンクを選択します。
その他のリソース
トレーニング
モジュール
App Service 診断ログを使用して Web アプリケーション ログをキャプチャする - Training
Azure Web アプリからトレース出力をキャプチャする方法について説明します。 ライブ ログ ストリームを表示し、オフライン分析用にログ ファイルをダウンロードします。