在本章中,也就是整个系列的第一部分将介绍如何定制日志记录(系列内容查阅《玩转ASP.NET 6.0框架-序言》)。默认日志记录仅写入控制台或调试窗口,这在大多数情况下都很好,但有时需要写入到文件或数据库,或者,您可能希望扩展日志记录的其他信息。在这些情况下,您需要知道如何更改默认日志记录。
在本章,我们将介绍以下主题:
- 配置日志记录
- 创建自定义日志记录
- 使用第三方日志框架
以上主题涉及ASP.NET Core
框架的Host
层。
技术要求
为了演示,我们创建一个ASP.NET Core MVC
应用程序。请打开控制台、shell
或Bash
终端,然后切换到工作目录,然后使用以下命令创建新的应用程序:
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.cs
的WebHostBuilder
,日志记录也是在这个时候被移动到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
方法,我们可以直接使用WebApplicationBuilder
的Logging
属性:
builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging")); builder.Logging.AddConsole(); builder.Logging.AddDebug();
现在我们已经了解了如何配置日志记录,接下来我们看看如何自定义日志记录。
创建自定义日志记录
为了演示,我们这里创建一个小而简单的日志记录器,它能够在控制台中使用特定的日志级别对日志条目进行着色。此日志记录称为ColoredConsoleLogger
,它会使用LoggerProvider
创建。要指定颜色和日志级别,我们还需要添加一个配置类Configuration
。
在接下来的代码片段中,将分别创建这三个关键类(Configuration
、LoggerProvider
和Logger
):
1.ColoredConsoleLoggerConfiguration
我们创建一个名为CustomLogger.cs
的文件中,它与Program.cs
位于同一文件夹中,我们在CustomLogger.cs
中创建ColoredConsoleLoggerConfiguration
,该配置类包含三个可设置的属性:LogLevel
、EventId
和Color
:
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
实例。
这里配置了不同的日志级别,您可以使用这种方法发送有关错误的电子邮件,或者将调试消息记录到别的日志接收器等等。
下图显示了日志框架的彩色输出:
在许多时候,编写自定义日志框架是没有意义的,因为已经有许多优秀的第三方日志记录框架可用,例如ELMAH
、log4net
和NLog
。
下面,我们将介绍如何在ASP.NET Core
中使用NLog
。
使用第三方日志框架NLog
NLog
是最早的一款可用于ASP.NET Core
的日志框架,NLog
提供了一个日志记录提供程序插件,可以方便地插入ASP.NET Core
。(你可以通过NuGet
找到NLog)
1.配置Nlog
我们需要添加一个NLog.Config
配置文件,用于定义两个不同的日志记录:
- 所有标准消息记录在一个日志文件中;
- 而自定义消息记录在另一个文件中
<targets> <!-- 标准消息 --> <target xsi:type="File" name="allfile" fileName="C:gitdotnetconf 01-loggingnlog-all-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId.Id}|${logger}|${uppercase:${level}}|${message} ${exception}" /> <!-- 自定义消息 --> <target xsi:type="File" name="ownFile-web" fileName="C:gitdotnetconf 01-loggingnlog-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
添加NLog
的ASP.NET Core
包:
dotnet add package NLog.Web.AspNetCore
3.将NLog
与IWebHostBuilder
结合使用
清除ConfigureLogging
方法中的其他提供程序,使用UseNLog()
方法将NLog
与IWebHostBuilder
结合使用:
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的应用配置》。