在本章中,也就是整個系列的第一部分將介紹如何定製日誌記錄(系列內容查閱《玩轉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:\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
新增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的應用配置》。