[C#] Log4netを使うサンプル

ざっと書き下しておきます。

Apache log4net: Home
http://logging.apache.org/log4net/
Log4NET – TSCWiki
http://www.tokyosoft.co.jp/tscwiki/index.php/Log4NET
【C#】【VS2010】Visual Studio 2010で Log4net を使う – プログラム の個人的なメモ – Yahoo!ブログ
http://blogs.yahoo.co.jp/dk521123/20264938.html

■環境構築

Visual Studio 2012 と 64bit という環境なので、これで。

Download Apache log4net
http://logging.apache.org/log4net/download_log4net.cgi
から、log4net-1.2.11-src.zip のほうをダウンロードして、展開。
D:toolslog4net-1.2.11 へコピー。
D:toolslog4net-1.2.11srclog4net.vs2010.sln を開く。

対象のフレームワークを「.NET Framework 4.5」に変更

image

ビルドをすると

D:toolslog4net-1.2.11buildbinnet2.0debuglog4net.dll

に作成される。

■ログ出力のサンプル

適当なプロジェクトを作って、参照設定で D:toolslog4net-1.2.11buildbinnet2.0debuglog4net.dll を追加。

image

app.config を開いて、Log4NET – TSCWiki にある「プロジェクトの組み込み」の部分をそのまま組み入れ。
作成するログファイル名だけを

<param name="File" value="D:toolslog4net-1.2.11outlog-file.txt" />

のように書き換えておく。

出力設定自体は、

    <root>
      <!-- ここではINFOログのレベルを指定 -->
      <level value="DEBUG" />
      <!-- 下記の何れかを使用
      <level value="OFF " />
      <level value="FATAL" />
      <level value="ERROR" />
      <level value="WARN" />
      <level value="INFO" />
      <level value="ALL" />
      -->
      <!-- どのログ出力先を使用するか -->
      <appender-ref ref="LogToFile" />
      <appender-ref ref="DayRollingLogToFile" />
      <!-- 複数指定可能 -->
    </root>

のように、通常のログ「LogToFile」と、日付でローリング「DayRollingLogToFile」で出力。

ソリューションエクスプローラーで「AssemblyInfo.cs」を開いて、

image

[assembly: log4net.Config.XmlConfigurator(Watch = true)] の記述を追加する。

// アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
// アセンブリに関連付けられている情報を変更するには、
// これらの属性値を変更してください。
[assembly: AssemblyTitle("SampleLog4Net")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SampleLog4Net")]
[assembly: AssemblyCopyright("Copyright c  2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: log4net.Config.XmlConfigurator(Watch = true)]

適当に画面を作って、

image

namespace SampleLog4Net
{
	public partial class Form1 : Form
	{
		private static readonly log4net.ILog log =
		log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

		public Form1()
		{
			InitializeComponent();
		}

		private void button1_Click(object sender, EventArgs e)
		{
			log.Info("INFOで出力");
		}
	}
}

な風に書く。log4net.ILog log なところをプライベートフィールドで。

■サンプルを実行してみる

こんな風に時刻とクラス名、ログが出ます。

image

出力自体は、app.config に書いた

      <level value="ERROR" />
      <level value="WARN" />
      <level value="INFO" />
      <level value="DEBUG" />

のところで切り替えます。通常のデバッグ時には、DEBUG を有効にしておいて、リリース時には、ERROR だけを有効にするとか規約で決めればよいでしょう。

■動的にログ出力レベルを変更する

[assembly: log4net.Config.XmlConfigurator(Watch = true)]

を設定することで、実行時にも *.config を変えることができる…という記事があるのですが、.NET 4.5 だと動きませんでした。なので、直接ソースの中から操作します。

var rep = log4net.LogManager.GetRepository() as log4net.Repository.Hierarchy.Hierarchy;
rep.Threshold = log4net.Core.Level.Info;

ソースを見ると、出力レベルの判断は、Hierarchy プロパティで判断しているのでこれを書き換えます。この例では、Info 以上の出力(DEBUG出力は出ない)設定にしています。これはグローバル変数なので、全体に影響しますね。

■出力時のファイル名と行番号を出力する

こんな感じで拡張メソッドを作っておけばOK。

VS2012 の場合は、CallerMemberName 属性を使って生成、VS2010 の場合は StackFrame クラスを使って生成します。ここでは、Debug しか作っていませんが、同じように Info とかを作ればよいし、適当にフォーマットすれば使えるかと。

public static class ILogEx
{
    /// <summary>
    /// VS2012の場合
    /// </summary>
    /// <param name="log"></param>
    /// <param name="msg"></param>
    /// <param name="name"></param>
    /// <param name="path"></param>
    /// <param name="num"></param>
    public static void DebugL(this log4net.ILog log, string msg,
        [CallerMemberName] string name = "",
        [CallerFilePath] string path = "",
        [CallerLineNumber] int num = 0)
    {
        log.Debug(string.Format("{0} {1} {2} {3}", name, path, num, msg));
    }
    /// <summary>
    /// VS2010の場合
    /// </summary>
    /// <param name="log"></param>
    /// <param name="msg"></param>
    public static void DebugN(this log4net.ILog log, string msg)
    {
        var sf = new StackFrame(1, true);
        string name = sf.GetMethod().ToString();
        string path = sf.GetFileName();
        int num = sf.GetFileLineNumber();
        log.Debug(string.Format("{0} {1} {2} {3}", name, path, num, msg));
    }
}

~ 追記
と思ったものの、もともと log4net にはログの形式で %location を使えばファイル名などが出力できるので、これで良いかと。
連載:VBで実践! 外部コンポーネント活用術:オープンソースのロギング・サービス「log4net」を使う (3/4) – @IT あたりを参考に

        <param name="ConversionPattern" value="%date [%thread] %-5level %logger - %location %message%newline" />

■サンプル

サンプルコードはこちら
SampleLog4Net-v0.1-src.zip をダウンロードしてください。

カテゴリー: C# パーマリンク