.NET 標準の Microsoft.Extensions.Logging は優秀ですが、デフォルトでは「テキストファイルへのログ出力」や「ローテーション(日付ごとのファイル切り替え)」機能が弱いです。
そこで、高機能なサードパーティ製ライブラリである NLog を導入することで、柔軟なファイル出力やフォーマット設定を実現する方法を解説します。
実装手順
1. パッケージのインストール
.NET のコンソールアプリ(Generic Host)で NLog を使うために必要なパッケージをインストールします。
dotnet add package NLog.Extensions.Logging
※ Webアプリ(ASP.NET Core)の場合は NLog.Web.AspNetCore を使いますが、バッチやコンソールアプリでは上記が標準的です。
2. nlog.config の作成と設定
プロジェクトのルートに nlog.config という名前でXMLファイルを作成します。 重要: 作成後、プロパティで「出力ディレクトリにコピー: 常にコピー」に設定してください。
以下の設定では、ログレベルに応じて「デバッグ用(詳細)」と「エラー用(重要)」の2つのファイルに書き分けます。
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Info"
internalLogFile="internal-nlog.txt">
<targets>
<target xsi:type="File" name="debugLog" fileName="logs/debug-${shortdate}.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
<target xsi:type="File" name="errorLog" fileName="logs/error-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
<target xsi:type="Console" name="console"
layout="${date:format=HH\:mm\:ss} [${uppercase:${level}}] ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="console" />
<logger name="*" minlevel="Trace" maxlevel="Warn" writeTo="debugLog" />
<logger name="*" minlevel="Error" writeTo="errorLog" />
</rules>
</nlog>
3. Program.cs (NLogの有効化)
Generic Host の構築時に .UseNLog() を呼び出すことで、標準の ILogger の裏側で NLog が動くようになります。
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using NLog.Extensions.Logging; // UseNLogに必要
namespace TaskApp
{
class Program
{
static async Task Main(string[] args)
{
try
{
await CreateHostBuilder(args).Build().RunAsync();
}
catch (Exception ex)
{
// NLog自体の設定ミスなどで落ちた場合の保険
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Error(ex, "プログラムが停止しました");
throw;
}
finally
{
// アプリ終了時にログをフラッシュ(書き込み)する
NLog.LogManager.Shutdown();
}
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((context, logging) =>
{
// 標準のプロバイダをクリアし、NLogに任せる
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog() // NLogを有効化
.ConfigureServices((context, services) =>
{
services.AddHostedService<MyWorker>();
});
}
}
4. MyWorker.cs (ログ出力の実装)
ここでのコードは、標準の Microsoft.Extensions.Logging.ILogger を使う場合と全く同じです。NLog を使っていることを意識する必要はありません。
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace TaskApp
{
public class MyWorker : BackgroundService
{
private readonly ILogger<MyWorker> _logger;
public MyWorker(ILogger<MyWorker> logger)
{
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
// 各種レベルでのログ出力
// NLogの設定に従い、ファイルやコンソールに振り分けられます
_logger.LogTrace("詳細: 変数の値をトレースします...");
_logger.LogDebug("デバッグ: 処理の分岐を確認");
_logger.LogInformation("情報: アプリケーションが起動しました");
_logger.LogWarning("警告: 処理に時間がかかっています");
// ↓ Error以上は errorLog ファイルに出力される設定
_logger.LogError("エラー: 予期しないデータを受信しました");
_logger.LogCritical("致命的: データベースに接続できません");
return Task.CompletedTask;
}
}
}
解説
NLog導入のメリット
標準機能だけでは実装が面倒な以下の機能が、XML設定だけで実現できます。
- ファイルローテーション:
fileName="logs/debug-${shortdate}.log"と書くだけで、毎日自動的に新しいログファイル(例:debug-2026-01-09.log)が作られます。 - 出力先の振り分け: エラーだけを別のファイルにしたり、特定のクラスのログだけ無視したりといったフィルタリングが強力です。
- フォーマットの自由度: ログの出力形式(CSV、JSON、タブ区切りなど)を自由にカスタマイズできます。
UseNLog() の役割
Program.cs で .UseNLog() を呼ぶことで、.NET の DIコンテナに NLog が登録されます。これにより、MyWorker クラスなどで ILogger<T> を使った際、実体として NLog が呼び出され、nlog.config の設定に従って出力が行われます。
