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. ceph-rbd和cephfs使用

    目录 1 用户权限管理和授权流程 1.1 列出用户 1.2 用户管理 1.2.1 ceph auth add 1.2.3 ceph auth get-or-create 1.2.4 ceph auth ...

  2. 【解决方案】基于数据库驱动的自定义 TypeHandler 处理器

    目录 前言 一.TypeHandler 简介 1.1转换步骤 1.2转换规则 二.JSON 转换 三.枚举转换 四.文章小结 前言 笔者在最近的项目开发中,频繁地遇到了 Java 类型与 JDBC 类 ...

  3. 流式dma和一致性dma的区别

    流式 DMA(Streaming DMA)和一致性 DMA(Consistent DMA)是两种不同的内存映射模式,用于 DMA(直接内存访问)操作.它们的主要区别在于缓存一致性.性能和使用场景.以下 ...

  4. BTF:实践指南

    BPF 是 Linux 内核中基于寄存器的虚拟机,可安全.高效和事件驱动的方式执行加载至内核的字节码.与内核模块不同,BPF 程序经过验证以确保它们终止并且不包含任何可能锁定内核的循环.BPF 程序允 ...

  5. 常见的mysql 函数 字符串函数

    1. concat (s1,s2,....sn) 字符串拼接,将 s1,s2,... sn 拼接成一个字符串 : 2. lower(str) 将字符串全部转换成小写 3. upper(str) 将字符 ...

  6. 46.使用过vuex和vue-router吗

    使用过,vuex是状态管理工具,它的数据可以被所有的组件获取,方法可以被所有的组件调用 : vuex  的内部的运行机制:state提供了数据驱动视图,dispath派发actions 执行异步操作, ...

  7. 基于BIO的Socket通信

    基于BIO的Socket通信 告知对方命令发送完毕 关闭socket:socket.close() 关闭流:socket.shutdownOutput(),ocket.shutdownInput() ...

  8. mongodb插入数据不能在vue显示

    问题描述:当我们在命令行插入数据时,在MongoVUE却显示不了数据,并且查询有插入数据的数据库,如下图所示 网上资料说,这是引擎的问题,mongoDB3.2版本之后默认开启的存储引擎是wiredRi ...

  9. OAS常见错误

    body { font-family: Arial, sans-serif; line-height: 1.6; margin: 20px } h1, h2 { color: rgba(51, 51, ...

  10. 强化学习训练过程中的过度拟合(overfitting)

    相关: A.I. Learns to Drive From Scratch in Trackmania 本文讨论的是强化学习中的过度拟合问题,要知道强化学习中的过拟合和其他的监督.无监督学习的过拟合不 ...