在 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主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...
随机推荐
- SpringBoot+Docker +Nginx 部署前后端项目
部署SpringBoot项目(通关版) 一.概述 使用 java -jar 命令直接部署项目的JAR包和使用Docker制作镜像进行部署是两种常见的部署方式.以下是对这两种方式的概述和简要的优劣势分析 ...
- C4996 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
错误原因 VS平台认为scanf函数不安全,要求换成scanf_s函数 解决方案 方案一:将scanf换成scanf_s[不建议] 将scanf换成scanf_s 但是,scanf_s函数只能在vs上 ...
- 第三方的开源库FluentVaidation校验字段的
内置的 using System.ComponentModel.DataAnnotations; 基本使用: 1. 安装包 FluentValidation.AspNetCOre 2. 注册服务 bu ...
- [Dest0g3 520迎新赛]funny_upload
打开靶机抓包发现过滤代码 发现.htaccess能上传后传入图片马 发现内容对<?进行过滤 我们换一种方式写后门代码 <script language="php"> ...
- 云原生周刊:Argo Rollouts 支持 Kubernetes Gateway API 1.0 | 2024.7.1
开源项目 Kubetools Recommender System Kubetools Recommender System (Krs) 是一个基于 GenAI 的工具,用于帮助管理和优化 Kuber ...
- 使用 Cilium 作为网络插件部署 K8s + KubeSphere
Cilium 简介 Cilium 是一个用于容器网络领域的开源项目,主要是面向容器而使用,用于提供并透明地保护应用程序工作负载(如应用程序容器或进程)之间的网络连接和负载均衡. Cilium 在第 3 ...
- RocketMQ 在小米的多场景灾备实践案例
本文作者:邓志文.王帆 01为什么要容灾? 在小米内部,我们使用 RocketMQ 来为各种在线业务提供消息队列服务,比如商城订单.短信通知甚至用来收集 IoT 设备的上报数据,可以说 RocketM ...
- 2024最新免费IP地址SSL证书申请
为IP地址申请免费的SSL证书相对较为困难,因为多数证书颁发机构(CA)提供的免费SSL证书主要是基于域名的.不过,还是可以尝试以下方法来申请免费的IP地址SSL证书: 一.确认IP地址与了解需求 确 ...
- GAN和CGAN——生成式对抗网络和条件生成式对抗网络
GAN的定义 GAN是一个评估和学习生成模型的框架.生成模型的目标是学习到输入样本的分布,用来生成样本.GAN和传统的生成模型不同,使用两个内置模型以"对抗"的方式来使学习分布不断 ...
- 数字IC知识点:处理多个时钟
1. 多时钟域 图1.多时钟域 对于工程师来说,开发含多个时钟(见图1)的设计是一种挑战. 这样的设计中可能有以下任何一个,或者全部类型的时钟关系: 时钟的频率不同 时钟频率相同,但相位不同 以上两种 ...