Serilog文档翻译系列(四) - 结构化数据
Serilog 是一种序列化器。在许多情况下,它具有良好的默认行为,能够满足其目的,但有时也需要指示 Serilog 如何存储附加到日志事件上的属性。

Serilog 使用一些不寻常的术语来指代 .NET 对象如何映射到其内部(与接收器无关的)属性表示。这些术语的详细解释如下,所以如果你打算阅读整页内容,可以跳过这一部分。
字符串化(Stringification) 是指获取一个提供.NET 属性,并调用其 ToString() 方法,以便到达接收器的表示是一个简单的字符串。
解构(Destructuring) 是指将复杂的 .NET 对象转换为结构的过程,这些结构可能会被表示为 JSON 对象或 XML 块。
标量(Scalars) 是指可以表示为原子值的 .NET 类型;大多数值类型如 int 都符合这个描述,但一些引用类型如 Uri 和 string 也符合。
01、为什么需要控制表示方式?
记录对象到日志的方式可能有很多种。大多数类型可以很好地表示为字符串或简单值,但有些则更适合记录为集合,还有些则适合记录为具有命名属性的结构体。
日志事件属性的存储表示方式对日志的大小以及获取这些数据所需的内存和处理开销有很大影响。
考虑到这一点,我们来看看如何在简单情况下配置 Serilog。
02、默认行为
当在日志事件中指定属性时,Serilog 会尽力确定正确的表示方式。
简单的标量值
var count = 456;
Log.Information("Retrieved {Count} records", count);
在这种情况下,Count 属性的存储方式几乎没有歧义。作为一个简单的整数值,Serilog 会选择这种表示方式。
{ "Count": 456 }
这些示例使用 JSON,但相同的原则也适用于其他格式。
开箱即用,Serilog 识别以下列表作为基本标量类型,无论是否应用了其他策略:
布尔值 - bool
数值 - byte, short, ushort, int, uint, long, ulong, float, double, decimal
字符串 - string, byte[]
时间 - DateTime, DateTimeOffset, TimeSpan
其他 - Guid, Uri
可空类型 - 上述类型的可空版本
集合
如果作为属性传递的对象是IEnumerable,Serilog会将该属性视为集合。
var fruit = new[] { "Apple", "Pear", "Orange" };
Log.Information("In my bowl I have {Fruit}", fruit);
```对应的JSON包括一个数组。
```csharp
{ "Fruit": ["Apple", "Pear", "Orange"] }
Serilog 之所以这样选择,是因为大多数可枚举类型关注的是其元素,而作为结构或字符串表示不佳。
Serilog还识别Dictionary<TKey,TValue>,只要键类型是上面列出的标量类型之一。
var fruit = new Dictionary<string,int> {{ "Apple", 1}, { "Pear", 5 }};
Log.Information("In my bowl I have {Fruit}", fruit);
支持字典的格式器可以将属性记录为字典。
{ "Fruit": { "Apple": 1, "Pear": 5 }}
IDictionary<TKey,TValue> - 实现字典接口的对象不会被序列化为字典。首先,因为在.NET中检查泛型接口兼容性效率较低,其次,一个对象可能实现多个泛型字典接口,从而产生歧义。
对象
除了上述特殊处理的类型之外,Serilog 很难智能地选择数据的渲染和持久化方式。未明确用于序列化的对象往往序列化效果很差。
SqlConnection conn = ...;
Log.Information("Connected to {Connection}", conn);
(哎呀!如何序列化一个 SqlConnection 对象?)
当 Serilog 无法识别该类型且未指定操作符(见下文)时,对象将使用 ToString() 方法进行渲染。
03、保留对象结构
在许多情况下,如果可能的话,将日志事件属性序列化为结构化对象是有意义的。数据传输对象(DTOs)、消息、事件和模型通常最好通过将其分解为具有值的属性来进行日志记录。
为此,Serilog 提供了 @ 解构操作符。
var sensorInput = new { Latitude = 25, Longitude = 134 };
Log.Information("Processing {@SensorInput}", sensorInput);
(“解构”一词是从各种编程语言中借用的;它是一种用于从结构化数据中提取值的模式匹配风格。目前,Serilog 中的用法仅与该术语在概念上相关,但未来对该运算符的扩展可能会更准确地匹配其更广泛的定义。)
自定义存储的数据
通常,对复杂对象的只有部分属性是感兴趣的。要自定义 Serilog 如何持久化解构的复杂类型,可以在 LoggerConfiguration 上使用 Destructure 配置对象:
Log.Logger = new LoggerConfiguration()
.Destructure.ByTransforming<HttpRequest>(
r => new { RawUrl = r.RawUrl, Method = r.Method })
.WriteTo...
这个示例将HttpRequest类型的对象转换为仅保留RawUrl和Method属性的新对象。可以使用多种不同的解构策略,也可以通过实现 IDestructuringPolicy 创建自定义策略。
注意:提供给 Destructure.ByTransforming() 的函数必须返回与传入类型不同的类型,否则会递归调用。可以使用自定义的 IDestructuringPolicy 来实现条件转换。
操作符与格式
虽然操作符和格式都影响属性的表示方式,但它们的作用是不同的。操作符在捕获属性时被应用,用于以某种方式保留或结构化数据。而格式则仅在将属性显示为文本时使用,不会影响序列化的表示。
格式化集合和结构
当为复杂属性指定格式字符串时,它们通常会被忽略。只有可枚举类型会考虑格式字符串,并在显示时将其传递给元素。
04、强制字符串化
有时,日志记录的对象类型可能不完全确定,或者可能以不希望在日志事件中保留的方式变化。在这些情况下,$ 字符串化操作符将把属性值转换为字符串,然后再进行其他处理,无论其类型或实现的接口是什么。
var unknown = new[] { 1, 2, 3 }
Log.Information("Received {$Data}", unknown);
尽管 unknown 是一个枚举类型,但它被捕获并以字符串形式呈现。
Received "System.Int32[]"
注:相关源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner
Serilog文档翻译系列(四) - 结构化数据的更多相关文章
- Solr系列四:Solr(solrj 、索引API 、 结构化数据导入)
一.SolrJ介绍 1. SolrJ是什么? Solr提供的用于JAVA应用中访问solr服务API的客户端jar.在我们的应用中引入solrj: <dependency> <gro ...
- (四)DIH导入结构化数据
(四)DIH导入结构化数据 目前大多数的应用程序将数据存储在关系数据库(如oracle.sql server .mysql等).xml文件中.对这样的数据进行搜索是很常见的应用.所谓的DataImpo ...
- ElasticSearch 2 (13) - 深入搜索系列之结构化搜索
ElasticSearch 2 (13) - 深入搜索系列之结构化搜索 摘要 结构化查询指的是查询那些具有内在结构的数据,比如日期.时间.数字都是结构化的.它们都有精确的格式,我们可以对这些数据进行逻 ...
- WordPress插件--WP BaiDu Submit结构化数据插件又快又全的向百度提交网页
一.WP BaiDu Submit 简介 WP BaiDu Submit帮助具有百度站长平台链接提交权限的用户自动提交最新文章,以保证新链接可以及时被百度收录. 安装WP BaiDu Submit后, ...
- 【阿里云产品公测】结构化数据服务OTS之JavaSDK初体验
[阿里云产品公测]结构化数据服务OTS之JavaSDK初体验 作者:阿里云用户蓝色之鹰 一.OTS简单介绍 OTS 是构建在阿里云飞天分布式系统之上的NoSQL数据库服务,提供海量结构化数据的存储和实 ...
- Python爬虫(九)_非结构化数据与结构化数据
爬虫的一个重要步骤就是页面解析与数据提取.更多内容请参考:Python学习指南 页面解析与数据提取 实际上爬虫一共就四个主要步骤: 定(要知道你准备在哪个范围或者网站去搜索) 爬(将所有的网站的内容全 ...
- TensorFlow从1到2(六)结构化数据预处理和心脏病预测
结构化数据的预处理 前面所展示的一些示例已经很让人兴奋.但从总体看,数据类型还是比较单一的,比如图片,比如文本. 这个单一并非指数据的类型单一,而是指数据组成的每一部分,在模型中对于结果预测的影响基本 ...
- Bigtable:一个分布式的结构化数据存储系统
Bigtable:一个分布式的结构化数据存储系统 摘要 Bigtable是一个管理结构化数据的分布式存储系统,它被设计用来处理海量数据:分布在数千台通用服务器上的PB级的数据.Google的很多项目将 ...
- [转] Protobuf高效结构化数据存储格式
从公司的项目源码中看到了这个东西,觉得挺好用的,写篇博客做下小总结.下面的操作以C++为编程语言,protoc的版本为libprotoc 3.2.0. 一.Protobuf? 1. 是什么? Goo ...
- RocketMQ Schema——让消息成为流动的结构化数据
本文作者:许奕斌,阿里云智能高级研发工程师. Why we need schema RocketMQ 目前对于消息体没有任何数据格式的约束,可以是 JSON ,可以是对象 toString ,也可以只 ...
随机推荐
- WTM的项目中EFCore如何适配人大金仓数据库
一.WTM是什么 WalkingTec.Mvvm框架(简称WTM)最早开发与2013年,基于Asp.net MVC3 和 最早的Entity Framework, 当初主要是为了解决公司内部开发效率低 ...
- js 获取年、月、周、当前日期第几周、这月有那几周
查看当前日期是第几周:https://wannianli.tianqi.com/today/zhou/ //获取完整的日期 var date=new Date; var y = date.getFul ...
- WSL2连接USB设备(以USRP B210为例)
使用WSL2时,发现其无法直接识别到宿主机上插入的USB设备. 可利用USPIPD-WIN项目进行连接. 以下以USRP B210设备连接为例,展示连接过程: 安装USBIPD-WIN 项目 参考连接 ...
- Nginx 可视化配置神器NginxConfig
Nginx 是前后端开发工程师必须掌握的神器.该神器有很多使用场景:比如反向代理.负载均衡.动静分离.跨域等等. 把 Nginx 下载下来打开 conf 文件夹的 nginx.conf 文件,Ngin ...
- Python爬虫Post请求返回值为-1000
今天写了一个简单的爬虫程序,为了爬取kfc官网的餐厅数据,代码如下 # ajax的post请求--肯德基官网 def create_request(page): url='http://www.kfc ...
- 【2024最新】4000字搞懂sora!一张脑图贯穿!
话不多说,上图! 下面就是对sora的具体阐释: Sora是OpenAI推出的一款革命性的视频生成模型,能够根据文本指令.静态图像或视频生成长达60秒的完整视频.这一模型基于扩散式模型和自注意力深度学 ...
- c++ 17 demo
1 // Cpp.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并结束. 2 // 3 4 #include <iostream> 5 #includ ...
- 写写Redis十大类型stream的常用命令
前言:感觉这个好像没啥用,我没学过mq,好像这个东西用别的中间件比较好,比如kafka,rabbitmq 最后一个是bitfield,看尚硅谷介绍说那玩意基本用不着,所以那个也不看了,直接跳了,十大类 ...
- 使用update-alternatives管理GCC版本
目录 简介 操作过程 简介 当操作系统中存在多个版本的GCC时,可以使用使用update-alternatives管理默认使用的编译器版本. 本文使用gcc-9和gcc-11做演示,操作系统为ubun ...
- 5、Git之版本号
5.1.概述 每一次提交,Git 都会生成相关的版本号:每个版本号由 40 位 16 进制的数字组成. 这 40 位 16 进制的数字,是根据提交的内容,通过 SHA-1 算法计算出来的. 版本号具体 ...