日志事件通过 Log 静态类或 ILogger 接口上的方法写入接收器。下面的示例将使用 Log 以便语法简洁,但下面显示的方法同样可用于接口。

Log.Warning("Disk quota {Quota} MB exceeded by {User}", quota, user);

通过此日志方法创建的警告事件将具有两个相关属性,Quota 和 User。假设 quota 是一个整数,user 是一个字符串,呈现的消息可能如下所示。

Disk quota 1024 MB exceeded by "nblumhardt"

(Serilog 使用双引号渲染字符串值,以更清晰地指示其底层数据类型,并使属性值从周围的消息文本中脱颖而出。)

01、消息模板语法

上述字符串 “Disk quota {Quota} exceeded by {User}” 是一个 Serilog 消息模板。消息模板是标准 .NET 格式字符串的超集,因此任何适用于 string.Format() 的格式字符串也会被 Serilog 正确处理。

  • 属性名称用 { 和 } 括起来书写。
  • 属性名称必须是有效的 C# 标识符,例如 FooBar,但不能是 Foo.Bar 或 Foo-Bar。
  • 括号可以通过重复书写来转义,例如 {{ 将被渲染为 {。
  • 使用数字属性名称的格式,如 {0} 和 {1},将通过将属性名称视为索引来与日志方法的参数匹配;这与 string.Format() 的行为相同。
  • 如果任何属性名称是非数字,则所有属性名称将从左到右与日志方法的参数进行匹配。
  • 属性名称可以带有可选的运算符前缀 @ 或 $,以控制属性的序列化方式。
  • 属性名称可以带有可选的格式后缀,例如 :000,以控制属性的渲染方式;这些格式字符串的行为与 string.Format() 语法中的对应部分完全相同。

02、消息模板推荐

流畅风格指南:好的 Serilog 事件使用属性名称作为消息内容,如上面的用户示例。这提高了可读性,并使事件更简洁。

句子与片段:日志事件消息是片段,而不是句子;为了与其他使用 Serilog 的库保持一致,尽量避免使用句末的句号。

模板与消息:Serilog 事件关联的是消息模板,而不是消息。内部,Serilog 会解析并缓存每个模板(直到固定大小限制)。将日志方法的字符串参数视为消息,如下例所示,会降低性能并消耗缓存内存。

//不推荐
Log.Information("The time is " + DateTime.Now);

相反,始终使用模板属性在消息中包含变量

// 推荐
Log.Information("The time is {Now}", DateTime.Now);

属性命名:属性名称应使用 PascalCase,以保持与 Serilog 生态系统中其他代码和库的一致性。

03、日志事件级别

Serilog 使用级别作为分配日志事件重要性的主要手段。级别按重要性递增的顺序为:

  • 详细信息(Verbose) - 跟踪信息和调试细节;通常仅在特殊情况下开启。
  • 调试(Debug) - 内部控制流和诊断状态转储,以便于定位已知问题。
  • 信息(Information) - 对外部观察者有意义或相关的事件;默认启用的最低日志级别。
  • 警告(Warning) - 可能问题或服务/功能下降的指示。
  • 错误(Error) - 指示应用程序或连接系统中的失败。
  • 致命(Fatal) - 导致应用程序完全失败的严重错误。

1、信息级别的作用

信息级别与其他指定级别不同-它没有特定的语义,许多方面上表达了其他级别的缺失。

由于 Serilog 允许对应用程序的事件流进行处理或分析,信息级别可以视为事件的同义词。也就是说,大多数有趣的应用程序事件数据应记录在此级别。

2、级别检测

在大多数情况下,应用程序应该在不检查当前日志级别的情况下记录事件。级别检查的开销非常小,而调用禁用的日志记录方法的开销也很低。

在少数性能敏感的情况下,推荐的级别检测模式是将级别检测的结果存储在一个字段中,例如:

readonly bool _isDebug = Log.IsEnabled(LogEventLevel.Debug);

可以在写入日志事件之前高效地检查 _isDebug 字段:

if (_isDebug) Log.Debug("Someone is stuck debugging...");

3、动态级别

许多大型或分布式应用需要在相对限制的日志级别下运行,例如信息级(我更倾向于这种)或警告级,并仅在检测到问题时将日志级别提高到调试级或详细级,以便收集更多数据的开销是合理的。

如果应用需要动态切换日志级别,第一步是在配置日志记录器时创建一个 LoggingLevelSwitch 的实例:

var levelSwitch = new LoggingLevelSwitch();

该对象默认将当前最低级别设置为信息级,因此为了使日志记录更为严格,可以提前设置其最低级别:

levelSwitch.MinimumLevel = LogEventLevel.Warning;

在配置日志记录器时,使用 MinimumLevel.ControlledBy() 提供该开关:

var log = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.WriteTo.ColoredConsole()
.CreateLogger();

现在,写入日志记录器的事件将根据开关的 MinimumLevel 属性进行过滤。

要在运行时调整日志级别,例如响应通过网络发送的命令,可以更改该属性:

levelSwitch.MinimumLevel = LogEventLevel.Verbose;
log.Verbose("This will now be logged");

04、源上下文

Serilog 和大多数 .NET 日志框架一样,允许事件带上其来源标签,通常是写入这些事件的类的名称:

var myLog = Log.ForContext<MyClass>();
myLog.Information("Hello!");

写入的事件将包含一个属性 SourceContext,其值为 "MyNamespace.MyClass",可以用来过滤噪音事件或选择性地将其写入特定的接收器。

并非所有附加到事件的属性都需要在消息模板或输出格式中表示;所有属性都存储在底层 LogEvent 对象的字典中。

有关过滤器和日志记录拓扑的更多信息,请参阅《Serilog文档翻译系列(三) - 基础配置》知识。

05、关联

正如 ForContext() 会将日志事件标记为写入它们的类,ForContext() 的其他重载允许日志事件用标识符进行标记,这些标识符随后可以支持与该标识符关联的事件的关联。

var job = GetNextJob();
var jobLog = Log.ForContext("JobId", job.Id);
jobLog.Information("Running a new job");
job.Run();
jobLog.Information("Finished");

在这里,两个日志事件都将携带 JobId 属性,其中包含作业标识符。

提示:当记录到使用文本格式的接收器时,例如 Serilog.Sinks.Console,可以在输出模板中包含 {Properties} 来打印出所有未包含的上下文属性。

注:相关源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

Serilog文档翻译系列(五) - 编写日志事件的更多相关文章

  1. MySQL系列(五)--二进制日志对主从复制的影响

    MySQL复制是基于主库上的二进制日志来完成,复制是异步的,可能存在延迟 MySQL日志分为: 1.服务层日志:二进制日志.通用日志.慢查日志 2.存储引擎层日志:innodb中重做日志和回滚日志 二 ...

  2. C#微信公众号开发系列教程五(接收事件推送与消息排重)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  3. 普冉PY32系列(五) 使用JLink RTT代替串口输出日志

    目录 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境 普冉PY32系列(三) P ...

  4. Netty4.x中文教程系列(五)编解码器Codec

    Netty4.x中文教程系列(五)编解码器Codec 上一篇文章详细解释了ChannelHandler的相关构架设计,版本和设计逻辑变更等等. 这篇文章主要在于讲述Handler里面的Codec,也就 ...

  5. JVM系列五:JVM监测&工具

    JVM系列五:JVM监测&工具[整理中]  http://www.cnblogs.com/redcreen/archive/2011/05/09/2040977.html 前几篇篇文章介绍了介 ...

  6. WCF开发实战系列五:创建WCF客户端程序

    WCF开发实战系列五:创建WCF客户端程序 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 在前面的三篇文章中我们分别介绍了WCF服务的三种载体:IIS.Self-Hos ...

  7. WCF编程系列(五)元数据

    WCF编程系列(五)元数据   示例一中我们使用了scvutil命令自动生成了服务的客户端代理类: svcutil http://localhost:8000/?wsdl /o:FirstServic ...

  8. VSTO之旅系列(五):创建Outlook解决方案

    原文:VSTO之旅系列(五):创建Outlook解决方案 本专题概要 引言 Outlook对象模型 自定义Outlook窗体 小结 一.引言 在上一个专题中,为大家简单介绍了下如何创建Word解决方案 ...

  9. Orchard core 中文文档翻译系列

    本系列翻译顺序完全参照 官方顺序 原文地址:https://orchardcore.readthedocs.io/en/latest/ Orchard Core 中文文档翻译(一)关于Orchard ...

  10. Hexo系列(五) 撰写文章

    在利用 Hexo 框架搭建一个属于我们自己的博客网站后,下面我们就来谈谈怎样在网站上书写我们的第一篇博客吧 一.创建文章 在站点文件夹中打开 git bash,输入如下命令创建文章,其中 title ...

随机推荐

  1. Oracle 存储过程学习总结

    创建/更新存储过程 基础基础用法 创建/修改无参存储过程 CREATE OR REPLACE PROCEDURE procedure_name [IS|AS] --声明全局变量(可选) BEGIN - ...

  2. springsecurity流程梳理与总结

    springsecurity的基本使用方法学习完了,还是有些懵圈,再回过头来梳理一下流程以及使用情况 1-4.传一个User实体,new一个UserPasswordAuthenticationToke ...

  3. java17特性:文本块

    例子 String content= """ { "text_1":"%s", "text_2":" ...

  4. 【Git】02 创建本地仓库 & 添加文件并提交

    1.创建版本库 版本库又名仓库,英文名repository, 你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来 每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追踪历史, ...

  5. 【Layui】16 表单元素 Form

    文档地址: https://www.layui.com/demo/form.html 表单元素: 1.输入框 2.密码框 3.下拉列表 4.单选框 5.复选框 6.文档域 7.富文本 8.开关 单行输 ...

  6. kimchi – kvm虚拟机网页管理

    参考: https://mangolassi.it/topic/15882/kimchi-kvm-updated-and-better-and-easy-guide-for-kvm-beginners ...

  7. 使用python对Excel表格某个区域保存为图片

    实际工作中,我们经常会把表格某个区域(如:A1:F5)或某个图形保存为图片,如何用python自动做到这一点?不知屏幕前的小伙伴有没有遇到过类似的需求,此刻脑海里有木有一丢丢思路. python操作e ...

  8. 代码随想录Day4

    24.两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点.你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换). 示例 1: 输入:head = [1, ...

  9. 有没有使用过MindSpore的,体验怎么样啊?

    看到了一个帖子: https://www.zhihu.com/question/386352303/answer/3160948468 ================================ ...

  10. 强化学习:一种新的并行算法下的参数同步更新方式——半异步更新方式——( 同步、异步 -> 半异步 )

    Abstract: 并行算法下的参数同步方式一般有同步更新和异步更新两种方式,本文在此基础之上提出了一种新的参数同步方式--半异步更新方式. Introduction: 这里用神经网络举例子,也就是神 ...