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

时间:2022-09-11 09:57:07

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

上文我们演示了使用NLog向ElasticSearch写日志的基本过程(输出的是普通文本日志),今天我们来看下如何向ES输出结构化日志、并利用Kibana中分析日志。

  • NLog输出结构化日志
  • ElasticSearch面向文档

什么是结构化日志?

当前互联网、物联网、大数据突飞猛进,软件越复杂,查找任何给定问题的起因就越困难(且成本更高)。

在实践中我们开发了各种规避、诊断应用程序错误行为的利器:

静态类型检查自动化测试事件探查器崩溃转储监视系统。但是记录程序执行步骤的日志仍然是事后诊断最丰富的数据源。

在日志分析时,小批量普通的文本对于人类很友好,但却很难从大量普通文本中快速定位、精准提取特定信息。

.....
[2018-04-07T13:45:56.789Z INF] https://example.com/api/warehouse,query reserve,took 100 ms
[2018-04-07T13:45:56.789Z INF] api/commitOrder,OrderId:9876543210,commit order took 50 ms
......
[2018-04-07T13:45:56.789Z INF] /login,user:Kenny,from ip_address:127.0.0.1,took 100 ms
......
[2018-04-07T13:45:56.789Z INF] https://example.com/api/warehouse,OrderId:9876543210,decrease reserve took 10000 ms
[2018-04-07T13:45:56.789Z INF] /api/creatNewOrder,OrderId:9876543210, create order took 100 ms
.....
  • 如果找到特定OrderId?
  • 如何找到哪些请求耗时较长(比如大于2S)?
  • 如何定位到该耗时请求处理管道中哪一段出现性能瓶颈?
  • 出现性能瓶颈的请求占比?

普通文本对人类友好,对于机器不友好。

结构化日志提出了Message template来解决日志对机器不友好的问题。

Messgae Template: 是一个与语言无关的规范,以对人类和机器友好的格式捕获、呈现结构化的日志事件。

var traceid = _.TraceIdentifier;
// 【锁定库存】 这个动作耗时较长
_logger.LogInformation("{TraceId},{endpoint},OrderId:{orderId},decrease reserve took {elasped} ms", traceid, "https://example.com/api/warehouse", 9876543210, 10000);

注意命名占位符,它们能如格式化字符串占位符{0}{1}一样占位,而且能将属性名称与每个匹配位置的消息数据相关联,如下图以json格式提取了关键消息。

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

消息模板的优势在于:既能保持普通文本的格式,又具备捕获结构化数据的能力(对机器友好)。


下面来完整输出、分析提交订单请求的日志:

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

利用NLog向ES输出结构化日志

NLog4.5引入结构化日志,支持Message Template, 在ASP.NET Core脚手架Startup文件--->Configure方法添加如下代码:

 app.MapWhen(_ => _.Request.Path.Value == "/" ,
appBuilder => appBuilder.Run(_ =>
{
var traceid = _.TraceIdentifier;
// 查询库存
_logger.LogInformation("{traceId},{endpoint},query reserve,took{elasped} ms", traceid, "https://example.com/api/warehouse", 100); // 创建订单
_logger.LogInformation("{traceId},{endpoint},OrderId:{orderId}, create order took {elasped} ms", traceid, "/api/creatNewOrder", 9876543210, 100); // 锁定库存
_logger.LogInformation("{traceId},{endpoint},OrderId:{orderId},decrease reserve took {elasped} ms", traceid, "https://example.com/api/warehouse", 9876543210, 10000); // 提交订单
_logger.LogInformation("{traceId},{endpoint},OrderId:{orderId},commit order took {elasped} ms", traceid, "api/commitOrder", 9876543210, 50); _.Response.StatusCode = StatusCodes.Status200OK;
_.Response.WriteAsync("Generate Order OK!");
return Task.CompletedTask;
}));

这里我们关注如何向ElasticSearch输出结构化日志,请务必将includeAllProperties="true",这样输出到ES的才会包含所有事件属性。

<target name="elastic" xsi:type="BufferingWrapper" flushTimeout="5000">
<target xsi:type="ElasticSearch" includeAllProperties="true" index="logstash-20200805" uri="${configsetting:item=ConnectionStrings.ElasticUrl}" />
</target>

Kibana中分析日志

这个订单请求,会产生6条日志(这里你也会看到日志的显示顺序可能不能如你所愿):

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

下面给出[锁定库存]日志ES文档, 文档上已经出现了关键的消息属性[traceId] [endpoint] [orderId] [elasped]

{
"_index": "logstash-20200805",
"_type": "logevent",
"_id": "emTivXMBwcdwe4RliB9f",
"_version": 1,
"_score": null,
"_source": {
"@timestamp": "2020-08-05T17:10:00.7170456+08:00",
"level": "Info",
"message": "2020-08-05 17:10:00.7170|INFO|EqidManager.Startup|0HM1P3TAGNJ5Q:00000001,https://example.com/api/warehouse,OrderId:9876543210,decrease reserve took 10000 ms",
"TraceId": "0HM1P3TAGNJ5Q:00000001",
"endpoint": "https://example.com/api/warehouse",
"orderId": 9876543210,
"elasped": 10000
},
"fields": {
"@timestamp": [
"2020-08-05T09:10:00.717Z"
]
},
"sort": [
1596618600717
]
}

通过Kibana界面我们可以便捷地完成如下分析:

  1. 通过{TraceId}找到某次请求所有日志
  2. 通过{elasped} >=10s 过滤出处理时长大于10s的阶段
  3. 通过{ordeid} 追踪该订单完整链路

    ......

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

总结

本文肝时较长(elasped>=10天)

  • 从常规诊断日志谈到[对机器友好,适用于分析的结构化日志],其中的核心是消息模板。
  • 再谈到我是如何利用NLog输出结构化日志,其中注意在NLog Target中设置includeAllProperties=true(默认是false), 摸索了很久
  • 最后在Kibana中演示便捷的分析结构化日志

干货周边

  1. [消息模板] https://messagetemplates.org/
  2. [如何利用NLog输出结构化日志] https://github.com/nlog/nlog/wiki/How-to-use-structured-logging
  3. [NLog to ES] https://github.com/markmcdowell/NLog.Targets.ElasticSearch
  4. [TraceId]
  5. Logging with ElasticSearch, Kibana, ASP.NET Core and Docker

如何利用NLog输出结构化日志,并在Kibana优雅分析日志?的更多相关文章

  1. 利用Mongoose来结构化模式与验证

    Mongoose是一个文档对象模型(ODM)库,为MongoDB Node.js原生驱动程序提供更多的功能. 把结构化的模式应用到一个MongoDB集合,提供了验证和类型转换的好处 Mongoose通 ...

  2. &lbrack;AI开发&rsqb;基于DeepStream的视频结构化解决方案

    视频结构化的定义 利用深度学习技术实时分析视频中有价值的内容,并输出结构化数据.相比数据库中每条结构化数据记录,视频.图片.音频等属于非结构化数据,计算机程序不能直接识别非结构化数据,因此需要先将这些 ...

  3. 有效的结构化思维训练,MECE分析法

    MECE原则,表达精准分类与全面性的有效利器 结构化思维的本质就是逻辑,其目的在于对问题的思考更完整.更有条理,它帮助我们一个一个找到线头,理清思路,探求事物之间的相互联系.MECE分析法是一种结构化 ...

  4. Asp&period;Net Core中利用Seq组件展示结构化日志功能

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

  5. &period;NET Core开发日志——结构化日志

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

  6. 结构化日志类库 ---- Serilog库

    在过去的几年中,结构化日志已经大受欢迎.而Serilog是 .NET 中最著名的结构化日志类库 ,我们提供了这份的精简指南来帮助你快速了解并运用它. 0. 内容 设定目标 认识Serilog 事件和级 ...

  7. &lbrack;C&num;&rsqb; 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤

    作者: zyl910 一.缘由 NLog是一个很好用的日志类库.利用它,可以很方便的将日志输出到 调试器.文件 等目标,还支持输出到窗体界面中的RichTextBox等目标. 而且它还支持在运行时修改 ...

  8. 探索ASP&period;Net Core 3&period;0系列六:ASP&period;NET Core 3&period;0新特性启动信息中的结构化日志

    前言:在本文中,我将聊聊在ASP.NET Core 3.0中细小的变化——启动时记录消息的方式进行小的更改. 现在,ASP.NET Core不再将消息直接记录到控制台,而是正确使用了logging 基 ...

  9. 重新整理 &period;net core 实践篇—————日志系统之结构化&lbrack;十八&rsqb;

    前言 什么是结构化呢? 结构化,就是将原本没有规律的东西进行有规律话. 就比如我们学习数据结构,需要学习排序然后又要学习查询,说白了这就是一套,没有排序,谈如何查询是没有意义的,因为查询算法就是根据某 ...

随机推荐

  1. KPI绩效考核为何在国内不管用?

    很多外国很好的管理制度,到了中国都有水土不服,就像KPI绩效考核一样,到了中国执行得很不好,甚至还不如用本土的人治管理方法,那是为何呢?为什么国内学平衡计分法和KPI的热情非常高,效果却往往有限? 其 ...

  2. 网友对twisted deferr的理解

    事實上Deferred的確就像是一連串的動作,用callback的形式被串在一起,我們用deferred或許可以這樣寫 d.addCallback(洗菜)d.addCallback(切菜)d.addC ...

  3. 简单方便地扩充Python的系统路径

    参考: http://www.elias.cn/Python/PythonPath?from=Develop.PythonPath http://v2in.com/pth-file-usage-in- ...

  4. 《你不知道的JavaScript》读书笔记(二)词法作用域

    JavaScript 采用的是 词法作用域 的工作模型. 定义 词法化:大部分标准语言编译器的第一个工作阶段叫词法化(单词化),这个过程会对源代码中的字符进行检查,如果是有状态的解析过程,还会赋予单词 ...

  5. 解决TIME&lowbar;WAIT过多问题

    http://bbs.linuxtone.org/thread-853-1-1.html http://bbs.linuxtone.org/thread-2327-1-1.html

  6. ubuntu装机

    备份: .bashrc profile .vimrc exports defults/ 各种workspace中的源码 */ 重转后安装: apt-get install openjdk- ...

  7. 读取xml格式文件

    $v = [xml]get-content d:\vmconfig.xml $v.Domain.Computer.Name =========================== $v.GetElem ...

  8. 大数据笔记06:大数据之Hadoop的HDFS(文件的读写操作)

    1. 首先我们看一看文件读取: (1)客户端(java程序.命令行等等)向NameNode发送文件读取请求,请求中包含文件名和文件路径,让NameNode查询元数据. (2)接着,NameNode返回 ...

  9. jquery下php与ajax的数据交换方式

    参考链接:http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2013/0122/11971.html 一.前台传递字符串变量,后台返回字符串变量( ...

  10. 流畅python学习笔记:第十七章:并发处理

    第十七章:并发处理 本章主要讨论Python3引入的concurrent.futures模块.在python2.7中需要用pip install futures来安装.concurrent.futur ...