Problem

前回はログの出力パスを動的に設定する方法を書きました。
ですが、あの方法は Variablesプロパティ に設定した値がロガー全体で共有されてしまいます。
私がやりたかったのは、ログの設定は同一の設定を使うがファイルパスだけ変更したい。ただし、ファイルパスは、プロセスやインスタンス毎に変更したい、という要求でした。

プロセスやインスタンスが常に一定であるならば、NLog.config に必要な数だけ設定を追加すれば済みますが、ファイルパスだけ異なるのに、似たような記述を増やすのは、面倒です。

ここでは、ロガー毎にVariablesプロパティの値を独立して設定する方法を記します。

Solution

まずは、NLog.configを変更します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target
name="LogFile"
xsi:type="File"
layout="${longdate} [${uppercase:${level:padding=-5}}] ${message} ${exception:format=tostring}"
fileName="${basedir}Logs\${var:runtime}\${date:format=yyyyMMdd}.log"
encoding="UTF-8"
archiveFileName="${basedir}Logs\archives\${var:runtime}\archive.{#}.log"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7"
header="[Start Logging]"
footer="[End Logging]${newline}" />
</targets>

<rules>
<logger name="Log" minlevel="Trace" writeTo="LogFile" />
</rules>
</nlog>

ここは前回と同じです。

次に、ソース部分です。

1
2
3
4
var factory = new LogFactory();
var logger = factory.GetLogger("Log");
logger.Factory.Configuration.Variables.Add("runtime", "test");
factory.ReconfigExistingLoggers();

前回と異なるのは、LogManager.GetLogger メソッドを使うのではなく、LogFactoryのインスタンスを自分で生成し、LogFactory.GetLogger メソッドを呼び出している箇所です。
logger.Factory プロパティを見るとわかりますが、このプロパティは、LogFactory.GetLogger メソッドから取得している場合、常に同一の値を指すため、当然Configuration.Variables プロパティの中身も一致してしまいます。

これにより、下記のように、Loggerのインスタンス毎に出力先を簡単に切り替えることができます。

1
2
3
4
5
6
7
8
9
10
11
12
var factory1 = new LogFactory();
var logger1 = factory1.GetLogger("Log");
logger1.Factory.Configuration.Variables.Add("runtime", "test1");
factory1.ReconfigExistingLoggers();

var factory2 = new LogFactory();
var logger2 = factory2.GetLogger("Log");
logger2.Factory.Configuration.Variables.Add("runtime", "test2");
factory2.ReconfigExistingLoggers();

logger1.Warn("message"); // test1フォルダ配下に出力
logger2.Warn("message"); // test2フォルダ配下に出力