2017-07-20 1 views
1

私は多くのスレッド(〜50)を実行するアプリケーションを持っています。すべてのスレッドは、データベースから処理するロックを持つ支払いを取得し、処理します。
しかし、50個のスレッドは、ログを読めなくし、混乱させ、膨大なファイルサイズにします。
ここでは、すべての支払いIDに対して個別のファイルにNLog書き込みを行い、支払い処理に関するすべての履歴を1つのファイルに保存するようにします。NLogをスレッドセーフな方法で実行時に別のファイルターゲットに書き込む方法を教えてください。

NLog設定ファイル:今

<?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="file" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard"> 
     <target name="f" xsi:type="File" fileName="C:\LogFiles\Immediate\${shortdate}.server.log" layout="${longdate}|${level}|${processid}|${threadid}|${level:upperCase=true}|${callsite:className=false}|${message}" encoding="utf-8"/> 
    </target> 
    </targets> 
    <rules> 
    <logger name="*" minlevel="Debug" writeTo="file"/> 
    </rules> 
</nlog> 

マイコード:

private static readonly ILogger Logger = LogManager.GetCurrentClassLogger(); // "2017-07-20.log" 

while (!_cancellationToken.IsCancellationRequested) 
{ 
    using (var session = _connectionFactory.GetSession()) 
    { 
     AcquirePaymentWithUpdlockReadpast(session, 
      Logger, // "2017-07-20.log" 
      payment => { 
       if (payment == null) 
        return; 

       Logger.Debug($"Payment {payment.Id} has been acquired for processment"); 

       ProcessPayment(session, Logger, payment); // "2017-07-20.log" 
      }); 
    } 

    Thread.Sleep(50); 
} 

私はそれがあることを期待するもの:私はLogManager.Configurationを使用するいくつかの解決策を見つけた

private static readonly ILogger GeneralLogger = LogManager.GetCurrentClassLogger(); // "2017-07-20.General.log" 

while (!_cancellationToken.IsCancellationRequested) 
{ 
    using (var session = _connectionFactory.GetSession()) 
    { 
     AcquirePaymentWithUpdlockReadpast(session, 
      GeneralLogger, // "2017-07-20.General.log" 
      payment => { 
       if (payment == null) 
        return; 

       var paymentLogger = LogManager.GetCurrentClassLogger(); 
       paymentLogger.FileName = $"Payment-{payment.Id}.log"; // <-- I want this. 
       paymentLogger.Debug($"Payment has been acquired for processment"); 

       ProcessPayment(session, paymentLogger, payment); // "2017-07-20.Payment-123.log" 
      }); 
    } 

    Thread.Sleep(50); 
} 

は、しかし、スレッドセーフではないようです。

答えて

4

たぶん、このような何か:

<?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="file" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard"> 
     <target name="f" xsi:type="File" fileName="C:\LogFiles\Immediate\${shortdate}.server.log" layout="${longdate}|${level}|${processid}|${threadid}|${level:upperCase=true}|${callsite:className=false}|${message}" encoding="utf-8"/> 
    </target> 
    <target name="paymentFile" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard"> 
     <target name="p" xsi:type="File" fileName="C:\LogFiles\Immediate\Payment-${event-properties:PaymentID:whenEmpty=0}.log" layout="${longdate}|${level}|${processid}|${threadid}|${level:upperCase=true}|${callsite:className=false}|${message}" encoding="utf-8"/> 
    </target> 
    </targets> 
    <rules> 
    <logger name="*" minlevel="Debug" writeTo="paymentFile"> 
     <condition="'${event-properties:PaymentID:whenEmpty=0}'!='0'" action="LogFinal" /> 
    </logger> 
    <logger name="*" minlevel="Debug" writeTo="file"/> 
    </rules> 
</nlog> 

次に、あなたはこのようにロギングを行うことができます(NLog-流暢で改善することができる):

LogEventInfo theEvent = new LogEventInfo(LogLevel.Debug, $"Payment has been acquired for processment"); 
theEvent.Properties["PaymentID"] = payment.Id; 
Logger.Debug(theEvent); 

代替ソリューションは、このようなことができます

var paymentLogger = LogManager.GetLogger($"Payment-{payment.Id}"); 
paymentLogger.Debug($"Payment has been acquired for processment") 

さらに、logger-fi

<logger name="Payment-*" minlevel="Debug" writeTo="paymentFile" /> 

そしてこれにpaymentFileのファイル名を変更します:これまでLTERロルフ・クリステンセンの答えに

fileName="C:\LogFiles\Immediate\{logger}.log" 
+0

ありがとうございました。 2番目のアプローチは私を助けました、私はこの方法でロガー名を使用することはできませんでした。しかし、私は 'name'プロパティを持つ少し短い解決法を見つけました。それはあなたにとって興味深いかもしれません:) –

1

おかげで、私が使用する第二のアプローチを使用していたが、同様の、より短い解決策を発見しましたnameプロパティ:

<?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="all" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard"> 
     <target name="f" xsi:type="File" fileName="C:\LogFiles\${shortdate}.All.log" layout="${longdate}|${level}|${processid}|${threadid}|${level:upperCase=true}|${callsite:className=false}|${message}" encoding="utf-8"/> 
    </target> 
    <target name="perLoggerName" xsi:type="AsyncWrapper" queueLimit="10000" overflowAction="Discard"> 
     <target name="f" xsi:type="File" fileName="C:\LogFiles\${shortdate}.${logger}.log" layout="${longdate}|${level}|${processid}|${threadid}|${level:upperCase=true}|${callsite:className=false}|${message}" encoding="utf-8"/> 
    </target> 
    </targets> 
    <rules> 
    <logger name="*" minlevel="Debug" writeTo="all"/> 
    <logger name="Document-*" minlevel="Debug" writeTo="perLoggerName"/> 
    <logger name="Job-*" minlevel="Debug" writeTo="perLoggerName"/> 
    </rules> 
</nlog> 
+1

" perLoggerName "の下にラップされたファイルターゲットにopenFileCacheSize =" 25 "とopenFileCacheTimeout =" 600 "各ロガー名に対して保留中のファイル状態を取得します)。 "perLoggerName"の下に "p"( "f"の代わりに)にラップされたファイルターゲットの名前を変更することを検討してください。 –

関連する問題