内容目录
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0-preview.2.22152.2" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0-preview.2.22152.2" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.0.2-dev-00890" />
</ItemGroup>
使用依赖注入单纯注入 Serilog 的方法:
static IServiceProvider GetServiceProvider()
{
using var log = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.Enrich.FromLogContext()
.CreateLogger();
Serilog.Log.Logger = log;
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging(builder => builder.AddSerilog(dispose: true));
return serviceCollection.BuildServiceProvider();
}
获取日志:
var loggerProvider = GetServiceProvider().GetService<ILoggerProvider>()!;
var logger = loggerProvider.CreateLogger(nameof(Program));
创建 Scope
日志范围注意事项
Microsoft.Extensions.Logging提供BeginScopeAPI,可用于添加任意属性以记录特定代码区域内的事件。API 有两种形式:
方法:IDisposable BeginScope
扩展方法:IDisposable BeginScope(this ILogger logger, string messageFormat, params object[] args)
模板:
{SourceContext} {Timestamp:HH:mm} [{Level}] (ThreadId:{ThreadId}) {Message}{NewLine}{Exception} {Scope}
using (logger.BeginScope("Checking mail"))
{
// Scope is "Checking mail"
logger.LogInformation("Opening SMTP connection");
using (logger.BeginScope("Downloading messages"))
{
// Scope is "Checking mail" -> "Downloading messages"
logger.LogError("Connection interrupted");
}
}
临时增加一个属性
需要先开启 .Enrich.FromLogContext()
。
using (LogContext.PushProperty("Test", 1))
{
// Process request; all logged events will carry <code>RequestId</code>
Log.Information("{Test} Adding {Item} to cart {CartId}", 1,1);
}
嵌套复杂一些:
using (LogContext.PushProperty("A", 1))
{
log.Information("Carries property A = 1");
using (LogContext.PushProperty("A", 2))
using (LogContext.PushProperty("B", 1))
{
log.Information("Carries A = 2 and B = 1");
}
log.Information("Carries property A = 1, again");
}
ASP.NET Core 模板案例
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Elasticsearch", "Serilog.Sinks.Trace" ],
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Default": "Debug",
"Microsoft": "Debug",
"System": "Debug",
"System.Net.Http.HttpClient": "Debug",
"Microsoft.AspNetCore": "Debug",
"Microsoft.Hosting.Lifetime": "Debug",
"Microsoft.AspNetCore.Hosting.Diagnostics": "Debug"
}
},
"Enrich": [ "FromLogContext", "WithMachineName" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "{SourceContext} {Scope} {Timestamp:HH:mm} [{Level}] {Message:lj} {Properties:j} {NewLine}{Exception} "
}
},
模板是:
{SourceContext} {Scope} {Timestamp:HH:mm} [{Level}] {Message:lj} {Properties:j} {NewLine}{Exception}
配置日志输出:
var logger = _loggerfactory.CreateLogger<IFreeSql>();
fsql.Aop.CurdAfter += (s, e) =>
{
#pragma warning disable CA2017 // 参数计数不匹配。
logger.LogInformation("[Freesql] operation log,operation type:{CurdType} TableName: {DbName} , Time: {ElapsedMilliseconds}ms ,SQL: {Sql}", e.CurdType, e.Table.DbName, e.ElapsedMilliseconds, e.Sql, e.DbParms);
#pragma warning restore CA2017 // 参数计数不匹配。
};
services.AddSingleton(fsql);
效果:
在中间件很多多层调用时,注入属性示例:
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var enrichers = new List<ILogEventEnricher>();
if (!string.IsNullOrEmpty(correlationId))
{
enrichers.Add(new PropertyEnricher(_options.EnricherPropertyNames.CorrelationId, correlationId));
}
using (LogContext.Push(enrichers.ToArray()))
{
await next(context);
}
}
文章评论
编译期日志生成方案 https://github.com/dotnet/docs/blob/main/docs/core/extensions/logger-message-generator.md