【C#】TraceSwitchとDebugクラスで重要度に応じたログ出力を実装する

目次

概要

Visual Studioでの開発中に、変数の状態や処理の通過を確認するためのデバッグログ出力機能の実装です。

単にすべてのログを出力するのではなく、TraceSwitch を利用して「エラーのみ」「警告まで」「詳細情報すべて」といった出力レベルを動的に制御する仕組みを構築します。これにより、必要な情報だけを効率的にフィルタリングして確認できるようになります。

仕様(入出力)

  • 入力
    • ログメッセージ(string
    • ログレベル(TraceLevel
  • 出力
    • Visual Studioの「出力」ウィンドウ(デバッグ)へのテキスト表示
  • 動作
    • 設定されたスイッチのレベル(Off, Error, Warning, Info, Verbose)に応じて、出力するか否かを自動判定します。
    • リリースビルド(Release)では、これらのデバッグコードは自動的に削除されます。

基本の使い方

System.Diagnostics.Debug クラスを使用します。WriteLineIf メソッドを使うことで、条件判定と出力を1行で記述できます。

// 条件(第1引数)が true の場合のみメッセージが出力される
bool isDebugMode = true;
Debug.WriteLineIf(isDebugMode, "デバッグモードで実行中です");

コード全文

「在庫管理システム」を想定し、処理の進行状況や発生した問題をレベル別に制御して出力するコンソールアプリケーションです。

using System;
using System.Diagnostics;

class Program
{
    // ログレベル制御用スイッチの定義
    // displayName: "InventoryLog", description: "在庫システムのログ制御"
    private static TraceSwitch _logSwitch = new TraceSwitch("InventoryLog", "Stock Management Log Switch");

    static void Main()
    {
        // 1. ログレベルの設定
        // ここで指定したレベル「以上」の重要度を持つログが出力されます。
        // 例: Info に設定すると、Error, Warning, Info が出力され、Verbose は無視されます。
        _logSwitch.Level = TraceLevel.Info;

        Console.WriteLine($"現在のログレベル: {_logSwitch.Level}");
        Console.WriteLine("--- 処理開始 ---");

        // 商品データの処理シミュレーション
        UpdateStock("Item-A001", 10);
        UpdateStock("Item-B999", -5); // 警告ケース
        UpdateStock("Item-Err", 0);   // エラーケース

        Console.WriteLine("--- 処理終了 ---");
    }

    static void UpdateStock(string productId, int quantity)
    {
        // [Verbose] 詳細情報: ループ内や変数の細かい値など(最も優先度が低い)
        Debug.WriteLineIf(_logSwitch.TraceVerbose, 
            $"[VERBOSE] {productId} の数量チェック開始: {quantity}");

        // [Info] 情報: 処理の開始・終了など正常系の記録
        Debug.WriteLineIf(_logSwitch.TraceInfo, 
            $"[INFO] {productId} の更新処理を実行します。");

        if (quantity < 0)
        {
            // [Warning] 警告: 続行可能だが不審な点
            Debug.WriteLineIf(_logSwitch.TraceWarning, 
                $"[WARNING] {productId} の数量が負の値です({quantity})。補正が必要かもしれません。");
        }

        if (productId == "Item-Err")
        {
            // [Error] エラー: 処理の中断や失敗
            Debug.WriteLineIf(_logSwitch.TraceError, 
                $"[ERROR] {productId} はデータベースに存在しません。処理をスキップします。");
            return;
        }

        // 正常終了時の詳細ログ
        Debug.WriteLineIf(_logSwitch.TraceVerbose, 
            $"[VERBOSE] {productId} の更新が正常に完了しました。");
    }
}

実行後の出力ウィンドウ表示例

[INFO] Item-A001 の更新処理を実行します。
[INFO] Item-B999 の更新処理を実行します。
[WARNING] Item-B999 の数量が負の値です(-5)。補正が必要かもしれません。
[INFO] Item-Err の更新処理を実行します。
[ERROR] Item-Err はデータベースに存在しません。処理をスキップします。

TraceLevel.Info 設定のため、[VERBOSE] は出力されません。

カスタムポイント

  • 構成ファイルからの制御
    • app.config ファイルにスイッチの設定を記述することで、プログラムを再コンパイルせずにログレベルを変更(例:本番トラブル調査時に Verbose へ変更など)できます。
  • カテゴリの活用
    • Debug.WriteLine(message, category) を使用すると、出力ウィンドウ上で「[SQL] …」「[UI] …」のように分類表示でき、フィルタリングが容易になります。

注意点

  1. DebugとTraceの違い
    • Debug クラスのメソッドは、デフォルトで Debug ビルド構成でのみコンパイルされます。本番(Release)環境でもログを残したい場合は System.Diagnostics.Trace クラスを使用してください。
  2. リスナーの登録
    • Visual Studio以外(テキストファイルやコンソール)にログを出力したい場合は、Debug.Listeners.Add(new TextWriterTraceListener(...)) などでリスナーを追加する必要があります。
  3. パフォーマンスへの影響
    • WriteLineIf はメソッド呼び出し自体は残るため、引数の文字列生成($ による文字列補間など)は評価されます。極端に重い文字列処理を行う場合は、if (_logSwitch.TraceVerbose) ブロックで囲むのが安全です。

応用

TraceLevelのフィールドと意味

TraceSwitch.Level に設定する値と、それによって有効になるプロパティ(出力条件)の対応表です。

フィールド意味有効になる判定プロパティ
Off0出力なしなし
Error1エラーのみTraceError
Warning2エラー、警告TraceError, TraceWarning
Info3エラー、警告、情報TraceError, TraceWarning, TraceInfo
Verbose4すべての詳細情報TraceError, TraceWarning, TraceInfo, TraceVerbose

まとめ

TraceSwitch を導入することで、開発フェーズや調査対象に応じてログの細かさを柔軟に調整できる堅牢なデバッグ環境が整います。単に WriteLine を羅列するのではなく、重要度(レベル)を意識した実装を行うことで、膨大なログの中から真に必要な情報だけを即座に見つけ出せるようになります。リリースビルドでは自動的に無効化される特性を活かし、開発中は最大限の詳細情報を出力する設定にしておくのが効果的です。

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

この記事を書いた人

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

目次