在自定义NLog目标中检索HttpContext

Mat*_*ttW 5 c# logging nlog httpcontext

我可能在这里错过了一些基本的知识-但是否可以HttpContext.Current在自定义NLog事件中检索?

我试图给每个请求一个唯一的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

wag*_*ghe 0

这篇关于使用 HttpContext.Current 的文章文章可能会有所帮助。对您来说,关键可能是当控制权从一个线程传递到另一个 HttpContext 时,新线程中的 Current 可以为 null。

这是来自此处的另一个问题/答案,描述了 HttpContext.Current 在 Web 服务上下文中为 null。接受的答案建议在 web.config 文件中打开 ASP.Net 兼容性。

我不知道其中任何一个都会有所帮助,但它们可能会有所帮助。我通过谷歌搜索“HttpContext.Current is null”找到了它们,这产生了相当多的点击量。我很少进行 ASP.NET 开发,因此我无法根据我自己的个人经验对 HttpContext.Current 进行真正的评论。

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

ActivityId 的一个很好的特性是它从父线程“流动”到子线程(包括线程池线程)。我认为它与任务和并行操作配合得很好。效果很好,这意味着在父线程中设置的 ActivityId 在子线程中具有预期值。

ActivityId 没有 LayoutRenderer,但编写一个很容易。请参阅此处的示例(针对 NLog 1.0 编写):

最有用的 NLog 配置

我很确定不再需要“EstimatedBufferSize”的东西,所以类似的东西可能会起作用:

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

如果您采用此方法,您可能会考虑向 ActivityIdLayoutRenderer 添加 Format 属性,以允许您指定 guid 格式。请参阅这个答案(来自我)。它包含许多有关使用指南的有用信息。

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

请参阅此源文件(在 NLog 的 git 存储库中),了解如何实现和使用此类 Format 属性的示例:

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