【问题标题】:How to setup a per request global variable for NLog?如何为 NLog 设置每个请求的全局变量?
【发布时间】:2017-06-24 13:25:36
【问题描述】:

我正在努力为我们的 Web 应用程序以最有用的方式设置 NLogs

我的思考过程如下

  • 新请求已启动
  • 生成了一个新的 guid
  • 使用 guid 记录 webapi 事件
  • 使用 guid 记录服务层事件
  • 为下一个请求生成一个新的 guid

这样可以很容易地跟踪从请求开始到结束的全系列事件

如果线程影响此解决方案,我也会并行运行服务方法

我已尝试设置以下内容,但 ${activityid} 似乎没有延续到输出

https://github.com/NLog/NLog/wiki/Trace-Activity-Id-Layout-Renderer

【问题讨论】:

    标签: c# .net logging nlog


    【解决方案1】:

    将值添加到您的httpContext 并使用 NLog 读取它。

    例如

    HttpContext.Current.Items["myvariable"] = 123;
    

    在你的 NLog.config 中

    ${aspnet-item:variable=myvariable} - produces "123"
    

    More examples in the docs

    为此,您需要 NLog.web 或 NLog.web.aspnetcore! Install instructions

    【讨论】:

    • 我遵循了您建议的答案,但第二天我遇到了问题 HttpContext.Current 在正在进行的线程中为空。您认为这种方法容易受到攻击吗?
    【解决方案2】:

    这就是我最终要做的事情

    我设置了一个新类,以使请求数据在系统的任何地方都可以轻松访问

    public static class HttpContextRequestData
    {
        public static string RequestGuid
        {
            get
            {
                if (HttpContext.Current.Items["RequestGuid"] == null)
                    return string.Empty;
                else
                    return HttpContext.Current.Items["RequestGuid"] as string;
            }
            set
            {
                HttpContext.Current.Items["RequestGuid"] = value;
            }
        }
    
    
        public static DateTime RequestInitiated
        {
            get
            {
                if (HttpContext.Current.Items["RequestInitiated"] == null)
                    return DateTime.Now;
                else
                    return Convert.ToDateTime(HttpContext.Current.Items["RequestInitiated"]);
            }
            set
            {
                HttpContext.Current.Items["RequestInitiated"] = value;
            }
        }
    }
    

    然后我设置 global.asax 为每个请求设置一个 Guid。我还添加了一些基本规则来记录请求长度,如果超过 1 分钟则致命

        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpContextRequestData.RequestGuid = Guid.NewGuid().ToString();
            HttpContextRequestData.RequestInitiated = DateTime.Now;
            logger.Info("Application_BeginRequest");
        }
    
        void Application_EndRequest(object sender, EventArgs e)
        {
            var requestAge = DateTime.Now.Subtract(HttpContextRequestData.RequestInitiated);
    
            if (requestAge.TotalSeconds <= 20)
                logger.Info("Application_End, took {0} seconds", requestAge.TotalSeconds);
            else if (requestAge.TotalSeconds <= 60)
                logger.Warn("Application_End, took {0} seconds", requestAge.TotalSeconds);
            else
                logger.Fatal("Application_End, took {0} seconds", requestAge.TotalSeconds);
        }
    

    然后,为了让事情变得更简单,我设置了一个自定义 NLog LayoutRender,以便 RequestGuid 自动添加到日志记录事件中,而无需记住包含它

    [LayoutRenderer("RequestGuid")]
    public class RequestGuidLayoutRenderer : LayoutRenderer
    {
        protected override void Append(StringBuilder builder, LogEventInfo logEvent)
        {
            builder.Append(HttpContextRequestData.RequestGuid);
        }
    }
    

    在NLog.config中注册了RequestGuidLayoutRenderer

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

    最后添加到我的目标配置中

    <target name="AllLogs" xsi:type="File" maxArchiveFiles="30" fileName="${logDirectory}/AllLogs.log" layout="${longdate}|${RequestGuid}|${level:uppercase=true}|${message}|${exception:format=tostring}"
    

    【讨论】:

      猜你喜欢
      • 2012-08-20
      • 1970-01-01
      • 2019-12-24
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多