Nlog 在.net core中 记录请求上下文的标识符

由于做接口平台需要,清楚的记录下每个请求的日志,
当多个请求同时来访问的时候, 都记录在数据库里面, 会导致日志相互之间混淆.
所以日志在记录的时候还需要增加一个字段用来区分当前请求 “活动唯一标识符” 也就是ActivityId

先看参考答案, 后面是我自己的说明

Currently there is no built in support for CorrelationManager.ActivityId.
However you can create your own layout render which outputs it:

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

You also need to register it with:

 ConfigurationItemFactory.Default.LayoutRenderers
      .RegisterDefinition("activityid", typeof(ActivityIdLayoutRenderer));

Then you can use it in your target definition with:

<target xsi:type="Mongo">
      <!-- ... -->
      <field name="ActivityId" layout="${activityid}" />
</target>

As an alternative solution you can also you the Event Context Layout Renderer to output any custom property like the ActivityId but in this case you have to include it every time when you log something.

//上面的看懂了应该也就明白了, 但是一些具体的细节上面没说清楚.
下面是我自己写的.

对于这个问题需要解决3个小问题.
一,如何在每个请求上下文中,保存唯一的标识符.
二,何时创建这个唯一的标识符
三,唯一标识符 什么规则才能不重复(很简单GUID)
四,如何自动写入到日志中, 而不需要每次自己在Log.Error的时候自己拼装成message

首先 针对这第一个问题 "如何在每个请求上下文中,保存唯一的标识符. "
这个很简单,.net已经为我们提供了这么个属性.

	//初始化唯一标识符
	Trace.CorrelationManager.ActivityId = Guid.NewGuid();

第二个问题, 何时创建这个唯一的标识符
实际上可以在请求开始的任何一个地方, 一般放在页面函数入口第一句话.进行初始化, 只要在日志记录之前就可以了. 也可以写在其它的地方. 反正上下文都是通用的. 一般都是写在中间件里面的.

第四个问题, 如何自动写入到日志中, 而不需要每次自己在Log.Error的时候自己拼装成message

首先需要一个能够取得 “唯一标识符” 的类, 这个类是扩展了Nlog, 相关文档是Nlog的. 如果你是logger4net 的, 那么看一下logger4net 是怎么取的就可以了.

using NLog;
using NLog.Config;
using NLog.LayoutRenderers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WSI
{
    /// <summary>
    /// The trace correlation activity id.
    /// </summary>
    [LayoutRenderer("activityid")]
    [ThreadAgnostic]
    public class TraceActivityIdLayoutRenderer : LayoutRenderer
    { 

        protected override void Append(StringBuilder builder, LogEventInfo logEvent)
        {
            builder.Append(Trace.CorrelationManager.ActivityId.ToString("D", CultureInfo.InvariantCulture));
        }
    }
}

有了这个类还不行, 还需要再启用这个类. 也就是注册一下告诉Nlog 我有这么个类下次遇到${activityid} 这个变量就用我写的TraceActivityIdLayoutRenderer这个类来解析

 //这句话我一般都在Startup.cs 类中的 ConfigureServices方法中第一句话执行.
 public void ConfigureServices(  IServiceCollection services )
 {
	 ConfigurationItemFactory.Default.LayoutRenderers
      .RegisterDefinition("activityid", typeof(TraceActivityIdLayoutRenderer));
}
      

到这一步基本用过Nlog的都知道怎么用的了. 不知道的看下面.
最后一步, 在Nlog.config中. 配置输出这个数值

我的Nlog.config 是这么写的

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false" 
      internalLogLevel="Error"
      internalLogFile="nlog.log"
      >

<!-- 
internalLogLevel="Trace"  Trace|Debug|Info|Warn|Error|Fatal决定内部日志的级别  Off=关闭
internalLogFile="nlog.log"
internalLogFile="nlog.log" 这个开了会写很多的内部信息,用来调试Nlog用. 这里用不到就关闭了
-->
  
  <!-- optional, add some variables
  https://github.com/nlog/NLog/wiki/Configuration-file#variables
  -->
  <variable name="variable1" value="
            ${newline}message:	${message}   
            ${newline}callsite:	${callsite}
            ${newline}stacktrace: ${stacktrace}${newline} 
            ${newline}counter:	${counter}
            ${newline}machinename:	${machinename}
            ${newline}appdomain:	${appdomain}
            ${newline}assembly-version:	${assembly-version}
            ${newline}basedir:	${basedir}
            ${newline}callsite-linenumber:	${callsite-linenumber}
            ${newline}nlogdir:	${nlogdir}
            ${newline}processid:	${processid}
            ${newline}processname:	${processname}
            ${newline}specialfolder:	${specialfolder}" />
  
  <!--
  See https://github.com/nlog/nlog/wiki/Configuration-file
  for information on customizing logging rules and outputs.
   -->
  <targets>
    <!--  <target name="log_file"
            xsi:type="File"
            fileName="${basedir}/LogInformation/${level}_${shortdate}.txt"
            layout="${variable1}" />-->
    <target name="blackhole" xsi:type="Null"  />

    <!--
    sql server 这么写
    <target
      name="log_database"
      xsi:type="Database"
      connectionString="Data Source=.;Initial Catalog=数据库名;Persist Security Info=True;User ID=sa;Password=密码">-->
    
    <!-- my sql 这么写 -->
    
    <target name="log_mysql_database" 
              xsi:type="Database"
              dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"
              connectionString="server=127.0.0.1;Database=wsi5;user id=root;password=123456;SslMode=none" >
       
      <commandText>
        INSERT INTO `ws_log` (
        `Date`,
        `Origin`,
        `Level`,
        `Message`,
        `Detail`,
        `Logger`,
        `Threadid`,
        `Processid`,
        `Activityid`
        ) VALUES (
        now(),
        @origin,
        @logLevel,
        @message,
        @detail,
        @logger,
        @threadid,
        @processid,
        @activityid
        );
      </commandText>
      <!--日志来源-->
      <parameter name="@origin" layout="${callsite}" />
      <!--日志等级-->
      <parameter name="@logLevel" layout="${level}" />
      <!-- 线程id -->
      <parameter name="@threadid" layout="${threadid}" /> 
      <!--日志类-->
      <parameter name="@logger" layout="${logger}" />
      
      <!--日志消息-->
      <parameter name="@message" layout="${message}" />

      <!--System.Diagnostics trace correlation id -->
      <parameter name="@activityid" layout="${activityid}" /> 就是这里用到了.
      
      <!--引用variable1信息-->
      <parameter name="@detail" layout="${variable1}" />
      <parameter name="@processid" layout="${processid}" />

    </target>


    <!-- sqlite 这么写 但是sqlite有并发访问问题 -->
    <!--<target name="log_sqlite_database" xsi:type="Database" keepConnection="false"
              useTransactions="true"
              dbProvider="System.Data.SQLite.SQLiteConnection, System.Data.SQLite" 
              connectionString="Data Source=../WSIConfig.db;Version=3;">


      <commandText>
        INSERT INTO ws_log (
        Date,
        Origin,
        Level,
        Message,
        Detail,
        Logger,
        Threadid,
        Processid
        ) VALUES (
        datetime('now', 'localtime' ),
        @origin,
        @logLevel,
        @message,
        @detail,
        @logger,
        @threadid,
        @processid
        )
      </commandText>
      日志来源 
      <parameter name="@origin" layout="${callsite}" />
       日志等级 
      <parameter name="@logLevel" layout="${level}" />
      线程id 
      <parameter name="@threadid" layout="${threadid}" />
      日志类 
      <parameter name="@logger" layout="${logger}" />

      日志消息
      <parameter name="@message" layout="${message}" />

      引用variable1信息
      <parameter name="@detail" layout="${variable1}" />
      <parameter name="@processid" layout="${processid}" />

    </target>-->
  </targets> 
  
  <rules>
    <logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />
    <logger name="*" writeTo="log_mysql_database" />
  </rules>
</nlog>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值