【C#】コンソールアプリでログとエラー出力を適切に分離する実装手法

目次

概要

コンソールアプリケーション開発において、正常な実行ログとエラー情報を同じ出力先(標準出力)に混在させることは、運用の観点から推奨されません。 .NET では Console.Error プロパティを利用することで、OSレベルで提供される「標準エラー出力(stderr)」へデータを送信できます。これにより、ログファイルへのリダイレクト時にエラーだけを画面に残したり、別のファイルへ記録したりといった柔軟な制御が可能になります。

仕様(入出力)

  • 入力
    • エラーとして通知したいメッセージ(string
  • 出力
    • 標準エラー出力ストリームへの書き込み
  • 特性
    • 画面上の見た目は標準出力と同じですが、パイプライン処理やリダイレクト時の扱いが異なります。

基本の使い方

通常の Console.WriteLine が標準出力(stdout)であるのに対し、Console.Error.WriteLine は標準エラー出力(stderr)へ書き込みます。

// 正常系のログ(標準出力)
Console.WriteLine("処理を開始しました。");

// 異常系のログ(標準エラー出力)
Console.Error.WriteLine("ファイルが見つかりません。");

コード全文

正常な処理フローのメッセージと、例外発生時のエラーメッセージを、それぞれ適切なストリームに出力し分けるコンソールアプリケーションの実装です。

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("--- データ処理バッチ ---");

        try
        {
            // 1. 標準出力 (stdout) への書き込み
            // 処理の進行状況など、正常なログを出力します。
            // シェルで "> log.txt" とリダイレクトした場合、これらはファイルに保存されます。
            Console.WriteLine("[INFO] 設定ファイルを読み込んでいます...");
            Console.WriteLine("[INFO] データベース接続を確認中...");

            // エラーをシミュレーションするためのメソッド呼び出し
            ProcessData();

            Console.WriteLine("[INFO] 全ての処理が正常に完了しました。");
        }
        catch (Exception ex)
        {
            // 2. 標準エラー出力 (stderr) への書き込み
            // プログラムの異常終了や警告などを出力します。
            // リダイレクト時もコンソール画面にメッセージが残るため、オペレーターが気づきやすくなります。
            Console.Error.WriteLine($"[ERROR] 予期せぬ障害が発生しました: {ex.Message}");
            
            // 異常終了を示すために終了コードを 1 に設定
            Environment.ExitCode = 1;
        }
    }

    static void ProcessData()
    {
        // 何らかの処理...
        // ここでは強制的に例外を発生させます
        throw new InvalidOperationException("外部APIへの接続がタイムアウトしました。");
    }
}

実行結果例

--- データ処理バッチ ---
[INFO] 設定ファイルを読み込んでいます...
[INFO] データベース接続を確認中...
[ERROR] 予期せぬ障害が発生しました: 外部APIへの接続がタイムアウトしました。

カスタムポイント

  • 出力の即時反映
    • Console.Error.AutoFlush = true; を設定すると、書き込みのたびにバッファがフラッシュされます。アプリがクラッシュする直前のログも確実に記録したい場合に有効です。
  • リダイレクト動作の確認
    • 実行時に MyApp.exe > output.log とすると、[INFO] 行はファイルに行き、[ERROR] 行だけが画面に残ります。エラーもファイルに含めたい場合は MyApp.exe > output.log 2>&1 と記述します。

注意点

  1. 視認性の限界
    • デフォルトのコンソール画面では、標準出力も標準エラー出力も同じ文字色で表示されるため、見た目での区別はつきません。区別が必要な場合は、後述の応用例のように色を変更する必要があります。
  2. パフォーマンス
    • Console.Error への大量書き込みは、同期I/Oであるため処理速度に影響を与える可能性があります。デバッグログなどを大量に出す場合は注意してください。

応用

エラー出力時のみ文字色を赤くする拡張メソッド

標準エラー出力への書き込み時だけ自動的にコンソールの文字色を変更し、オペレーターが視覚的にエラーを認識しやすくするヘルパー実装です。

using System;

public static class ConsoleHelper
{
    public static void WriteError(string message)
    {
        // 現在の色を退避
        var originalColor = Console.ForegroundColor;
        
        // エラー用の色(赤)に変更して出力
        Console.ForegroundColor = ConsoleColor.Red;
        Console.Error.WriteLine(message);
        
        // 元の色に復元
        Console.ForegroundColor = originalColor;
    }
}

// 使用例: ConsoleHelper.WriteError("重大なエラーです");

まとめ

Console.Error.WriteLine を活用することで、システムの運用監視やログ収集において、正常ログとエラーログを明確に分離して扱うことが可能になります。特にクラウド環境やコンテナ基盤(Docker/Kubernetes)では、標準出力と標準エラー出力を個別に収集する仕組みが一般的であるため、このメソッドを用いて適切に出力先を振り分ける実装が推奨されます。

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

この記事を書いた人

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

目次