在.NET生态圈中,最早被广泛使用的日志库可能是派生自Java世界里的Apache log4net。而其后来者,莫过于NLog。Nlog与log4net相比,有一项较显著的优势,它支持结构化日志。

结构化日志,也被称为语义化日志。其作用有二,利于查询与方便分析。

当系统上线被广泛使用或者时间久远之后,日志的大量出现不可避免。且日志本身作为一种数据,也有其重要的价值。因此,如何有效地对其进行查询以及最大价值化地分析处理便成了一个重要的问题。

非结构化日志

对于日志的处理,需要权衡对开发者的友好性与对程序解析的方便性。传统的非结构化日志更倾向于前者。当开发者想要记录一段日志时,他可以很简单地加上一行代码,即可达成其目的。

logger.Info("Logon by user:{0} from ip_address:{1}", "Kenny", "127.0.0.1");

然后这行代码的执行结果可能被存于文本文件或者数据库中。

2018-12-22 16:29:29.2793|Info|Logon by user:Kenny from ip_address:127.0.0.1

这样的日志以开发者的角度来看,清晰易懂,十分友好。但如果要使用程序去查找海量的上述例子里的某段时间内的特定登陆用户,则很难高效地完成这一要求,因为需要对每个日志进行字符串解析。

消息模板

消息模板规范是结构化日志的通用语法,其是一个与开发语言无关的规范,能以特定格式捕获及呈现结构化日志,同时提供对开发者与程序解析的友好支持。

以上图片中的日志记录方式乍看起来与非结构化日志差不多,但它们之间具有本质的区别,在结构化日志里,是以对象而非字符串处理日志内容的。

如果将非结构化日志例子里的代码改成结构化日志的写法。

logger.Info("Logon by {user} from {ip_address}", "Kenny", "127.0.0.1");

执行后两者的结果是这样的:

2018-12-22 16:29:29.2793|Info|Logon by user:Kenny from ip_address:127.0.0.1
2018-12-22 16:29:29.2976|Info|Logon by "Kenny" from "127.0.0.1"

似乎差别并不大,再将输出类型改成JSON风格看看:

{ "time": "2018-12-22 16:30:15.1314", "level": "INFO", "message": "Logon by user:Kenny from ip_address:127.0.0.1" }
{ "time": "2018-12-22 16:30:15.1569", "level": "INFO", "message": "Logon by \"Kenny\" from \"127.0.0.1\"", "user": "Kenny", "ip_address": "127.0.0.1" }

显而易见,对于后者,因为user被作为对象的属性独立分离出来,在做程序处理时,可以很方便地以其为条件进行筛选。这对于查询或者分析日志是极为重要的。

NLog

NLog中对于结构化日志的支持是在4.5版本才开始的。这一改动并不会破坏原有的代码,而如果想要使用新的特性,则只要用符合消息模板的语法编写所需的代码即可。

代码的格式化结果依据数据的类型而定。

  • 字符串类型将被双引号包围

  • 数值类型没有引号

  • null显示为NULL

  • 列表或数组类型,以逗号分隔,例如:"item1", "item2"

  • 字典类型,健与值之间用等号相联,例如:"key1"="value1", "key2"="value2"

  • 对象类型,调用ToString方法显示结果

此外,还可以有@与$符号:

  • @ 以JSON格式格式化数据

  • $ 强制调用ToString方法

而将日志输出格式改成JSON的方法,是在NLog.config配置文件里将布局切换成JsonLayout类型,同时设置includeAllPropertiestrue,以显示所有对象属性。

<target name="console" xsi:type="Console"><layout xsi:type="JsonLayout" includeAllProperties="true"><attribute name="time" layout="${longdate}" /><attribute name="level" layout="${level:upperCase=true}"/><attribute name="message" layout="${message}" /></layout></target>

Serilog

能够实现结构化日志的类库除了NLog之外,其它较常用的当属Serilog。

与NLog相比,Serilog省去了配置文件,直接使用代码,实现方式更加简洁。

执行结果:

{"Timestamp":"2018-12-22T17:15:23.6389082+08:00","Level":"Information","MessageTemplate":"Processed {@Position} in {Elapsed:000} ms.","Properties":{"Position":{"Latitude":25,"Longitude":134},"Elapsed":34},"Renderings":{"Elapsed":[{"Format":"000","Rendering":"034"}]}}

原文地址:https://www.cnblogs.com/kenwoo/p/9906185.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

.NET Core开发日志——结构化日志相关推荐

  1. ASP.NET Core 沉思录 - 结构化日志

    在 <ASP.NET Core 沉思录 - Logging 的两种介入方法>中我们介绍了 ASP.NET Core 中日志的基本设计结构.这一次我们来观察日志记录的格式,并进一步考虑如何在 ...

  2. 如何利用NLog输出结构化日志,并在Kibana优雅分析日志?

    上文我们演示了使用NLog向ElasticSearch写日志的基本过程(输出的是普通文本日志),今天我们来看下如何向ES输出结构化日志.在Kibana中分析日志. 什么是结构化日志? 当前互联网.物联 ...

  3. 结构化日志:出错时你最想要的好朋友

    目录 介绍 什么是日志? Grab中日志的状况 为什么改变? 结构化日志 支持不同格式的多写 开发中类似生产环境的日志 因果顺序 但为什么要结构化记日志? 原文:Structured Logging: ...

  4. Beats: 使用 Filebeat 进行日志结构化 - Python

    结构化日志背后的想法很简单:让应用程序直接编写 JSON 对象,而不是让应用程序将需要通过正则表达式解析的日志写入到你索引到 Elasticsearch 的 JSON 对象中. 举例来说,假设你正在编 ...

  5. Asp.Net Core中利用Seq组件展示结构化日志功能

    在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...

  6. 日志结构化,SQL来查询

    通常,日志文件都是文本格式,其中的内容是非结构化的文本串.这就使得我们查询日志信息时,一般只能使用文本编辑软件的搜索功能,输入关键字后,靠眼力去侦查每处匹配结果.在日志量不大,或者只是偶尔查一下时,这 ...

  7. Self-Attentive 基于自注意力分类的非结构化日志异常检测

    原文:Self-Attentive Classification-Based Anomaly Detection in Unstructured Logs 理解:使用目标数据集和辅助数据集训练,使目标 ...

  8. .Net Core with 微服务 - Seq 日志聚合

    上一次我们介绍并演示了如果使用 Consul 做为我们微服务的注册中心,来实现服务的注册与发现.那么本次我们讲会演示如何做日志聚合.日志聚合比较常用的有 ELK 等,但是这次我想要介绍的是一款比较小众 ...

  9. Go 学习笔记(54)— Go 第三方库之 uber-go/zap/lumberjack(记录日志到文件、支持自动分割日志、支持日志级别、打印调用文件、函数和行号)

    1. 简要说明 zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割,这里我们可以使用 lumberjack 也是 zap 官方推荐用于日志分 ...

最新文章

  1. 解析广泛应用于NLP的自注意力机制(附论文、源码)
  2. Surf算法学习心得(一)——算法原理
  3. 【spring 配置文件】spring配置文件的解析
  4. Oracle表连接深入浅出
  5. 关于相对布局RelativeLayout的各种属性介绍
  6. 为什么梯度反方向是函数下降最快的方向
  7. C中的malloc:C中的动态内存分配
  8. Zookeeper架构及FastLeaderElection机制
  9. 企业级docker私有仓库的配置与使用
  10. [HTML5]块和内联元素的嵌套
  11. GWR学习笔记(一)
  12. sql插入后返回id
  13. 关于navicat设置主键属性identity
  14. 白盒测试技术—逻辑覆盖方法
  15. 正文 第二章 通背拳
  16. 国家电力项目思路总结
  17. pinyin4j获取多音字首字母同时保留非中文字符
  18. 奋斗正当时|云畅科技2022财年启动会顺利召开
  19. DB2表空间操作详解
  20. 解决org.springframework.beans.factory.NoUniqueBeanDefinitionException No qualifying bean of type

热门文章

  1. PIE SDK与OpenCV结合说明文档
  2. Unbuntu 自动重启MySQL
  3. 用jekyll制作高大上的网站(二)——实际应用
  4. exchange2013 owa-outlook界面语言
  5. setTimeout(function(){}, 0);
  6. 转 php include
  7. Ansible 一步一步从入门到精通(一)
  8. ffmpeg speex转换为mp3或者aac
  9. 成不了天才,但为何也没成人材?(转)
  10. Java类的继承总结