読者です 読者をやめる 読者になる 読者になる

TomoProgの技術書

底辺プログラマーが達人プログラマーになるまで

C#で自作ロガーを作ってみる

C#

皆さん
こんにちは、こんばんは
TomoProgです。

最近WindowsPCが新しくなり、気分がいいTomoProgです。

以前Pythonで自作ロガーを作成した以下の記事を書きました。
tomoprog.hatenablog.com

今回はC#で自作ロガーを作ってみたので、それについて書いていこうと思います。

それでは頑張っていきましょう。

自作ロガーの仕様を決める

まずは自作ロガーの仕様を決めていきます。
何を出力しようか考えましたが、とりあえず以下の4つを出力することにしました。

  • 日時
  • ファイル名
  • 行番号
  • 任意のログメッセージ

ほぼPythonの自作ロガーと同じです。

ログファイルに出力する内容を取得する

仕様も決まったので、早速作成していきましょう。

日時の取得

まずは日時から取得していきます。
C#で現在の日時を取得する場合はDateTime構造体のNowプロパティを参照すると簡単に取得できます。

string dateTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff");

ToStringメソッドに書式を渡してあげることで、様々な形の日時文字列を作ることができます。

書式については以下のサイトを参考にさせていただきました。
note.phyllo.net

ファイル名の取得

次はファイル名を取得してみます。
呼び出し元のファイル名を取得するにはStackTraceクラスを使用します。

StackTrace st = new StackTrace(1, true);
string fileName = st.GetFrame(0).GetFileName()

StackTraceクラスについてですが、
第1引数に1を指定することで呼び出し元からファイル名や行番号を解析できるようです。
また、第2引数にはファイル名、行番号をキャプチャする場合はtrueを指定します。

なんとなく分かるような分からないような・・・

第1引数に1を指定したため、GetFrameの引数には0(呼び出し元のフレーム)を指定しています。

詳しくは以下のサイトを参考にしてみてください。
StackTrace コンストラクター (Int32, Boolean) (System.Diagnostics)

行番号の取得

最後に行番号です。
とは言っても行番号はファイル名と同じやり方で取得できます。

StackTrace st = new StackTrace(1, true);
string lineNumber = st.GetFrame(0).GetFileLineNumber().ToString();

これで呼び出し元の行番号が取得できます。

Loggerクラスを作成する

欲しい情報はすべて手に入ったので、実際にLoggerクラスを作って呼び出してみます。

Loggerクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;

namespace MyUtility
{
    public class Logger
    {
        /// <summary>
        /// ファイルパス
        /// </summary>
        string _filePath;

        /// <summary>
        /// エンコーディング
        /// </summary>
        Encoding _enc;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="logFilePath">ログファイルパス(ログファイル名込み)</param>
        /// <param name="enc">ログファイルのエンコーディング</param>
        public Logger(string logFilePath, Encoding enc)
        {
            _filePath = logFilePath;
            _enc = enc;
        }
        
        /// <summary>
        /// ログファイル書き込み
        /// </summary>
        /// <param name="writeContents">書き込み内容</param>
        public void Write(string writeContents)
        {
            StackTrace st = new StackTrace(1, true);
            string dateTime = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff");
            string fileName = Path.GetFileName(st.GetFrame(0).GetFileName());
            string lineNumber = st.GetFrame(0).GetFileLineNumber().ToString();
            //string methodName = st.GetFrame(0).GetMethod().ToString();

            writeContents = (dateTime + " " + fileName + " Line:" + lineNumber + " " + writeContents);

            try
            {
                using (StreamWriter sw = new StreamWriter(_filePath, true, _enc))
                {
                    sw.WriteLine(writeContents);
                }
            }
            catch
            {
                // 握りつぶす
            }
        }
    }
}
呼び出し用Mainクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Diagnostics;
using MyUtility;

namespace ConsoleApp1
{
    class Program
    {
        static Logger l = new Logger("test.txt", Encoding.UTF8);
        static void Main(string[] args)
        {
            l.Write("test文字列");
            method1("method1を呼び出したよ。");
        }
        static void method1(string str)
        {
            l.Write(str);
        }
    }
}
実際に実行した結果
2017/02/26 21:25:04.198 Program.cs Line:17 test文字列
2017/02/26 21:25:04.201 Program.cs Line:22 method1を呼び出したよ。

例外処理などかなり雑な部分はありますが、
ログファイルへ書き込むことができました!!

まとめ

  • 自作ロガーを作成できた
  • StackTraceクラスを使うことで呼び出し元の情報を取得できる

今回はC#で自作ロガーを作成してみました。
実際に使用する際にはログレベルなども必要かもしれませんが、個人で使用する分には十分な機能だと思います。

GitHubにもアップしていますので、使いたい方おられましたらご自由にどうぞ。
github.com


それではまた。

TomoProg

GitHub
TomoProg (TomoProg) · GitHub

Twitter
TomoProg (@TomoHelloxxx) | Twitter