Serilog初识(二)————结构化数据

前言


本篇是本人根据对官方文档Structured data章节的内容,所做的理解总结记录,如果有什么不对的地方,望评论指出。

地址:https://github.com/serilog/serilog/wiki/Structured-Data

Serilog的默认序列化

Serilog是一个序列化器,如果我们不主动告诉Serilog数据该如何序列化的时候,Serilog对数据也有默认的序列方式。

基本标量类型的属性

如果我们要序列化的属性是简单标量类型的话,Serilog很容易识别是什么,并进行序列化,例如标量类型是int类型。

int Sum = 100;
Log.Information("序列化int类型:{Sum}", Sum);

在这里插入图片描述
Seilog遇到下列的几种类型,都会识别为基本标量。

  1. 布尔类型 bool

  2. NUMERICS(数值类型)
    byte ushort int uint long ulong float double decimal

  3. Strings (字符串类型)
    String byte[]

  4. Temporals (与时间相关)
    DateTime DateTimeOffset TimeSpan

  5. Other(其它)
    Guid Uri

  6. Nullables——以上所有类型的可空版本

集合

Serilog如果发现属性实现了IEnumerable接口,那么Serilog会识别为集合

List<int> list = new List<int>() { 1, 2, 4, 5, 78, 45 };

String[] strs = new String[] { "li", "yang", "hong" };

Log.Information("实现了IEnumerable接口的集合:{list}{strs}", list,strs);

在这里插入图片描述
同时,Serilog也认识Dictionary这个类型,不过前提是Dictionary中的Key类型是基本标量

Dictionary<string, int> dic = new Dictionary<string, int>();
dic.Add("li", 23);
dic.Add("yang", 19);
Log.Information("Dictionary类型:{dic}",dic);

在这里插入图片描述

PS:如果有实现了IDictionary<key,value>接口的字典对象但没有被序列化成字典的话,官方给出了两点解释:
1.在.NET中检查通用接口兼容性的效率较低
2.因为单个对象可能实现多个通用字典接口,从而产生歧义。
例如,我们序列化SortedDictionary这个类的对象
SortedDictionary<string, int> sdic = new SortedDictionary<string, int>();
sdic.Add(“li”, 123);
sdic.Add(“yang”, 456);
sdic.Add(“hong”, 12);`
Log.Information(“Dictionary类型:{sdic}”,sdic);
在这里插入图片描述
被Serilog认为是集合(因为实现了IEnumberable接口),序列化成集合。

对象(Object)

Serilog如果要序列化除上面描述的对象以外的对象,往往就很难做出明确的选择

定义Student类和Teacher类
abstract class Person
{
    public String Name { get; set; }
    
    public int Age { get; set; }
}

class Teacher :Person
{
        private Guid GuidID { get; set; }
        public Teacher(Guid id, string name,int age)
        {
            this.GuidID = id;
            this.Name = name;
            this.Age = age;
        }
 }
class Student:Person
{
       public Student(Guid id,string name,int age)
        {
            this.GuidID = id;
            this.Name = name;
            this.Age = age;
        }
        private Guid GuidID { get; set; }
        public Teacher teacher { get; set; }
}

            //自定义类的对象
            Teacher teacher = new Teacher("wen",45);
            Student student = new Student("lic",12);
            student.teacher = teacher;
            //HttpClient对象
            HttpClient hc = new HttpClient();
            Log.Information("自定义对象:{teacher}", teacher);
            Log.Information("Student对象:{student}", student);
            Log.Information("HttpClient对象:{hc}", hc);

在这里插入图片描述

Serilog判断不出对象是什么类型,所以调用了对象的ToString方法,并对结果进行序列化

Serilog提供了@ 解构运算符。

            Log.Information("自定义对象:{@teacher}", teacher);
            Log.Information("Student对象:{@student}", student);
            Log.Information("HttpClient对象:{@hc}", hc);

在这里插入图片描述
我们如果只是单单添加@来进行序列化,Serilog会将对象中的所有public属性给序列化。

如果我们不想序列化对象的全部public属性怎么办呢?也就是想要自定义对象结构

我们可以使用Destructure来配置LogConfiguration

            Log.Logger = new LoggerConfiguration()
                //设置最低等级
                .MinimumLevel.Debug()
                //对自定义对象进行筛选
                .Destructure.ByTransforming<Teacher>(t=>new {Name=t.Name })
                .Destructure.ByTransforming<Student>(s=>new {Name=s.Name})
                //将事件发送到控制台并展示
                .WriteTo.Console(outputTemplate:Logformat)         
                .CreateLogger();

我们再次运行程序的时候。
在这里插入图片描述
当然 除了这种方法还有其它做法可以实现效果,Serilog.Extras.Attributed程序包,这个只需要在类中属性添加一个特性,就可以告诉Serilog是否忽略,下面我们来演示一下.

abstract class Person
 {
        public String Name { get; set; }
        [NotLogged]
        public int Age { get; set; }
 }
            Log.Logger = new LoggerConfiguration()
                //设置最低等级
                .MinimumLevel.Debug()
                //使用Serilog.Extras.Attributed中的扩展方法
                .Destructure.UsingAttributes()
                //将事件发送到控制台并展示
                .WriteTo.Console(outputTemplate:Logformat)         
                .CreateLogger();

在这里插入图片描述

我们可以看到图中Age属性被Serilog忽略了

除此之外Serilog.Extras.Attributed程序包还有一个特性,[LogAsScalar]特性,这个特性会在序列化的时候调用ToString方法(没加@时Serilog对象序列化的方式)

    class Student:Person
    {
        public Student(Guid id,string name,int age)
        {
            this.GuidID = id;
            this.Name = name;
            this.Age = age;
        }
        private Guid GuidID { get; set; }
        
        [LogAsScalar]
        public Teacher teacher { get; set; }
    }

在这里插入图片描述

如果没有了[LogAsScalar] teacher对应的值是以Json形式的数据,但这种形式在日志是没有多大作用的,所以我们可以用ToString的方式来表示

参考文章

官方文档:https://github.com/serilog/serilog/wiki/Structured-Data
博客:https://nblumhardt.com/2014/07/using-attributes-to-control-destructuring-in-serilog/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值