• 如何定制.NET6.0的日志记录


    在本章中,也就是整个系列的第一部分将介绍如何定制日志记录(系列内容查阅《玩转ASP.NET 6.0框架-序言》)。默认日志记录仅写入控制台或调试窗口,这在大多数情况下都很好,但有时需要写入到文件或数据库,或者,您可能希望扩展日志记录的其他信息。在这些情况下,您需要知道如何更改默认日志记录。

    在本章,我们将介绍以下主题:

    • 配置日志记录
    • 创建自定义日志记录
    • 使用第三方日志框架

    以上主题涉及ASP.NET Core框架的Host层。

    技术要求

    为了演示,我们创建一个ASP.NET Core MVC应用程序。请打开控制台、shellBash终端,然后切换到工作目录,然后使用以下命令创建新的应用程序:

    dotnet new mvc -n LoggingSample -o LoggingSample
    

    Visual Studio中双击打开该项目,或者在控制台中键入以下命令用Visual Studio Code打开该项目:

    cd LoggingSample code .
    

    配置日志记录

    ASP.NET Core的早期版本中(即2.0版之前的版本),日志记录是在Startup.cs配置的。之后Startup.cs文件慢慢简化,许多配置被移动到Program.csWebHostBuilder,日志记录也是在这个时候被移动到WebHostBuilder

    ASP.NET Core 3.1及更高版本的程序,Program.cs文件变得更加通用,IHostBuilder将最先创建,它是引导应用启动的关键(我们将在后面详解IHostBuilder),通过IHostBuilder,我们可以创建IWebHostBuilder用以配置ASP.NET Core

    public class Program {     
        public static void Main(string[] args)
        {         
            CreateHostBuilder(args).Build().Run();     
        }     
        
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => 
            { 
                webBuilder.UseStartup<Startup>();
            }); 
    }
    

    ASP.NET Core 6.0中,Microsoft引入了简化配置的迷你API(minimal API)方法。这种方法不使用Startup文件,而是将所有配置添加到Program.cs文件,如下代码段:

    var builder = WebApplication.CreateBuilder(args); 
    
    //添加服务到容器.
    builder.Services.AddControllersWithViews(); 
    var app = builder.Build(); 
    …
    

    ASP.NET Core,您可以覆盖和自定义几乎所有内容,包括日志记录。IWebHostBuilder有很多扩展方法,允许我们覆盖不同功能的默认行为。要覆盖日志记录的默认设置,我们需要使用ConfigureLogging方法。

    以下代码片段显示的日志记录与上面的ConfigureWebHostDefaults()方法中配置的日志记录几乎完全相同:

    Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{         
        webBuilder.ConfigureLogging((hostingContext, logging) => {
            logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));                 
            logging.AddConsole();                 
            logging.AddDebug();             
        }).UseStartup<Startup>();
    

    使用minimal API方法,我们不再需要ConfigureLogging方法,我们可以直接使用WebApplicationBuilderLogging属性:

    builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging")); 
    builder.Logging.AddConsole(); 
    builder.Logging.AddDebug();
    

    现在我们已经了解了如何配置日志记录,接下来我们看看如何自定义日志记录。

    创建自定义日志记录

    为了演示,我们这里创建一个小而简单的日志记录器,它能够在控制台中使用特定的日志级别对日志条目进行着色。此日志记录称为ColoredConsoleLogger,它会使用LoggerProvider创建。要指定颜色和日志级别,我们还需要添加一个配置类Configuration

    在接下来的代码片段中,将分别创建这三个关键类(ConfigurationLoggerProviderLogger):

    1.ColoredConsoleLoggerConfiguration

    我们创建一个名为CustomLogger.cs的文件中,它与Program.cs位于同一文件夹中,我们在CustomLogger.cs中创建ColoredConsoleLoggerConfiguration,该配置类包含三个可设置的属性:LogLevelEventIdColor

    public class ColoredConsoleLoggerConfiguration 
    {     
        public LogLevel LogLevel { get; set; } = LogLevel.Warning;     
        public int EventId { get; set; } = 0;    
        public ConsoleColor Color { get; set; } = ConsoleColor.Yellow; 
    }
    

    2.ColoredConsoleLoggerProvider

    接下来,我们需要一个提供程序来检索配置并创建实际的日志记录实例

    public class ColoredConsoleLoggerProvider : ILoggerProvider 
    {     
        private readonly ColoredConsoleLoggerConfiguration _config;     
        private readonly ConcurrentDictionary<string, ColoredConsoleLogger> _loggers = new ConcurrentDictionary<string,ColoredConsoleLogger>();     
        
        public ColoredConsoleLoggerProvider (ColoredConsoleLoggerConfiguration config) 
        { 
            _config = config; 
        }     
        
        public ILogger CreateLogger(string categoryName) 
        { 
            return _loggers.GetOrAdd(categoryName,name => new ColoredConsoleLogger(name, _config));     
        }
        
        public void Dispose() 
        {
            _loggers.Clear(); 
        } 
    }
    

    不要忘记引入System.Collections.Concurrent

    3.ColoredConsoleLogger

    第三类是我们真正使用的日志记录器:

    public class ColoredConsoleLogger : ILogger
    {
        private static readonly object _lock = new Object();
        private readonly string _name;
        private readonly ColoredConsoleLoggerConfiguration _config;
    
        public ColoredConsoleLogger(
            string name,
            ColoredConsoleLoggerConfiguration config)
        {
            _name = name;
            _config = config;
        }
    
        public IDisposable BeginScope<TState>(TState state)
        {
            return null;
        }
    
        public bool IsEnabled(LogLevel logLevel)
        {
            return logLevel == _config.LogLevel;
        }
    
        public void Log<TState>(
            LogLevel logLevel,
            EventId eventId,
            TState state,
            Exception exception,
            Func<TState, Exception, string> formatter)
        {
            if (!IsEnabled(logLevel))
            {
                return;
            }
    
            lock (_lock)
            {
                if (_config.EventId == 0 || _config.EventId == eventId.Id)
                {
                    var color = Console.ForegroundColor;
                    Console.ForegroundColor = _config.Color;
                    Console.Write($"{logLevel} - ");
                    Console.Write($"{eventId.Id} - {_name} - ");
                    Console.Write($"{formatter(state, exception)}\n");
                    Console.ForegroundColor = color;
                }
            }
        }
    }
    

    我们现在需要lock(锁定) 控制台的输出——这是因为控制台本身并不是真正的线程安全的,可能出现错误的着色。

    完成后,我们可以将新的记录插入到Program.cs的配置中。

    using LoggingSample;
    
    builder.Logging.ClearProviders();
    var config = new ColoredConsoleLoggerConfiguration
    {
        LogLevel = LogLevel.Information,
        Color = ConsoleColor.Red
    };
    builder.Logging.AddProvider(new ColoredConsoleLoggerProvider(config));
    

    首先需要向引入LoggerSample命名空间。

    using LoggingSample;
    

    如果不想使用现有的日志框架,可以清除之前添加的所有日志框架提供程序

    builder.Logging.ClearProviders();
    

    然后,我们调用AddProvider来添加ColoredConsoleLoggerProvider实例。

    这里配置了不同的日志级别,您可以使用这种方法发送有关错误的电子邮件,或者将调试消息记录到别的日志接收器等等。

    下图显示了日志框架的彩色输出:

    在许多时候,编写自定义日志框架是没有意义的,因为已经有许多优秀的第三方日志记录框架可用,例如ELMAHlog4netNLog

    下面,我们将介绍如何在ASP.NET Core中使用NLog

    使用第三方日志框架NLog

    NLog是最早的一款可用于ASP.NET Core的日志框架,NLog提供了一个日志记录提供程序插件,可以方便地插入ASP.NET Core。(你可以通过NuGet找到NLog

    1.配置Nlog

    我们需要添加一个NLog.Config配置文件,用于定义两个不同的日志记录:

    1. 所有标准消息记录在一个日志文件中;
    2. 而自定义消息记录在另一个文件中
    <targets>
         <!-- 标准消息 -->
         <target xsi:type="File" name="allfile" fileName="C:\git\dotnetconf\001-logging\nlog-all-${shortdate}.log"
                     layout="${longdate}|${event-properties:item=EventId.Id}|${logger}|${uppercase:${level}}|${message} ${exception}" />
    
         
         <!-- 自定义消息 -->
         <target xsi:type="File" name="ownFile-web" fileName="C:\git\dotnetconf\001-logging\nlog-own-${shortdate}.log"
                 layout="${longdate}|${event-properties:item=EventId.Id}|${logger}|${uppercase:${level}}|  ${message} ${exception}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
          
         <target xsi:type="Null" name="blackhole" />
      </targets>
    
      <!-- rules to map from logger name to target -->
      <rules>
        <!--All logs, including from Microsoft-->
        <logger name="*" minlevel="Trace" writeTo="allfile" />
    
        <!--Skip Microsoft logs and so log only own logs-->
        <logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />
        <logger name="*" minlevel="Trace" writeTo="ownFile-web" />
      </rules>
    

    2.引入NuGet包

    然后我们需要NuGet添加NLogASP.NET Core包:

    dotnet add package NLog.Web.AspNetCore
    

    3.将NLogIWebHostBuilder结合使用

    清除ConfigureLogging方法中的其他提供程序,使用UseNLog()方法将NLogIWebHostBuilder结合使用:

    Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => {         
        webBuilder.ConfigureLogging((hostingContext,logging) => {      
            //清除其他提供程序       
            logging.ClearProviders();                 
            logging.SetMinimumLevel(LogLevel.Trace);             
        }).UseNLog().UseStartup<Startup>();     
    });
    

    使用minimal API看起来简单得多:

    using NLog.Web; 
    
    var builder = WebApplication.CreateBuilder(args); 
    
    //清除其他提供程序  
    builder.Logging.ClearProviders(); 
    builder.Logging.SetMinimumLevel(LogLevel.Trace); 
    builder.WebHost.UseNLog();
    

    在这里,您可以根据需要添加任意多个日志记录提供程序。

    回顾 & 思考

    现在,让我们回顾一下本文所涵盖的内容:

    • 配置日志记录
    • 创建自定义日志记录
    • 使用第三方日志框架

    思考:我们应该如何自定义应用的配置?欢迎关注下篇内容《如何自定义.NET 6.0的应用配置》。

  • 相关阅读:
    POJ 1915 简单 广搜题
    poj 2479 最大子数段
    poj 1321 深搜题
    hdu 1024 最大子段和
    .net 学习总结
    [转]SharpDevelop源码分析 (二、主程序+隐藏的初始化)
    工作六年经验分享:软件工程师如何修炼(转)
    Ajax命名空间一个获取指定的页面元素的快捷方式——$get()
    [转]SharpDevelop代码分析 (一、序+基本概念)
    [转]SharpDevelop源码分析 (三、插件系统)
  • 原文地址:https://www.cnblogs.com/jackyfei/p/16287326.html
Copyright © 2020-2023  润新知