2014-02-23 24 views
2

我可能会在这里丢失一些基本的东西 - 但是可以在自定义NLog事件中检索HttpContext.Current吗?在自定义NLog目标中检索HttpContext

我试图给每个请求一个独特的Guid,以便我可以将日志消息关联到单个事件(即将单个请求的每个日志事件绑定在一起)。所以,我想将这个Guid存储在HttpContext.Current.Items中,然后在NLog目标中检索它并将其包含在日志消息中。

这是我的目标例子,我想访问HttpContext.Current:

[Target("AzureTableTarget")] 
public class AzureTableTarget : TargetWithLayout 
{ 

    public AzureTableTarget() 
    { 
     _appSettings = IoCResolver.Get<IAppSettings>(); 
    } 

    protected override void Write(LogEventInfo logEvent) 
    { 
     var correlationId = HttpContext.Current; //This is always null 

     var batchOperation = new TableBatchOperation(); 
     CxLogEventBuilder.Build(_appSettings, logEvent).ForEach(batchOperation.Insert); 
     _loggingTable.ExecuteBatchAsync(batchOperation); 
    } 
} 

回答

0

这篇文章Working with HttpContext.Current可能的帮助。对你来说,关键可能是当控制从一个线程传递到另一个线程时,新线程中的HttpContext.Current可能为空。

这是另一个question/answer从这里SO描述HttpContext.Current在Web服务的上下文中为空。接受的答案建议在web.config文件中打开ASP.Net兼容性。

我不知道这些会有帮助,但他们可能会。我发现他们的搜索结果是“HttpContext.Current为空”,这产生了相当多的点击。我做了很少的ASP.NET开发,所以我不能从我自己的个人经验中评论HttpContext.Current。

鉴于你的用例,我建议你看看System.Diagnostics.CorrelationManager.ActivityId

ActivityId的一个很好的功能是它从父线程“流”到子线程(包括线程池线程)。我认为它适用于任务和并行操作。正常工作意味着在父线程中设置的ActivityId在子线程中具有期望的值。

ActivityId没有LayoutRenderer,但写起来很容易。在这里看到一个例子(书面反对NLOG 1.0):

Most useful NLog configurations

我敢肯定的是, “EstimatedBufferSize” 的东西不再需要,所以像可能会工作:

[LayoutRenderer("ActivityId")] 
class ActivityIdLayoutRenderer : LayoutRenderer 
{ 
    protected override void Append(StringBuilder builder, LogEventInfo logEvent) 
    { 
    builder.Append(Trace.CorrelationManager.ActivityId); 
    } 
} 

如果你走这条路线,你可能会考虑将一个Format属性添加到ActivityIdLayoutRenderer中,以允许你指定guid格式。看到这个答案(来自我)。它包含了很多有关使用GUID的有用信息。

https://github.com/NLog/NLog/blob/master/src/NLog/LayoutRenderers/GuidLayoutRenderer.cs

NewGuid vs System.Guid.NewGuid().ToString("D");

对于如何实施和使用这种格式属性的例子来看看这个源文件(在NLOG的git仓库)