2012-10-16 139 views
1

我執行一個循環的Parallel.For爲其創建一個日誌文件上的一些操作。但是我需要知道哪個操作創建了一個特定的日誌條目。我嘗試在我的nlog-config中使用{ThreadID},但thread.ID被parallel.for循環重用,因此似乎沒有唯一的標識符。 任何建議如何給每個文件一個唯一的日誌標識符?中並行循環和NLOG

Basic代碼:

Private Sub DoParallel 
Private Logger As NLog.Logger = NLog.LogManager.GetCurrentClassLogger 
Dim ListOfFolder as New List(of String) 
ListOfFolder.add("C:\Test.txt") 

Parallel.ForEach(listOfFolders, Sub(elem As String) 
    logger.warn("Doing stuff, need to know on which elem it is done") 
    End Sub) 
End Sub 

NLOG配置:

layout="${threadid} | ${time} | ${level:uppercase=true} | ${logger} | ${message} | ${exception}" 

回答

1

你可以嘗試使用Trace.CorrelationManager.ActivityId。您可以設置一個值,然後使用自定義NLog LayoutRenderer將該值呈現給輸出日誌。你可以找到一個this here on SO的LayoutRenderer的例子。在最佳答案的中間看看。

下面是從該職位的LayoutRender的代碼(注意,這是書面反對NLOG 1.0,而不是2.0 NLOG它不應該是很難更新)。

[LayoutRenderer("ActivityId")] 
class ActivityIdLayoutRenderer : LayoutRenderer 
{ 
    int estimatedSize = Guid.Empty.ToString().Length; 

    protected override void Append(StringBuilder builder, LogEventInfo logEvent) 
    { 
    builder.Append(Trace.CorrelationManager.ActivityId); 
    } 

    protected override int GetEstimatedBufferSize(LogEventInfo logEvent) 
    { 
    return estimatedSize; 
    } 
} 

你NLog.config會是這個樣子:

告訴NLOG您的NLOG擴展位於:

<extensions> 
    <add assembly="MyNLogExtensions"/> 
</extensions> 

layout="${threadid} | ${ActivityId} | ${time} | ${level:uppercase=true} | ${logger} | ${message} | ${exception}" 

使用你原來的示例代碼,您可以登錄是這樣的:

Private Sub DoParallel 
Private Logger As NLog.Logger = NLog.LogManager.GetCurrentClassLogger 
Dim ListOfFolder as New List(of String) 
ListOfFolder.add("C:\Test.txt") 

Trace.CorrelationManager.ActivityId = Guid.Empty; 
Parallel.ForEach(listOfFolders, Sub(elem As String) 
    Trace.CorrelationManager.ActivityId = Guid.NewGuid(); 
    logger.warn("Doing stuff, need to know on which elem it is done") 
    Trace.CorrelationManager.ActivityId = Guid.Empty; 
    End Sub) 
End Sub 

這應該唯一標識每個記錄的語句,如果你爲m你的動作中的代碼行,所有來自給定執行動作的日誌語句都會被標記爲相同的guid。

如果這種方法對你的作品,你可以很容易地包裹ActivityId設置/在IDisposable接口類和解封使用using語句的過程自動化。

請原諒C#:

public class ActivityIdContext : IDisposable 
{ 
    Guid oldActivityId; 

    public ActivityIdContext(Guid id) 
    { 
    oldActivityId = Trace.CorrelationManager.ActivityId; 
    Trace.CorrelationManager.ActivityId = Guid.NewGuid(); 
    } 

    public ActivityIdContext() : this(Guid.NewGuid()) { } 

    public Dispose() 
    { 
    Trace.CorrelationManager.ActivityId = oldActivityId; 
    } 
} 

然後,你可以附上Parallel.ForEach動作做這樣的事情的身體(同樣,在C#)

Parallel.ForEach(listOfFolders,() => 
{ 
    using(new ActivityIdContext()) 
    { 
    logger.Warn("Hello! I hope the ActivityId helps!"); 
    } 
}); 
+0

哇,看起來很大!我的工作日今天結束,但明天早上我會嘗試你的方法。 我對你的工作印象深刻,非常感謝! –

+0

像魅力一樣工作。非常感謝你! –