.NET Core 以降(.NET 5/6/8含む)のコンソールアプリケーションで、本格的なログ出力を行うには Microsoft.Extensions.Logging と Microsoft.Extensions.Hosting を組み合わせるのが標準的な手法です。
System.Console.WriteLine とは異なり、ログレベル(Information, Warning, Errorなど)に応じた色分けや、ファイル・DBへの出力先の切り替えが容易になります。
ここでは、Generic Host パターンを使用して、DI(依存性注入)コンテナから ILogger を受け取り、各レベルのログを出力する基本的な実装を紹介します。
1. 必要なパッケージのインストール
プロジェクトを作成した後、以下のNuGetパッケージをインストールします。
dotnet add package Microsoft.Extensions.Hosting
dotnet add package Microsoft.Extensions.Logging
dotnet add package Microsoft.Extensions.Logging.Console
2. 実装コード
Program.cs (ホストの構築と設定)
Host.CreateDefaultBuilder を使い、ログの設定と、実行するワーカークラス(MyWorker)の登録を行います。 ここでは LogTrace や LogDebug も表示されるように、最小ログレベルを Trace に設定しています。
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Gihyo
{
class Program
{
static async Task Main(string[] args)
{
// ホストを構築して実行
await CreateHostBuilder(args).Build().RunAsync();
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((context, logging) =>
{
// デフォルトのプロバイダをクリアし、コンソールのみ追加
logging.ClearProviders();
logging.AddConsole();
// すべてのレベルのログを表示するように設定
logging.SetMinimumLevel(LogLevel.Trace);
})
.ConfigureServices((context, services) =>
{
// MyWorkerをHostedServiceとして登録(アプリ起動時に自動実行されます)
services.AddHostedService<MyWorker>();
});
}
}
MyWorker.cs (ログ出力を行うクラス)
ILogger<MyWorker> をコンストラクタで受け取ることで、このクラス専用のロガーが注入されます。 BackgroundService を継承することで、アプリ起動時に ExecuteAsync が自動的に呼び出されます。
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Gihyo
{
// BackgroundServiceを継承すると、起動時にExecuteAsyncが走ります
public class MyWorker : BackgroundService
{
private readonly ILogger<MyWorker> _logger;
// DIコンテナからロガーを受け取る
public MyWorker(ILogger<MyWorker> logger)
{
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
// 各レベルのログ出力テスト
// 第1引数にメッセージ、必要であれば第2引数以降に引数を渡せます
_logger.LogTrace("これは Trace (詳細トレース) レベルのログです。");
_logger.LogDebug("これは Debug (デバッグ) レベルのログです。");
_logger.LogInformation("これは Information (情報) レベルのログです。");
_logger.LogWarning("これは Warning (警告) レベルのログです。");
_logger.LogError("これは Error (エラー) レベルのログです。");
_logger.LogCritical("これは Critical (致命的) レベルのログです。");
return Task.CompletedTask;
}
}
}
3. 実行結果
コンソールには以下のように、ログレベルごとに色分けされて出力されます(配色はターミナル環境により異なります)。
trce: Gihyo.MyWorker[0]
これは Trace (詳細トレース) レベルのログです。
dbug: Gihyo.MyWorker[0]
これは Debug (デバッグ) レベルのログです。
info: Gihyo.MyWorker[0]
これは Information (情報) レベルのログです。
warn: Gihyo.MyWorker[0]
これは Warning (警告) レベルのログです。
fail: Gihyo.MyWorker[0]
これは Error (エラー) レベルのログです。
crit: Gihyo.MyWorker[0]
これは Critical (致命的) レベルのログです。
解説とポイント
- ILogger<T> の注入:
public MyWorker(ILogger<MyWorker> logger)とすることで、ログ出力時に「どのクラス(MyWorker)から出たログか」がカテゴリ名として自動的に付与されます(出力結果のGihyo.MyWorker部分)。 - ログレベルの設定: デフォルト設定では
Information以上のログしか表示されません。開発中にTraceやDebugを見たい場合は、logging.SetMinimumLevel(LogLevel.Trace)を設定するか、appsettings.jsonで設定を変更する必要があります。 - 構造化ログ:
_logger.LogInformation("Processing id: {Id}", 123);のようにプレースホルダーを使うと、単なる文字列結合ではなく、構造化されたデータとしてログを記録でき、後で検索・分析しやすくなります。
