C#中日志模块,.Net提供了一套日志接口,但是内置的日志提供程序只有Console、Debug、EventSource、EventLog,没有常规的日志提供程序。微软推荐了一些第三方日志提供程序库,我这里选择了NLog。
NLog的配置文件固定命名NLog.config,为xml格式文件。其配置的文件名如果使用内置date字段,则日志文件名会根据配置的date的format级别进行切分,比如配置到秒级别:fileName="${date:format="yyyyMMdd-HHmmss"}" ,对应日志文件会在秒级别切割,我习惯与使用不切割日志,同时又习惯与使用启动日期时间来命名日志文件,于是使用了参数来配置日志文件名。
NLog对于不同类型的工程配置稍有不同,这里主要分为桌面应用(包含控制台)与web应用。
桌面使用的程序库:
这里还需要指定拷贝配置文件到输出目录:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
namespace TestNLog
{
internal class Program
{
static void Main(string[] args)
{
//配置变量:供NLog配置文件使用,用于fileName
LogManager.Configuration.Variables["ProgramName"] = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
LogManager.Configuration.Variables["StartTime"] = DateTime.Now.ToString("yyyyMMdd-HHmmss");
//初始化NLog配置
var configuration = new ConfigurationBuilder().Build();
//使用NLog
var logger = LoggerFactory.Create(builder => builder.AddNLog(configuration)).CreateLogger();
string message1 = "Hello, World!";
logger.LogTrace(message1);
logger.LogDebug(message1);
logger.LogInformation(message1);
logger.LogWarning(message1);
logger.LogError(message1);
logger.LogCritical(message1);
Thread.Sleep(3000);
string message2 = "Hello, World2!";
logger.LogTrace(message2);
logger.LogDebug(message2);
logger.LogInformation(message2);
logger.LogWarning(message2);
logger.LogError(message2);
logger.LogCritical(message2);
LogManager.Shutdown();
}
}
}
控制台输出:
20230821-17:10:13.312 INFO Hello, World! - TestNLog.Program.Main:21
20230821-17:10:13.354 WARN Hello, World! - TestNLog.Program.Main:22
20230821-17:10:13.354 ERROR Hello, World! - TestNLog.Program.Main:23
20230821-17:10:13.354 FATAL Hello, World! - TestNLog.Program.Main:24
20230821-17:10:16.368 INFO Hello, World2! - TestNLog.Program.Main:31
20230821-17:10:16.368 WARN Hello, World2! - TestNLog.Program.Main:32
20230821-17:10:16.368 ERROR Hello, World2! - TestNLog.Program.Main:33
20230821-17:10:16.368 FATAL Hello, World2! - TestNLog.Program.Main:34
文件输出:TestNLog.20230821-171013.log
20230821-17:10:13.312 INFO Hello, World! - TestNLog.Program.Main:21
20230821-17:10:13.354 WARN Hello, World! - TestNLog.Program.Main:22
20230821-17:10:13.354 ERROR Hello, World! - TestNLog.Program.Main:23
20230821-17:10:13.354 FATAL Hello, World! - TestNLog.Program.Main:24
20230821-17:10:16.368 INFO Hello, World2! - TestNLog.Program.Main:31
20230821-17:10:16.368 WARN Hello, World2! - TestNLog.Program.Main:32
20230821-17:10:16.368 ERROR Hello, World2! - TestNLog.Program.Main:33
20230821-17:10:16.368 FATAL Hello, World2! - TestNLog.Program.Main:34
需要添加DependencyInjection包。
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog;
using NLog.Extensions.Logging;
namespace TestNLog2
{
public class Runner
{
private readonly ILogger _logger;
public Runner(ILogger logger)
{
_logger = logger;
}
public void DoAction(string name)
{
_logger.LogTrace("LogTrace: Doing hard work! {Action}", name);
_logger.LogDebug("LogDebug: Doing hard work! {Action}", name);
_logger.LogInformation("LogInformation: Doing hard work! {Action}", name);
_logger.LogWarning("LogWarning: Doing hard work! {Action}", name);
_logger.LogError("LogError: Doing hard work! {Action}", name);
_logger.LogCritical("LogCritical: Doing hard work! {Action}", name);
}
}
internal class Program
{
static void Main(string[] args)
{
//配置变量:供NLog配置文件使用,用于fileName
LogManager.Configuration.Variables["ProgramName"] = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
LogManager.Configuration.Variables["StartTime"] = DateTime.Now.ToString("yyyyMMdd-HHmmss");
//初始化NLog配置
var config = new ConfigurationBuilder().Build();
var servicesProvider = new ServiceCollection()
.AddTransient()
//使用NLog
.AddLogging(loggingBuilder => loggingBuilder.AddNLog(config))
.BuildServiceProvider();
var runner = servicesProvider.GetRequiredService();
runner.DoAction("Action1");
Thread.Sleep(3000);
runner.DoAction("Action2");
LogManager.Shutdown();
}
}
}
控制台输出:
20230821-17:19:21.227 INFO LogInformation: Doing hard work! Action1 - TestNLog2.Runner.DoAction:20
20230821-17:19:21.278 WARN LogWarning: Doing hard work! Action1 - TestNLog2.Runner.DoAction:21
20230821-17:19:21.278 ERROR LogError: Doing hard work! Action1 - TestNLog2.Runner.DoAction:22
20230821-17:19:21.278 FATAL LogCritical: Doing hard work! Action1 - TestNLog2.Runner.DoAction:23
20230821-17:19:24.279 INFO LogInformation: Doing hard work! Action2 - TestNLog2.Runner.DoAction:20
20230821-17:19:24.279 WARN LogWarning: Doing hard work! Action2 - TestNLog2.Runner.DoAction:21
20230821-17:19:24.279 ERROR LogError: Doing hard work! Action2 - TestNLog2.Runner.DoAction:22
20230821-17:19:24.279 FATAL LogCritical: Doing hard work! Action2 - TestNLog2.Runner.DoAction:23
文件输出:TestNLog2.20230821-171921.log
20230821-17:19:21.227 INFO LogInformation: Doing hard work! Action1 - TestNLog2.Runner.DoAction:20
20230821-17:19:21.278 WARN LogWarning: Doing hard work! Action1 - TestNLog2.Runner.DoAction:21
20230821-17:19:21.278 ERROR LogError: Doing hard work! Action1 - TestNLog2.Runner.DoAction:22
20230821-17:19:21.278 FATAL LogCritical: Doing hard work! Action1 - TestNLog2.Runner.DoAction:23
20230821-17:19:24.279 INFO LogInformation: Doing hard work! Action2 - TestNLog2.Runner.DoAction:20
20230821-17:19:24.279 WARN LogWarning: Doing hard work! Action2 - TestNLog2.Runner.DoAction:21
20230821-17:19:24.279 ERROR LogError: Doing hard work! Action2 - TestNLog2.Runner.DoAction:22
20230821-17:19:24.279 FATAL LogCritical: Doing hard work! Action2 - TestNLog2.Runner.DoAction:23
Web应用使用的程序包如下:
分别创建了BlazorServer跟ASP.NET Core Web应用进行测试,使用起来基本差不多,要注意的是添加NLog要在AddRazorPages之前,否则在Razor页面注入Logger会失败,建议把UseNLog放在第一位。
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using NLog;
using NLog.Web;
using TestNLog3.Data;
namespace TestNLog3
{
public class Program
{
public static void Main(string[] args)
{
//配置变量:供NLog配置文件使用,用于fileName
LogManager.Configuration.Variables["ProgramName"] = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
LogManager.Configuration.Variables["StartTime"] = DateTime.Now.ToString("yyyyMMdd-HHmmss");
//初始化NLog配置
LogManager.Setup().LoadConfigurationFromAppSettings();
var builder = WebApplication.CreateBuilder(args);
//使用NLog
builder.Host.UseNLog();
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
}
}
}
@page "/counter"
@inject ILogger _logger
Counter
Counter
Current count: @currentCount
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
_logger.LogTrace("IncrementCount");
_logger.LogDebug("IncrementCount");
_logger.LogInformation("IncrementCount");
_logger.LogWarning("IncrementCount");
_logger.LogError("IncrementCount");
_logger.LogCritical("IncrementCount");
}
}
文件输出:TestNLog3.20230821-173855.log
20230821-17:38:56.663 INFO User profile is available. Using 'C:\Users\pobo\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest. - Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager.GetFallbackKeyRepositoryEncryptorPair:0
20230821-17:38:57.123 INFO Now listening on: https://localhost:7061 - Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync:0
20230821-17:38:57.123 INFO Now listening on: http://localhost:5289 - Microsoft.AspNetCore.Hosting.GenericWebHostService.StartAsync:0
20230821-17:38:57.123 INFO Application started. Press Ctrl+C to shut down. - Microsoft.Extensions.Hosting.Internal.ConsoleLifetime.OnApplicationStarted:0
20230821-17:38:57.133 INFO Hosting environment: Development - Microsoft.Extensions.Hosting.Internal.ConsoleLifetime.OnApplicationStarted:0
20230821-17:38:57.133 INFO Content root path: D:\Workspace\C#\TestNLog3 - Microsoft.Extensions.Hosting.Internal.ApplicationLifetime.NotifyStarted:0
20230821-17:38:59.778 INFO Request starting HTTP/2 GET https://localhost:7061/ - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:38:59.830 INFO Executing endpoint '/_Host' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:38:59.966 INFO Route matched with {page = "/_Host"}. Executing page /_Host - Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker+Log.ExecutingAction:0
20230821-17:38:59.979 INFO Executing an implicit handler method - ModelState is Valid - Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync:0
20230821-17:38:59.979 INFO Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult. - Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync:0
20230821-17:39:00.315 INFO Executed page /_Host in 344.9807ms - Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker+Log.ExecutedAction:0
20230821-17:39:00.319 INFO Executed endpoint '/_Host' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:00.348 INFO Request starting HTTP/2 GET https://localhost:7061/_framework/blazor.server.js - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.348 INFO Request starting HTTP/2 GET https://localhost:7061/_framework/aspnetcore-browser-refresh.js - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.348 INFO Request finished HTTP/2 GET https://localhost:7061/ - - - 200 - text/html;+charset=utf-8 560.4594ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.351 INFO Request starting HTTP/2 GET https://localhost:7061/_vs/browserLink - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.351 INFO Request starting HTTP/2 GET https://localhost:7061/css/bootstrap/bootstrap.min.css - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.351 INFO Request starting HTTP/2 GET https://localhost:7061/TestNLog3.styles.css - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.351 INFO Request starting HTTP/2 GET https://localhost:7061/css/site.css - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.378 INFO Request finished HTTP/2 GET https://localhost:7061/_framework/aspnetcore-browser-refresh.js - - - 200 11988 application/javascript;+charset=utf-8 29.3564ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.378 INFO The file /TestNLog3.styles.css was not modified - Microsoft.AspNetCore.StaticFiles.StaticFileContext.ServeStaticFile:0
20230821-17:39:00.378 INFO The file /css/bootstrap/bootstrap.min.css was not modified - Microsoft.AspNetCore.StaticFiles.StaticFileContext.ServeStaticFile:0
20230821-17:39:00.378 INFO The file /css/site.css was not modified - Microsoft.AspNetCore.StaticFiles.StaticFileContext.ServeStaticFile:0
20230821-17:39:00.378 INFO The file /_framework/blazor.server.js was not modified - Microsoft.AspNetCore.StaticFiles.StaticFileContext.ServeStaticFile:0
20230821-17:39:00.383 INFO Request finished HTTP/2 GET https://localhost:7061/TestNLog3.styles.css - - - 304 - text/css 32.2087ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.383 INFO Request finished HTTP/2 GET https://localhost:7061/_framework/blazor.server.js - - - 304 - text/javascript 34.5748ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.383 INFO Request finished HTTP/2 GET https://localhost:7061/css/site.css - - - 304 - text/css 32.2552ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.383 INFO Request finished HTTP/2 GET https://localhost:7061/css/bootstrap/bootstrap.min.css - - - 304 - text/css 32.2040ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.383 INFO Request starting HTTP/2 GET https://localhost:7061/css/open-iconic/font/css/open-iconic-bootstrap.min.css - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.383 INFO The file /css/open-iconic/font/css/open-iconic-bootstrap.min.css was not modified - Microsoft.AspNetCore.StaticFiles.StaticFileContext.ServeStaticFile:0
20230821-17:39:00.396 INFO Request finished HTTP/2 GET https://localhost:7061/css/open-iconic/font/css/open-iconic-bootstrap.min.css - - - 304 - text/css 7.3314ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.412 INFO Request starting HTTP/2 GET https://localhost:7061/_blazor/initializers - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.412 INFO Executing endpoint 'Blazor initializers' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:00.433 INFO Executed endpoint 'Blazor initializers' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:00.433 INFO Request finished HTTP/2 GET https://localhost:7061/_vs/browserLink - - - 200 - text/javascript;+charset=UTF-8 82.5276ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.433 INFO Request finished HTTP/2 GET https://localhost:7061/_blazor/initializers - - - 200 - application/json;+charset=utf-8 22.3937ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.470 INFO Request starting HTTP/2 GET https://localhost:7061/css/open-iconic/font/fonts/open-iconic.woff - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.470 INFO The file /css/open-iconic/font/fonts/open-iconic.woff was not modified - Microsoft.AspNetCore.StaticFiles.StaticFileContext.ServeStaticFile:0
20230821-17:39:00.470 INFO Request finished HTTP/2 GET https://localhost:7061/css/open-iconic/font/fonts/open-iconic.woff - - - 304 - application/font-woff 1.3265ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.495 INFO Request starting HTTP/2 POST https://localhost:7061/_blazor/negotiate?negotiateVersion=1 - 0 - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.495 INFO Executing endpoint '/_blazor/negotiate' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:00.508 INFO Executed endpoint '/_blazor/negotiate' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:00.508 INFO Request finished HTTP/2 POST https://localhost:7061/_blazor/negotiate?negotiateVersion=1 - 0 - 200 316 application/json 13.7178ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:00.508 INFO Request starting HTTP/2 CONNECT https://localhost:7061/_blazor?id=wZWacy4asZs8XbiMDjBuqQ - - - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:00.508 INFO Executing endpoint '/_blazor' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:03.724 INFO IncrementCount - TestNLog3.Pages.Counter.IncrementCount:20
20230821-17:39:03.946 WARN IncrementCount - TestNLog3.Pages.Counter.IncrementCount:21
20230821-17:39:03.946 ERROR IncrementCount - TestNLog3.Pages.Counter.IncrementCount:22
20230821-17:39:03.963 FATAL IncrementCount - TestNLog3.Pages.Counter.IncrementCount:23
20230821-17:39:03.963 INFO IncrementCount - TestNLog3.Pages.Counter.IncrementCount:20
20230821-17:39:03.963 WARN IncrementCount - TestNLog3.Pages.Counter.IncrementCount:21
20230821-17:39:03.963 ERROR IncrementCount - TestNLog3.Pages.Counter.IncrementCount:22
20230821-17:39:04.009 FATAL IncrementCount - TestNLog3.Pages.Counter.IncrementCount:23
20230821-17:39:04.051 INFO IncrementCount - TestNLog3.Pages.Counter.IncrementCount:20
20230821-17:39:04.053 WARN IncrementCount - TestNLog3.Pages.Counter.IncrementCount:21
20230821-17:39:04.053 ERROR IncrementCount - TestNLog3.Pages.Counter.IncrementCount:22
20230821-17:39:04.053 FATAL IncrementCount - TestNLog3.Pages.Counter.IncrementCount:23
20230821-17:39:04.228 INFO IncrementCount - TestNLog3.Pages.Counter.IncrementCount:20
20230821-17:39:04.228 WARN IncrementCount - TestNLog3.Pages.Counter.IncrementCount:21
20230821-17:39:04.243 ERROR IncrementCount - TestNLog3.Pages.Counter.IncrementCount:22
20230821-17:39:04.243 FATAL IncrementCount - TestNLog3.Pages.Counter.IncrementCount:23
20230821-17:39:04.387 INFO IncrementCount - TestNLog3.Pages.Counter.IncrementCount:20
20230821-17:39:04.387 WARN IncrementCount - TestNLog3.Pages.Counter.IncrementCount:21
20230821-17:39:04.387 ERROR IncrementCount - TestNLog3.Pages.Counter.IncrementCount:22
20230821-17:39:04.387 FATAL IncrementCount - TestNLog3.Pages.Counter.IncrementCount:23
20230821-17:39:05.869 INFO Executed endpoint '/_blazor' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:05.869 INFO Request finished HTTP/2 CONNECT https://localhost:7061/_blazor?id=wZWacy4asZs8XbiMDjBuqQ - - - 200 - - 5351.3137ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0
20230821-17:39:05.902 INFO Request starting HTTP/2 POST https://localhost:7061/_blazor/disconnect multipart/form-data;+boundary=----WebKitFormBoundarybBtjcDAMQogZ0jEY 359 - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestStarting:0
20230821-17:39:05.902 INFO Executing endpoint 'Blazor disconnect' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:05.934 INFO Executed endpoint 'Blazor disconnect' - Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke:0
20230821-17:39:05.934 INFO Request finished HTTP/2 POST https://localhost:7061/_blazor/disconnect multipart/form-data;+boundary=----WebKitFormBoundarybBtjcDAMQogZ0jEY 359 - 0 - - 34.9715ms - Microsoft.AspNetCore.Hosting.HostingApplicationDiagnostics.LogRequestFinished:0