C# 日付ごとにファイルを分けたログ出力

# 業務アプリにログ出力は欠かせないよね！

アプリケーションの実行状況をログに出力すると障害発生時の原因調査にとっても役に立ちます。
特に長時間の複雑な処理の途中にネットワークやデータベース操作が絡む場合、処理の区切りごとに進行状況をログ出力すると例外が発生して止まったときに原因が特定しやすくなるので好んで使います。

```csharp
Trace.WriteLine("データベース接続");
//いろいろ
Trace.WriteLine("ふんわり情報登録中");
//いろいろ
Trace.WriteLine("データベース切断");
```

ログの最後が "ふんわり情報登録中" だったなら・・・
「ふんわり情報」の中にデータベースの制約に違反するようなデータが入っていたのかな？なんてね(　´∀｀)
なにも下準備しなければ、Trace.WriteLine は出力ウィンドウにメッセージが表示されるだけですけど。

# カスタムの TraceListener クラス

私がいただくお仕事では、わりと時間が掛かってエラーが避けられない処理を書くことが多いので、以下の機能を持った専用のログ出力クラスを作って利用しています。

* Trace.WriteLine メソッドでメッセージを出力できる
* メッセージの先頭に自動で出力日時がつく
* ログファイルは日付単位で分割される
* 一定のサイズを超えると別のファイルに出力する

TraceListener を継承したカスタムクラスを作成して登録すると、Trace.WriteLine メソッドが呼ばれたときに、カスタムクラスの WriteLine メソッドが呼ばれるので、そこでファイルに書き込んだりメール送信したりいろいろなことが出来ます。

```csharp:DailyLoggingTraceListener.cs
public class DailyLoggingTraceListener : TraceListener
{
    public override void WriteLine(string message)
    {
        // ファイル出力とか色々な処理
    }
}
```

```csharp:Program.cs
static void Main()
{
    // トレースリスナーを登録する
    Trace.Listeners.Add(new DailyLoggingTraceListener());
    Trace.WriteLine("＼コロンビア！／");
}
```

カスタムの TraceListener クラスはアプリケーション構成ファイルに定義することでも登録出来るんですけど、いまいち理解仕切れていないので省略(￣▽￣；)

# フォームアプリなら画面にも表示したい

出力ウィンドウと同じようにテキストボックスに表示するクラスも使っています。

```csharp:Form1.cs
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Trace.Listeners.Add(new TextBoxTraceListener(textBox1));
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Trace.WriteLine("＼コロンビア！／");
    }
}
```

![2014-08-25_145917.png](https://qiita-image-store.s3.amazonaws.com/0/52104/26a0194a-43c9-5c85-f46a-2196c8b016fd.png)

# もちろん両方一緒に使えるよ

以下のサンプルでは実行ファイルのあるフォルダに log フォルダを作って、その中に "日付_連番.log" 形式でファイルを出力します。

```csharp:Form1.cs
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        var dailyLogging = new DailyLoggingTraceListener()
        {
            OutputDirectory = Application.StartupPath + @"\log\",   // 既定値 Application.StartupPath
            FileNameFormat = "{0:yyyyMMdd}_{1}.log",                // 既定値 {0:yyyyMMdd}_{1}.txt
            DatetimeFormat = "{0:MM/dd HH:mm}",                     // 既定値 {0:MM/dd HH:mm:ss}
        };
        Trace.Listeners.Add(dailyLogging);
        Trace.Listeners.Add(new TextBoxTraceListener(textBox1));
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Trace.WriteLine("＼コロンビア！／");
    }
}
```

![2014-08-25_154138.png](https://qiita-image-store.s3.amazonaws.com/0/52104/47cdb351-0ae9-b20a-afcb-cd4c45ff0f10.png)


# ソース

GitHub に置いたので興味のある方は使ってみてください。
TextBoxWriter は WinForms 前提なので WPF だと修正しないとダメです。
素人の独学なのでソースのクオリティは保証できません＞＜

* [DailyLoggingTraceListener.cs](https://github.com/tomochan154/toy-box/blob/master/DailyLoggingTraceListener.cs)
* [TextBoxTraceListener.cs](https://github.com/tomochan154/toy-box/blob/master/TextBoxTraceListener.cs)
* [TextBoxWriter.cs](https://github.com/tomochan154/toy-box/blob/master/TextBoxWriter.cs)

GitHub の操作の仕方が分からなくて2時間以上掛かった・・・orz
CVS と SVN にはなんとか慣れたけど Git はエラーが出るとなにがなんだか分からなくて辛い；；
常に１人で開発しているので、あんまりバージョン管理使わないで何とかなってしまうから、余計にいつまで経っても覚えない悪循環(´つω；`)
日付フォルダバージョン管理システムっていいよね（＞＜）