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的更多相关文章

  1. 如何在 ASP.Net Core 中使用 Serilog

    记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...

  2. 在 ASP.NET Core 中使用 Serilog 进行日志记录

    目录 从 NuGet 安装 Serilog 在 Main函数 中配置 Serilog 在项目中使用 Serilog 进行日志输出 从 NuGet 安装 Serilog 核心的包是 Serilog 和 ...

  3. 玩转ASP.NET Core中的日志组件

    简介 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Console ...

  4. Asp.Net Core中利用Seq组件展示结构化日志功能

    在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...

  5. (14)ASP.NET Core 中的日志记录

    1.前言 ASP.NET Core支持适用于各种内置和第三方日志记录提供应用程序的日志记录API.本文介绍了如何将日志记录API与内置提供应用程序一起使用. 2.添加日志提供程序 日志记录提供应用程序 ...

  6. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  7. Asp.net Core中使用Session

    前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...

  8. 在ASP.NET Core中使用百度在线编辑器UEditor

    在ASP.NET Core中使用百度在线编辑器UEditor 0x00 起因 最近需要一个在线编辑器,之前听人说过百度的UEditor不错,去官网下了一个.不过服务端只有ASP.NET版的,如果是为了 ...

  9. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

  10. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

随机推荐

  1. 《Vue.js 设计与实现》读书笔记 - 第13章、异步组件与函数式组件

    第13章.异步组件与函数式组件 13.1 异步组件要解决的问题 用户可以简单通过 import 异步导入组件. <template> <component :is="asy ...

  2. excel江湖异闻录--◆K

    网名◆K,按照群里同学的说法,K神和老大kluas,以及一个名为KKK的VBA强人,都是K字头家族的高手. 因为函数实力极强,时常碾压难题,被群里同学们冠以了"K神"的称号. 用笔 ...

  3. UEFI原理与编程(四)(dec dsc inf文件)

    1 .inf文件 以下面 .inf文件为例 [Defines] # 块用于定义模块的属性和其他变量,块内定义的变量可被其他块引用 INF_VERSION = 0x00010006 #INF 标准的版本 ...

  4. 1. 什么是three.js?

    Three.js是一个基于JavaScript编写的开源3D图形库,它使用WebGL技术在网页上渲染3D图形.Three.js提供了许多高级功能,如几何体.纹理.光照.阴影等,以便开发者能够快速地创建 ...

  5. stm32开发

    基于寄存器开发 新建工程 添加C/C++识别路径 : 防止中文乱码 -  改变编码格式 基于库函数开发

  6. 《使用Gin框架构建分布式应用》阅读笔记:p77-p87

    <用Gin框架构建分布式应用>学习第5天,p77-p87总结,总计11页. 一.技术总结 1.Go知识点 (1)context 2.on-premises software p80, A ...

  7. RabbitMQ3.8.16安装延迟队列插件

    安装过程 1:RabbitMQ 延迟插件GitHub 2:各版本地址 如我的MQ版本是3.8.16,那么根据提示下载的版本是: ①:移动插件到RabbitMQ的插件目录下,如我的位置是:/usr/li ...

  8. Linux利用scp命令上传下载文件

    scp是secure copy的简写,用于在 Linux 下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器. scp传输是加密的,可能会稍微影响一下速度.当你服务 ...

  9. spring生态体系

    spring boot使用默认开发配置来实现快速开发spring xd用来简化大数据应用开发spring cloud为分布式系统开发提供工具集spring data对主流的关系型和nosql数据库的支 ...

  10. 一个专注推荐.Net开源项目的榜单

    大家好,我是编程乐趣,从7月份开始推荐开源项目,已经推荐了接近100个开源项目了,其中绝大部分是有关.Net的开源项目,也受到大家非常多人的喜欢. 由于公众号不方便查询,很多人又想了解更多的开源项目, ...