【C#】Log4netをGeneric Hostで使用する (Microsoft.Extensions.Logging)

古くから実績のあるロギングライブラリ log4net ですが、現在の .NET (Core) 環境でも、Microsoft の標準ロギングインターフェース(ILogger)を通して利用することが可能です。

既存資産の流用や、log4net 特有の設定(強力なローテーション機能など)を使いたい場合に有効です。

目次

実装サンプル:日次データ集計バッチ

ここでは、「データ集計サービス(AggregationService)」が動作し、警告(Warning)以上の重要なログだけを daily-batch.log に記録する構成を作成します。

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

必要なアダプターパッケージをインストールします。

dotnet add package Microsoft.Extensions.Logging.Log4Net.AspNetCore

2. log4net.config の作成

プロジェクト直下に log4net.config を作成します。 注意: ファイルのプロパティで「出力ディレクトリにコピー: 常にコピー」に設定することを忘れないでください。

以下の設定では、ログファイルを 50MB ごとに分割し、最大5世代までバックアップを残す設定にしています。

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <root>
    <level value="ALL" />
    <appender-ref ref="RollingFile" />
  </root>

  <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
    <file value="logs/daily-batch.log" />
    
    <appendToFile value="true" />
    
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="5" />
    <maximumFileSize value="50MB" />
    <staticLogFileName value="true" />

    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%-5level] %logger - %message%newline" />
    </layout>

    <filter type="log4net.Filter.LevelRangeFilter">
      <levelMin value="WARN" />
      <levelMax value="FATAL" />
    </filter>
  </appender>
</log4net>

3. Program.cs (Log4netの組み込み)

ホスト構築時に .AddLog4Net() を追加するだけで、アプリケーション全体のログ出力先として log4net が有効になります。

using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

namespace BatchSystem
{
    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();

                    // 最低ログレベルの設定(ここではTrace以上を通過させる)
                    logging.SetMinimumLevel(LogLevel.Trace);

                    // log4net を追加 (デフォルトで直下の log4net.config を読み込みます)
                    logging.AddLog4Net();
                })
                .ConfigureServices((context, services) =>
                {
                    // 集計サービスを登録
                    services.AddHostedService<AggregationService>();
                });
    }
}

4. AggregationService.cs (ログ出力の実装)

ログを出力するクラス側では、log4net への依存はなく、標準の ILogger を使って記述します。

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;

namespace BatchSystem
{
    public class AggregationService : BackgroundService
    {
        private readonly ILogger<AggregationService> _logger;

        public AggregationService(ILogger<AggregationService> logger)
        {
            _logger = logger;
        }

        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            // --- 以下のログは設定によりファイルには出力されません (Information以下) ---
            _logger.LogTrace("詳細: メモリ使用量の計測開始");
            _logger.LogDebug("デバッグ: DB接続文字列のパース成功");
            _logger.LogInformation("情報: 日次集計処理を開始しました");

            // --- 以下のログはファイル(daily-batch.log)に記録されます (Warning以上) ---
            
            // 警告: 処理は継続できるが、注意が必要なケース
            _logger.LogWarning("警告: 集計対象データの一部が欠損しています (Date: 2025-01-10)");

            // エラー: 処理が失敗したケース
            _logger.LogError("エラー: 出力先ディレクトリへの書き込み権限がありません");

            // 致命的: システム停止が必要なケース
            _logger.LogCritical("致命的: データベースとの接続が切断されました。強制終了します");

            return Task.CompletedTask;
        }
    }
}

解説

フィルタリングの挙動

この構成では、アプリケーションコード内で LogInformation を記述しても、log4net.config 側の <levelMin value="WARN" /> というフィルタによって弾かれるため、ログファイルには出力されません。 これにより、「開発中はコンソールですべて確認し、本番運用のログファイルにはエラーだけを残す」といった制御が可能になります。

設定ファイルの配置

log4net.config が読み込まれないトラブルの多くは、ビルド時に実行フォルダ(bin/Debug/...)へファイルがコピーされていないことが原因です。Visual Studioのプロパティまたは .csproj ファイルで <CopyToOutputDirectory>Always</CopyToOutputDirectory> が設定されているか必ず確認してください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次