【问题标题】:Retrieving HttpContext in a Custom NLog Target在自定义 NLog 目标中检索 HttpContext
【发布时间】:2014-03-25 04:53:34
【问题描述】:

我可能在这里遗漏了一些基本的东西 - 但是可以在自定义 NLog 事件中检索 HttpContext.Current 吗?

我试图为每个请求提供一个唯一的 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);
    }
}

【问题讨论】:

    标签: c# logging nlog httpcontext


    【解决方案1】:

    现在在 NLog 目标中检索 HTTP 上下文更容易(适用于 ASP.NET 和 ASP.NET Core)

    1. 安装NLog.Web (ASP.NET) 或NLog.Web.AspNetCore (ASP.NET Core) 包
    2. 对于 ASP.NET 核心,请关注ASP.NET Core - NLog setup
    3. AspNetLayoutRendererBase(命名空间NLog.Web.LayoutRenderers)继承
    4. 通过调用var context = HttpContextAccessor.HttpContext;获取请求

    例子:

    [LayoutRenderer("aspnet-sessionid")]
    [ThreadSafe]
    public class AspNetSessionIdLayoutRenderer : AspNetLayoutRendererBase
    {
        protected override void DoAppend(StringBuilder builder, LogEventInfo logEvent)
        {
            var context = HttpContextAccessor.HttpContext;
            var contextSession = context?.Session();
            if (contextSession == null)
            {
                 InternalLogger.Debug("HttpContext Session Lookup returned null");
                 return;
            }
    
            builder.Append(contextSession.SessionID); // ASP.NET Core: contextSession.Id
        }
    }
    

    PS:目前有很多 ASP.NET (Core) 的预定义渲染器:https://nlog-project.org/config/?tab=layout-renderers&search=aspnet

    【讨论】:

      【解决方案2】:

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

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

      我不知道这两种方法是否会有所帮助,但它们可能会有所帮助。我通过谷歌搜索“HttpContext.Current is null”找到了它们,这产生了相当多的点击量。我做过很少的 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 的有用信息。

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

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

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

      【讨论】:

        【解决方案3】:

        如果您的自定义目标应该捕获一个(或多个)特定于上下文的值,那么我建议您的目标继承自 TargetWithContext(或 AsyncTaskTarget)。

        它提供了设置和捕获contextproperty-items 的能力。可以分配布局以捕获上下文详细信息的位置。可从 HttpContext 轻松获得的可能上下文详细信息示例:

        https://nlog-project.org/config/?tab=layout-renderers&search=package:nlog.web.aspnetcore

        有关编写自定义目标的更多详细信息:

        https://github.com/NLog/NLog/wiki/How-to-write-a-custom-target-for-structured-logging

        https://github.com/NLog/NLog/wiki/How-to-write-a-custom-async-target

        顺便说一句。已经存在这个很好地继承自 AsyncTaskTarget 的自定义目标:

        https://www.nuget.org/packages/NLog.Extensions.AzureCosmosTable/

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-26
          • 2013-06-08
          • 1970-01-01
          相关资源
          最近更新 更多