简体   繁体   English

使用Func()参数进行ASP.NET Core Logging

[英]ASP.NET Core Logging with Func() argument

I am using ASP.NET core with NLog, using it as a replacement for the original ASP.NET Core logger with the NLog.Web.AspNetCore nugget package. 我使用ASP.NET核心与NLog,使用它作为原始ASP.NET核心记录器与NLog.Web.AspNetCore块硬件包的替代品。

NLog contains a useful Func() delegate signature that allows to performs arguments evaluation only if the corresponding logging level is enabled: NLog包含一个有用的Func()委托签名,只有在启用相应的日志记录级别时才允许执行参数评估:

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

I am using ASP.NET with NLog, but it sounds like this feature is not available: 我使用ASP.NET和NLog,但听起来这个功能不可用:

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

Before undertaking to write myself a method, I would like to know if I missed something, I have not find anything about such logging methods with a delegate argument using ASP.NET Core with NLog. 在开始给自己写一个方法之前,我想知道如果我错过了一些东西,我没有找到任何关于使用带有NLog的ASP.NET Core的委托参数的日志记录方法。

There is no such thing in the Microsoft.Extensions.Logging abstractions, and the way it is built, it isn't exactly easy to do such a thing. 在Microsoft.Extensions.Logging抽象中没有这样的东西,以及它的构建方式,做这样的事情并不容易。 While you can easily add extension methods to it, and actually all log calls are extension methods, the base Log method is what determines whether or not to log somethings since it is the only thing that actually has access to the configured log level. 虽然您可以轻松地向其添加扩展方法,并且实际上所有日志调用都是扩展方法,但基本Log方法决定是否记录某些事情,因为它是唯一可以实际访问已配置日志级别的事物。

That being said, the logging abstractions to use something that may make it possible to do something similar to this. 话虽这么说,日志抽象使用的东西可以做一些类似的事情。 For that, consider the signature of the ILogger.Log method: 为此,请考虑ILogger.Log方法的签名:

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

As you can see, there isn't actually a string being passed to it, but just a state and a formatter . 正如您所看到的,实际上并没有传递给它的字符串,只是一个state和一个formatter In the default extension methods, the state is a FormattedLogValues object and the formatter is just a method that calls ToString() on the state, ie the FormattedLogValues object. 在默认扩展方法中,状态是FormattedLogValues对象,格式化程序只是在状态上调用ToString()的方法,即FormattedLogValues对象。

The FormattedLogValues is what actually builds the formatted string, and that's also where the structured logging is happening. FormattedLogValues实际上构建了格式化的字符串,这也是结构化日志记录发生的地方。 So it is actually a bad idea to serialize some object in your log message; 因此,在日志消息中序列化某个对象实际上是一个坏主意; you can just pass that directly to the logger. 你可以直接将它传递给记录器。

But what you could do here is provide your own overloads to Log that take a function instead which is then wrapped into some state object that executes the function when ToString() is being called. 但是你可以在这里做的是为Log提供你自己的重载,取而代之的是一个函数,然后将其包装到一个状态对象中,该对象在调用ToString()时执行该函数。

There is not much change in Nlog Implementation for Asp.net core 2.0. Asp.net核心2.0的Nlog实施没有太大变化。

Setup 1: you need to install Nuget package Click here 设置1:你需要安装Nuget包点击这里

Setup 2: you need to create Nlog config file with below configuration. 设置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>

Setup 3: Need to update Startup file. 设置3:需要更新启动文件。

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

Setup 4: We have created custom Nlog manager. 设置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);
 }
}

Custom Event parameter for logging : 用于记录的自定义事件参数

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

Model for NLog logging. NLog日志记录的模型。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM