Skip to content

MS_DotNetLogging

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

.NETのログ

概要

.NET のログ出力のいろいろ

補足(現在の第一候補は ILogger: 本ページは
System.Diagnostics 系と log4net / NLog を並べた一覧だが、
現在の .NET では **Microsoft.Extensions.LoggingILogger<T>)**が
標準の入口になっている。

【アプリのコード】
   ILogger<T> に書く(抽象に依存する)
         ↓
【プロバイダー(差し替え可能)】
   Console / Debug / EventLog / EventSource
   Serilog / NLog / log4net / Application Insights / OpenTelemetry …

ILogger に書いておけば、出力先は後から差し替えられる
DI / 依存性反転原則
典型的な適用例)。

public class OrderService(ILogger<OrderService> logger)
{
    public void Place(Order o)
        => logger.LogInformation("Order {OrderId} placed by {UserId}", o.Id, o.UserId);
}

文字列を組み立てず、テンプレートとパラメータを渡すのが要点である
構造化ログ)。
こうしておくと、OrderId で検索・集計できるログになる。

詳細

System.Diagnostics

EventLog

補足(イベント ログの制約): Windows 専用であり、
.NET Core 以降では System.Diagnostics.EventLog パッケージが要る。

・イベント ソースの作成に管理者権限が必要(初回のみ)
・出力が遅い(同期書き込み)
・大量出力に向かない(ログがローテーションで流れる)

**サービス・常駐プログラムの「起動/停止/致命的エラー」**のような
少量の重要イベントに限って使うのが妥当である。
業務ログは別の出力先に分ける。

Trace や Debug

補足(DebugTrace の違い): 混同されやすいが、
コンパイル時に消えるかどうかが決定的に違う。

Debug Trace
有効化する定数 DEBUG TRACE
Release ビルド 消える(呼び出しごと削除) 残る(既定で TRACE 定義)
用途 開発時の確認 本番でも残す診断出力

どちらも [Conditional] 属性で実装されており、
定数が未定義なら呼び出し自体がコンパイル時に除去される
(引数の評価コストもかからない)。

TraceListener

TraceSource

補足(TraceSourceTrace の上位版): Trace
アプリ全体で 1 系統なのに対し、TraceSource
名前付きの系統を複数持てるILogger<T> のカテゴリに近い発想)。

<system.diagnostics>
  <sources>
    <source name="MyApp.Data" switchValue="Warning">
      <listeners><add name="file" /></listeners>
    </source>
  </sources>
</system.diagnostics>

ただし、設定が app.config の XML であること
構造化ログに向かないことから、
新規では ILogger を使う方がよい。

なお、ILogger から TraceSource へ流すプロバイダー
Microsoft.Extensions.Logging.TraceSource)もあるため、
既存の TraceListener 資産を活かしたまま移行できる。

ライブラリ

補足(現在のライブラリの選択肢): 原文が挙げる 2 つに加え、
Serilog が近年の主流である。

ライブラリ 特徴 現況
Serilog 構造化ログが前提。シンクが豊富 最も使われている
NLog 設定が柔軟。高速 現役
log4net 歴史が長い。Java の log4j 由来 新規採用は減少
ILogger + 標準プロバイダー 追加依存なし 単純な用途ならこれで足りる
// Serilog の例(ILogger の裏に入れる)
builder.Host.UseSerilog((ctx, cfg) => cfg
    .ReadFrom.Configuration(ctx.Configuration)
    .WriteTo.Console()
    .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day));

どれを選んでも、アプリ側は ILogger<T> に書く——
というのが現在の設計指針である。

補足(現在のログ設計の要点): 出力先の選択より、
何をどう書くかの方が実務では効く。

① ログ レベルを使い分ける

レベル 用途
Trace / Debug 開発時のみ。本番では出さない
Information 業務上の節目(注文確定、バッチ開始/終了)
Warning 想定内だが注意すべき事象(リトライ、既定値の使用)
Error 処理が失敗した(例外を伴う)
Critical アプリ全体が継続できない

② 構造化ログにする

// ✗ 文字列を組み立てると、後で検索・集計できない
logger.LogInformation($"Order {id} placed by {userId}");

// ○ テンプレートとして記録される
logger.LogInformation("Order {OrderId} placed by {UserId}", id, userId);

国際化対応項目 で述べた通り、
ログはユーザーの言語ではなく固定の言語で出す(検索性のため)。

③ 個人情報・秘密情報を出さない

パスワード、トークン、クレジットカード番号、
個人を特定できる情報(氏名・住所・メールアドレス)
  → ログに出さない。出すならマスクする

④ スコープで文脈を付ける

using (logger.BeginScope("{TraceId}", Activity.Current?.Id))
{
    // このブロック内のログすべてに TraceId が付く
}

⑤ 分散環境では OpenTelemetry を検討する

複数サービスにまたがる処理を追跡するには、
ログ単体ではなく**トレース(分散トレーシング)**が要る。
.NET には System.Diagnostics.Activity が標準で入っており、
OpenTelemetry で外部の可観測性基盤に送れる
ログ収集いろいろ)。

参考

Microsoft Learn


Tags: 移行, プログラミング, .NET開発

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally