ASP.NET 带有 Func() 参数的核心日志记录

ASP.NET Core Logging with Func() argument

我将 ASP.NET 核心与 NLog 一起使用,将其用作带有 NLog.Web.AspNetCore 金块包的原始 ASP.NET 核心记录器的替代品。

NLog 包含一个有用的 Func() 委托签名,仅当启用相应的日志记录级别时才允许执行参数评估:

static readonly Logger log = LogManager.GetCurrentClassLogger();
log.Trace(() => request.JsonSerializer.Serialize(body));

我正在使用 ASP.NET 和 NLog,但听起来这个功能不可用:

private ILogger<MyController> log;
log.Trace(() => request.JsonSerializer.Serialize(body));

在着手给自己写一个方法之前,我想知道我是否遗漏了什么,我没有找到任何关于使用 ASP.NET Core with NLog 的委托参数的日志记录方法。

Microsoft.Extensions.Logging 抽象中没有这样的东西,而且它的构建方式,做这样的事情并不容易。虽然您可以轻松地向其添加扩展方法,并且实际上所有日志调用 都是 扩展方法,但基本 Log 方法决定是否记录某些内容,因为它是只有真正有权访问配置的日志级别的东西。

话虽如此,日志记录抽象使用的东西可能使类似的事情成为可能。为此,请考虑 ILogger.Log 方法的签名:

void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)

如您所见,实际上并没有传递给它的字符串,而只是一个 state 和一个 formatter。在默认的扩展方法中,状态是一个 FormattedLogValues 对象,格式化程序只是一个在状态上调用 ToString() 的方法,即 FormattedLogValues 对象。

FormattedLogValues 是实际构建格式化字符串的内容,也是结构化日志记录发生的地方。所以在你的日志消息中序列化一些对象实际上是一个坏主意;您可以直接将其传递给记录器。

但是您在这里可以做的是为 Log 提供您自己的重载,它采用一个函数,然后将其包装到某个状态对象中,该对象在调用 ToString() 时执行该函数。

Asp.net 核心 2.0 的 Nlog 实现没有太大变化。

设置 1: 你需要安装 Nuget 包 Click here

设置 2: 您需要使用以下配置创建 Nlog 配置文件。

<nlog>

  <!-- the targets to write to -->

   <targets>
    <!-- write logs to file  -->
    <target filename="${basedir}/logs/${shortdate}.log" layout="            
             -----------Time Stamp: ${longdate}----------              
             Log Level: ${level}${newline}                        
             Logger Name : ${logger}${newline}            
             Log Message : ${message}${newline}            
             Exception Message: ${event-context:item=ErrorMessage}${newline}      
             Browser Detail:  ${event-context:item=BrowserDetail}${newline}              
             Session Id: ${event-context:item=SessionId}" name="file" xsi:type="File">

 <target br="" connectionstring="${gdc:item=defaultConnection}" dbprovider="Oracle.ManagedDataAccess.Client.OracleConnection, 
 Oracle.ManagedDataAccess, Version=2.0.12.0, Culture=neutral, PublicKeyToken=89b483f429c47342" keepconnection="false" name="database" xsi:type="Database"> 
 commandText="INSERT INTO TableName (LOG_LEVEL,LOGGER_NAME,SESSION_ID,BROWSER_DETAIL) values(:LOGLEVEL,:LOGGERNAME,:SESSIONID,:BROWSERDETAIL)">
      <parameter layout="${level:uppercase=true}" name="LOGLEVEL">
      <parameter layout="${logger}" name="LOGGERNAME">
      <parameter layout="${event-context:item=SessionId}" name="SESSIONID">
      <parameter layout="${event-context:item=BrowserDetail}" name="BROWSERDETAIL">
    </parameter></parameter></parameter></parameter></target>
  </target></targets>

   <rules>
    <!--All logs, including from Microsoft-->
    <logger minlevel="Error" name="*" writeto="file">
    <logger minlevel="Trace" name="*" writeto="database">
    <!--Skip non-critical Microsoft logs and so log only own logs-->
    <logger final="true" maxlevel="Info" name="Microsoft.*">
    <!-- BlackHole -->
  </logger></logger></logger></rules>
</nlog>

设置 3:需要更新启动文件。

NLog.GlobalDiagnosticsContext.Set("defaultConnection", Connection string);    NLog.LogManager.LoadConfiguration(env.ContentRootPath + "\NLog.config");

设置 4:我们已经创建了自定义 Nlog 管理器。

public static class NLogManager {

 public static ILogger _logger = NLog.LogManager.GetCurrentClassLogger();

 public static void InfoLog(NLogData nLogData) {
  LogEventInfo theEvent = new LogEventInfo(LogLevel.Info, NLogManager._logger.Name, nLogData.Message);
  SetLogEventInfo(theEvent, nLogData);
  _logger.Log(theEvent);
 }


 public static void DebugLog(NLogData nLogData) {
  LogEventInfo theEvent = new LogEventInfo(LogLevel.Debug, NLogManager._logger.Name, nLogData.Message);
  SetLogEventInfo(theEvent, nLogData);
  _logger.Log(theEvent);
 }


 public static void ErrorLog(NLogData nLogData) {
  LogEventInfo theEvent = new LogEventInfo(LogLevel.Error, NLogManager._logger.Name, nLogData.Message);
  SetLogEventInfo(theEvent, nLogData);
  _logger.Log(theEvent);
 }
}

用于记录的自定义事件参数:

private static void SetLogEventInfo(LogEventInfo theEvent, NLogData nLogData) {
 theEvent.Properties["SessionId"] = nLogData.SessionId;
 theEvent.Properties["BrowserDetail"] = nLogData.BrowserDetail;
}

NLog 日志记录模型。

public class NLogData {
 public string SessionId {
  get;
  set;
 }
 public string BrowserDetail {
  get;
  set;
 }
}