日志事件通过 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. 学习 React 需要具备的 JavaScript 知识

    学习 React 需要具备的 JavaScript 知识 为什么要学习 React? React 可以与任何其他库或框架无缝集成,因为 React 是一个仅视图库(它是 Model View C on ...

  2. selenium获取验证码截图

    获取验证码截图代码: 获取验证码代码: #!/user/bin/env python3 # -*- coding: utf-8 -*- import requests from selenium im ...

  3. 【JavaScript】前端算法题(重建二叉树、反向输出链表每个节点)

    前言 今天复习了一些前端算法题,写到一两道比较有意思的题:重建二叉树.反向输出链表每个节点 题目 重建二叉树: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的 ...

  4. 【Java】Springboot + Redis +(AOP & 响应外切)切面实现字典翻译

    使用案例演示: 先开发了一个简单的Demo: 普通DTO类注解翻译的字段和翻译来源 在需要翻译的方法上注解@Translate 接口返回结果: 框架思路: 1.标记的注解需要通过AOP切面在调用的时候 ...

  5. 【Mybatis】05 官方文档指北阅读 vol3 配置 其二

    对象工厂(objectFactory)[省略,入门阶段实在不懂] 插件(plugins)[省略,入门阶段实在不懂] 环境配置(environments) MyBatis 可以配置成适应多种环境,这种机 ...

  6. 2024-08-03:用go语言,给定一个从 0 开始的字符串数组 `words`, 我们定义一个名为 `isPrefixAndSuffix` 的布尔函数,该函数接受两个字符串参数 `str1` 和

    2024-08-03:用go语言,给定一个从 0 开始的字符串数组 words, 我们定义一个名为 isPrefixAndSuffix 的布尔函数,该函数接受两个字符串参数 str1 和 str2. ...

  7. T800机器人图片 —— 强大的好莱坞电影工业,T800机器人模型也如此精细真实!

    视频地址: https://www.ixigua.com/6764744689003266571

  8. OneFlow框架0.9.1dev版本,成功安装并运行

    安装cuda和cudnn: (此步骤可以忽略,pip安装框架时会自动安装依赖的cuda和cudnn环境) conda install cudatoolkit==11.8.0 python3 -m pi ...

  9. python进程绑定CPU的一些Demo

    从https://www.cnblogs.com/devilmaycry812839668/p/17066212.html中知道如何对python进程设置CPU绑定,本文对此进行一些延伸,给出一些例子 ...

  10. Spring Boot 基于 SCRAM 认证集成 Kafka 的详解

    一.说明 在现代微服务架构中,Kafka 作为消息中间件被广泛使用,而安全性则是其中的一个关键因素.在本篇文章中,我们将探讨如何在 Spring Boot 应用中集成 Kafka 并使用 SCRAM ...