web-dev-qa-db-ja.com

実行時にNLogターゲットファイル名を更新する

私のアプリケーションでは、1日に数千のドキュメントに取り組んでいます。場合によっては、いくつかのログ、ドキュメントごとに1つのログが欲しいです。次に、特定のターゲットについて、実行時に出力ファイル名(およびファイル名のみ)を変更します。

Webの周りで、プログラミングによってターゲットを作成する方法を見つけました。プログラミングによってファイル名を更新したいだけです。以下のコードを試してみました。受け取ったエラーは、「LayoutRenderが見つかりません 'logDirectory'です。

何か案が ?

おかげで、

var target = (FileTarget)LogManager.Configuration.FindTargetByName("logfile");
target.FileName = "${logDirectory}/file2.txt";

LoggingConfiguration config = new LoggingConfiguration();
var asyncFileTarget = new AsyncTargetWrapper(target);
config.AddTarget("logfile", asyncFileTarget);

LogManager.Configuration = config;

設定ファイルは:

  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <variable name="logDirectory" value="C:/MyLogs"/>
    <targets>
      <target name="logfile" xsi:type="File" layout="${date:format=dd/MM/yyyy HH\:mm\:ss.fff}|${level}|${stacktrace}|${message}" fileName="${logDirectory}/file.txt" />
    </targets>

    <rules>
      <logger name="*" minlevel="Info" writeTo="logfile" />
    </rules>    
  </nlog>
23
Kris-I

ReconfigExistingLoggersメソッドを試してください:

var target = (FileTarget)LogManager.Configuration.FindTargetByName("logfile");
target.FileName = "${logDirectory}/file2.txt";
LogManager.ReconfigExistingLoggers();

ドキュメントに書かれているように:

以前にGetLoggerによって返されたすべてのロガーをループします。ターゲットとフィルターリストを再計算します。すべてのロガーが適切に構成されていることを確認するために、プログラムで構成を変更した後に役立ちます。

[〜#〜]編集[〜#〜]

カスタムレイアウトレンダラーを使用してみてください: web.configから構成設定値を取得するためのNLog構成ファイル

23
Tony

実行時にLogDirectoryを変更する必要がない場合は、次のようにすることができます。

target.FileName = "${var:logDirectory}\\file2.txt");

実行時にlogDirectoryを変更する必要がある場合は、GDCを使用します。

https://github.com/NLog/NLog/wiki/Gdc-layout-renderer

NLog.GlobalDiagnosticsContext.Set("logDirectory","C:\Temp\");

その後、次のレイアウトを使用できます。

target.FileName = "${gdc:item=logDirectory}\\file2.txt";
6
Rolf Kristensen

Tony's NLog Async(<targets async="true">)を使用すると、ソリューションが機能しないようです。 FileTargetを取得するには、ラッパーターゲットを使用する必要がありました。それ以外の場合は、多くのエラーが発生します。 NLog 2.1を使用しています。

if (LogManager.Configuration != null && LogManager.Configuration.ConfiguredNamedTargets.Count != 0)
{
    Target target = LogManager.Configuration.FindTargetByName("yourFileName");
    if (target == null)
    {
        throw new Exception("Could not find target named: " + "file");
    }

    FileTarget fileTarget = null;
    WrapperTargetBase wrapperTarget = target as WrapperTargetBase;

    // Unwrap the target if necessary.
    if (wrapperTarget == null)
    {
        fileTarget = target as FileTarget;
    }
    else
    {
        fileTarget = wrapperTarget.WrappedTarget as FileTarget;
    }

    if (fileTarget == null)
    {
        throw new Exception("Could not get a FileTarget from " + target.GetType());
    }

    fileTarget.FileName = "SetFileNameHere";
    LogManager.ReconfigExistingLoggers();
}

これも設定ファイルを変更するのではなく、ランタイム値を変更するだけです。したがって、以下のコードを使用して、設定ファイルを手動で新しい値に編集します。

var nlogConfigFile = "NLog.config";
var xdoc = XDocument.Load(nlogConfigFile);
var ns = xdoc.Root.GetDefaultNamespace();
var fTarget = xdoc.Descendants(ns + "target")
         .FirstOrDefault(t => (string)t.Attribute("name") == "yourFileName");
fTarget.SetAttributeValue("fileName", "SetFileNameHere");
xdoc.Save(nlogConfigFile);
6
Baddack

これにこだわった人のために、私は最終的に解決策を見つけました。実行時にいくつかのsyslogターゲット設定を更新しようとしましたが、何も機能しませんでした。構成を更新するだけでは機能せず、Configurationオブジェクトをリセットする必要があります。これは、次のように簡単です。

LogManager.Configuration = LogManager.Configuration;

これにより、内部イベントが発生し、実際に更新された構成が使用されます。

1
Mark

エラーが発生する理由は、NLogが "logDirectory"キー名について何も知らないためです。自分で実装するか(手順 here を参照)、または here から事前定義されたものを使用します。

次に、 ここ からの指示を使用して、実行時にNLogターゲットを変更できます。

1
kravasb

これでうまくいきました。

using NLog;
using NLog.Targets;
using NLog.Targets.Wrappers;

var target = LogManager.Configuration.FindTargetByName("logfile");
var asyncTarget = target as AsyncTargetWrapper;
var fileTarget = asyncTarget.WrappedTarget as FileTarget;
var file = fileTarget.FileName;
var archiveFile = fileTarget.ArchiveFileName;

// FileNameおよびArchiveFileNameはタイプLayoutです。 ToStringは文字列を表します。それを変更して、割り当て直すことができます。文字列に変換するときに追加される余分な一重引用符を削除するには、.Trim( '\' ')を忘れずに追加してください。

0
spiairsh

私もたまたまあなたの質問に合った答えを書きました

本質的には、構成をrewriteしようとする代わりに、必要なファイル名を動的に選択できるようにする構成を作成する方がよいでしょう。


ユースケースに合わせた例:

Logger myLog = LogManager.GetLogger(name);
LogLevel level = LogLevel.Error;
string message = "This is an error message!";

この情報をLogEventInfoオブジェクトに変換します。

LogEventInfo logEvent = new LogEventInfo(level , myLog.Name, message);

次に、このイベントにプロパティを追加できます(文字列インデックスは自由に選択できます)。

logEvent.Properties["CustomFileName"] = "mycustomfilename";

次に、ログに書き込みます。

myLog.Log(logEvent);

ここで興味深いのは、NLog構成でNlogのドキュメントが「レイアウト」値として参照する任意のフィールドでこのカスタムプロパティを使用できることです

プロパティにアクセスするには、レイアウトで${event-properties:item=CustomFileName}を使用します。例えば:

<target xsi:type="File" 
        name="file" 
        fileName="${basedir}/logs/${event-properties:item=CustomFileName}.log"
        layout="${message}" />

投稿された例に従って、このメッセージはmycustomfilename.logファイルに記録されます。これにより、logEvent.Properties["CustomFileName"]値を使用したいファイル名に設定することで、ターゲットファイルを自由に動的に切り替えることができます。

これをさらに最適化できることに注意してください。ファイル名の一部しか選択できない

追加の利点は、これを機能させるために、構成ファイルに1つのターゲットと1つのルールのみが必要なことです。

0
Flater