在 ASP.NET Core 中 使用 Serilog
Serilog.AspNetCore
https://github.com/serilog/serilog-aspnetcore#two-stage-initialization
这是 Serilog 日志系统的 ASP.NET Core 支持包。该包将 ASP.NET Core 的日志信息路由到 Serilog,所以你可以得到关于 ASP.NET 的内部处理信息,与你的应用程序事件一起写入到同样的输出中。
当安装 Serilog.AspNetCore 并配置之后,你可以直接通过 Serilog 写出日志消息,或者使用任何通过 ASP.NET 所注入的 ILogger 接口。所有的日志器将使用相同的底层实现、日志级别以及输出目标。
.NET Framework 和 .NET Core 2.x 由本包的 v3.4.0 版本所支持。最新版本的 Serilog.AspNetCore 需要 .NET 3.x、.NET 5 或者更新版本的支持。
版本化
该包跟踪其 Microsoft.Extensions.Hosting 依赖项的版本控制和目标框架支持。大多数用户应选择与其应用程序的目标框架匹配的 Serilog.AspNetCore 版本。即,
- 如果面向 .NET 7.x,请选择 Serilog.AspNetCore 的 7.x 版本。
- 如果面向 .NET 8.x,请选择 8.x Serilog.AspNetCore 版本,依此类推。
使用说明
首先,安装 Serilog.AspNetCore NuGet 包到你的应用中
dotnet add package Serilog.AspNetCore
然后,在你的应用程序的 Program.cs 文件中,先配置 Serilog,然后使用 try/catch 语句块来确保任何配置问题都会被正确记录下来。
using Serilog;
using Serilog.Events;
public class Program
{
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
try
{
Log.Information("Starting web host");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}
然后,使用 UseSerilog() 到 Host 上来。
var builder = WebApplication.CreateBuilder(args);
// Add this line to add Serilog
builder.Host.UseSerilog ();
最后,通过删除对于默认日志器完成清理工作。
- 删除 appsetting.json 配置文件中的
Logging配置节
完成!使用配置的日志级别,你将会看到类似如下输出
[22:14:44.646 DBG] RouteCollection.RouteAsync
Routes:
Microsoft.AspNet.Mvc.Routing.AttributeRoute
{controller=Home}/{action=Index}/{id?}
Handled? True
[22:14:44.647 DBG] RouterMiddleware.Invoke
Handled? True
[22:14:45.706 DBG] /lib/jquery/jquery.js not modified
[22:14:45.706 DBG] /css/site.css not modified
[22:14:45.741 DBG] Handled. Status code: 304 File: /css/site.css
提示:为了在运行在 IIS 下的时候,通过 Visual Studio 中的 Output 窗口中看到 Serilog 输出,或者从输出窗口的
Show output的下拉列表中选择ASP.NET Core Web Server,或者将WriteTo.Console()替换为WriteTo.Debug()。
更多完整示例,包括使用 appsetting.json 配置,可以参考示例项目。
请求日志
本包中包括了一个用于智能处理 HTTP 请求日志的中间件。在默认的 ASP.NET Core 的请求日志实现中包含杂音。对于单个请求生成多个事件。本包所提供的中间件将它们合并为单个事件,包含了 Method、Path、Status Code 和计时信息。
以纯文本方式,示例格式如下
[16:05:54 INF] HTTP GET / responded 200 in 227.3253 ms
JSON 格式:
{
"@t": "2019-06-26T06:05:54.6881162Z",
"@mt": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
"@r": ["224.5185"],
"RequestMethod": "GET",
"RequestPath": "/",
"StatusCode": 200,
"Elapsed": 224.5185,
"RequestId": "0HLNPVG1HI42T:00000001",
"CorrelationId": null,
"ConnectionId": "0HLNPVG1HI42T"
}
为了启用该中间件,首先在你的日志配置或者 appsetting.json 中修改 Microsoft.AspNetCore 的最小日志级别到 Warning
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
然后,在应用程序的 Startup.cs 中,使用 UseSerilogRequestLogging() 启用该中间件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseSerilogRequestLogging(); // <-- Add this line
// Other app configuration
特别重要的是,UseSerilogRequestLogging() 调用要出现在像 MVC 这样的处理器之前。中间件并不能处理流水线中出现在它之前的组件 ( 这样可以排除一些杂音,比如通过将 UseSerilogRequestLogging() 放在 UseStaticFiles() 之后 )
在请求处理过程中,附加的属性可以通过 IDiagnosticContext.Set() 来追加到完整的事件上。
public class HomeController : Controller
{
readonly IDiagnosticContext _diagnosticContext;
public HomeController(IDiagnosticContext diagnosticContext)
{
_diagnosticContext = diagnosticContext ??
throw new ArgumentNullException(nameof(diagnosticContext));
}
public IActionResult Index()
{
// The request completion event will carry this property
_diagnosticContext.Set("CatalogLoadTime", 1423);
return View();
}
通过这种模式可以压缩日志事件的数量,涉及到针对每个 HTTP 请求中构造、传输和存储。在同一事件中设置多个属性也可以使得关联请求的细节内容,以及其它数据更简单。
下列请求信息将被默认添加到属性上:
- RequestMethod
- RequestPath
- StatusCode
- Elapsed
你可以修改默认的请求事件的模板,添加附加的属性,或者变更事件级别,在 UseSerilogRequestLogging() 回调方法中使用 options 参数设置:
app.UseSerilogRequestLogging(options =>
{
// Customize the message template
options.MessageTemplate = "Handled {RequestPath}";
// Emit debug-level events instead of the defaults
options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Debug;
// Attach additional properties to the request completion event
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{
diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
};
});
两段式初始化
前面的示例展示了如何在应用启动的时候,立即配置 Serilog。这样可以得到通过异常捕获在 ASP.NET Core 宿主初始化阶段的信息。
首先初始化 Serilog 的缺点是在 ASP.NET Core 主机的服务,包括了 appsetting.json 的配置和依赖注入,将不能使用到。
为了处理这个问题,Serilog 支持两段式初始化,第一步在应用启动的时候,立即配置并初始化日志器,然后再主机加载之后,它被重新配置的日志器替换掉。
为了使用这个技术,首先使用 CreateBootstrapLogger() 替换原来的 CreateLogger()。
using Serilog;
using Serilog.Events;
public class Program
{
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateBootstrapLogger(); // <-- Change this line!
然后,在调用 UseSerilog() 的时候通过回调函数来创建最终的日志器。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog((context, services, configuration) => configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
.WriteTo.Console())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
特别需要注意的是,最终的日志器完全替换了原来的启动日志器。比如说,如果你希望它们都输出到控制台 Console,那么你需要在两个地方都指定
WriteTo.Console(),如上面示例。
支持 appsetting.json 配置
使用两段式初始化,插入 ReadFrom.Configuration(context.Configuration) 调用,如上面示例所示,JSON 配置文件的语法见 Serilog.Settings.Configuratio README 文档
将服务注入到 Enricher 和 Sink 中
在使用两段式初始化的时候,插入如上面示例所示的 ReadFrom.Services(services) 调用。该调用将使用任何注册的如下服务的实现来配置日志处理管线:
- IDestructuringPolicy
- ILogEventEnricher
- ILogEventFilter
- ILogEventSink
- LoggingLevelSwitch
启用 Microsoft.Extensions.Logging.ILoggerProviders
Serilog 将事件发送到被称为 sink 的输出中,Serilog 的 ILogEventSink 接口实现,并使用 WriteTo 添加到日志处理管线中。Microsoft.Extensions.Logging 有类似的概念,不过被称为 provider。它实现 ILoggerProvider 接口。这些 provider 通过类似 AddConsole() 这样的方法在底层被创建出来。
默认情况下,Serilog 忽略这些 provider,因为它们等价于 Serilog 中存在的 sink。它们在 Serilog 的处理管线中更为高效。如果需要支持 provider,它也可以被可选地启用。
为了使 Serilog 将事件传递给 provider,在使用两段式初始化的示例中,提供 writeToProviders: true 作为参数传递给 UseSerilog()
.UseSerilog(
(hostingContext, services, loggerConfiguration) => /* snip! */,
writeToProviders: true)
JSON 输出
在 Console()、Debug()、File() 输出中,都原生支持 JSON 格式,通过包含 Serilog.Formatting.Compact NuGet 包。
输出新行分隔的 JSON,传递 CompactJsonFormatter 或者 RenderedCompactJsonFormatter 到 sink 配置方法中。
.WriteTo.Console(new RenderedCompactJsonFormatter())
如果你希望在你的代码的特定部分对日志都增加额外的属性,你可以将它们添加到 ILogger<> 中,在 Microsoft.Extensions.Logging 中使用如下代码。为了使得这些代码生效,确保你在 .UseSErilog(...) 的内部添加了 .Enrich.FromLogContext() 语句,如上面示例所示。
// Microsoft.Extensions.Logging ILogger<T>
// Yes, it's required to use a dictionary. See https://nblumhardt.com/2016/11/ilogger-beginscope/
using (logger.BeginScope(new Dictionary<string, object>
{
["UserId"] = "svrooij",
["OperationType"] = "update",
}))
{
// UserId and OperationType are set for all logging events in these brackets
}
在 Serilog 中,使用如下代码:
// Serilog ILogger
using (logger.PushProperty("UserId", "svrooij"))
using (logger.PushProperty("OperationType", "update"))
{
// UserId and OperationType are set for all logging events in these brackets
}
.NET 6 示例
Program
// step #1 serilog boostrap
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateBootstrapLogger(); // <-- Change this line!
try
{
Log.Information("Starting web host");
var builder = WebApplication.CreateBuilder(args);
// step #2 build final serilog logger
builder.Host.UseSerilog((context, services, configuration) => configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
);
配置文件 appsetting.json
{
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"Microsoft.AspNetCore": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" },
{
"Name": "File",
"Args": {
"path": "./Logs/log-.txt",
"rollingInterval": "Day",
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
"Properties": {
"Application": "Sample"
}
},
"AllowedHosts": "*"
}
Reference
在 ASP.NET Core 中 使用 Serilog的更多相关文章
- 如何在 ASP.Net Core 中使用 Serilog
记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...
- 在 ASP.NET Core 中使用 Serilog 进行日志记录
目录 从 NuGet 安装 Serilog 在 Main函数 中配置 Serilog 在项目中使用 Serilog 进行日志输出 从 NuGet 安装 Serilog 核心的包是 Serilog 和 ...
- 玩转ASP.NET Core中的日志组件
简介 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Console ...
- Asp.Net Core中利用Seq组件展示结构化日志功能
在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...
- (14)ASP.NET Core 中的日志记录
1.前言 ASP.NET Core支持适用于各种内置和第三方日志记录提供应用程序的日志记录API.本文介绍了如何将日志记录API与内置提供应用程序一起使用. 2.添加日志提供程序 日志记录提供应用程序 ...
- ASP.NET Core 中的那些认证中间件及一些重要知识点
前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...
- Asp.net Core中使用Session
前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...
- 在ASP.NET Core中使用百度在线编辑器UEditor
在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...
- ASP.NET Core中的依赖注入(1):控制反转(IoC)
ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...
- ASP.NET Core中的依赖注入(2):依赖注入(DI)
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...
随机推荐
- Dockerfile相关(推送镜像?私有仓库?)(九)
上面我们讲到了 Dockerfile 的基本写法以及构建镜像的时候一些注意事项,那么镜像构建完成后,如何把我们的镜像给到别人使用呢?第一种方法就是利用 Docker 官方提供的公共的 Docker H ...
- Autodesk 3d Max2020 初始化闪退
事件起因:给同事安装完 Autodesk 3d Max2020 版本之后,软件初始化就闪退,后来在网上查了资料后解决. 解决办法如下:services.msc --> Autodesk 开头的服 ...
- placement new --特殊的内存分配
placement new 是 C++ 中的一种特殊的内存分配技术,用来在指定的内存地址上直接构造对象.与普通的 new 运算符不同,placement new 并不分配新的内存,而是在已经分配好的内 ...
- 【USB3.0协议学习】Topic4·USB3.0的Port Connect State Machine和设备枚举
上一节的文章[USB3.0协议学习]Topic2·USB3.0的LTSSM分析中我们详细分析了USB3.0协议中的链路训练状态机(LTSSM)的各状态和跳转条件,覆盖了所有LTSSM状态.本文我们将从 ...
- python批量读取并显示图片,处理异常。
今天写了一个批量读取并显示图片的代码,当做练习,方便以后拿来使用. import imageio import os import matplotlib.pyplot as plt filepath ...
- Cookie、sessionStorage、localStorage的区别 ?
共同点:都是保存在浏览器端的. 区别: 1.cookie数据始终携带在同源的http请求中,即cookie在浏览器和服务器间来回传递,而sessionStorage和Localstorage不会自动把 ...
- 自签openssl证书(包含泛域名)
1.安装openSSL weget http://www.openssl.org/source/openssl-1.0.0a.tar.gz Tar -zxvf openssl-1.0.0a.tar.g ...
- HiT-SR:基于层级Transformer的超分辨率,计算高效且能提取长距离关系 | ECCV'24
Transformer在计算机视觉任务中表现出了令人鼓舞的性能,包括图像超分辨率(SR).然而,流行的基于Transformer的SR方法通常采用具有二次计算复杂度的窗口自注意力机制,导致固定的小窗口 ...
- 云原生爱好者周刊:买个蓝牙打印机实时打印新提交的 PR 吧 | 2022-10-24
开源项目推荐 blue 这个项目非常有意思,利用树莓派.蓝牙热敏打印机和 GitHub Actions 自动将新提交的 PR 或者 Issue 通过打印机打印出来,非常适合各个项目的维护者使用 Kub ...
- 格点拉格朗日插值与PME算法
技术背景 在前面的一篇博客中,我们介绍了拉格朗日插值法的基本由来和表示形式.这里我们要介绍一种拉格朗日插值法的应用场景:格点拉格朗日插值法.这种场景的优势在于,如果我们要对整个实数空间进行求和或者积分 ...