上文我们演示了使用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向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条日志(这里你也会看到日志的显示顺序可能不能如你所愿):
下面给出[锁定库存]日志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界面我们可以便捷地完成如下分析:
- 通过{TraceId}找到某次请求所有日志
- 通过{elasped} >=10s 过滤出处理时长大于10s的阶段
- 通过{ordeid} 追踪该订单完整链路
......
总结
本文肝时较长(elasped>=10天)
- 从常规诊断日志谈到[对机器友好,适用于分析的结构化日志],其中的核心是消息模板。
- 再谈到我是如何利用NLog输出结构化日志,其中注意在NLog Target中设置
includeAllProperties=true
(默认是false), 摸索了很久 - 最后在Kibana中演示便捷的分析结构化日志
干货周边
- [消息模板] https://messagetemplates.org/
- [如何利用NLog输出结构化日志] https://github.com/nlog/nlog/wiki/How-to-use-structured-logging
- [NLog to ES] https://github.com/markmcdowell/NLog.Targets.ElasticSearch
- [TraceId]
- Logging with ElasticSearch, Kibana, ASP.NET Core and Docker
如何利用NLog输出结构化日志,并在Kibana优雅分析日志?的更多相关文章
-
利用Mongoose来结构化模式与验证
Mongoose是一个文档对象模型(ODM)库,为MongoDB Node.js原生驱动程序提供更多的功能. 把结构化的模式应用到一个MongoDB集合,提供了验证和类型转换的好处 Mongoose通 ...
-
[AI开发]基于DeepStream的视频结构化解决方案
视频结构化的定义 利用深度学习技术实时分析视频中有价值的内容,并输出结构化数据.相比数据库中每条结构化数据记录,视频.图片.音频等属于非结构化数据,计算机程序不能直接识别非结构化数据,因此需要先将这些 ...
-
有效的结构化思维训练,MECE分析法
MECE原则,表达精准分类与全面性的有效利器 结构化思维的本质就是逻辑,其目的在于对问题的思考更完整.更有条理,它帮助我们一个一个找到线头,理清思路,探求事物之间的相互联系.MECE分析法是一种结构化 ...
-
Asp.Net Core中利用Seq组件展示结构化日志功能
在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...
-
.NET Core开发日志——结构化日志
在.NET生态圈中,最早被广泛使用的日志库可能是派生自Java世界里的Apache log4net.而其后来者,莫过于NLog.Nlog与log4net相比,有一项较显著的优势,它支持结构化日志. 结 ...
-
结构化日志类库 ---- Serilog库
在过去的几年中,结构化日志已经大受欢迎.而Serilog是 .NET 中最著名的结构化日志类库 ,我们提供了这份的精简指南来帮助你快速了解并运用它. 0. 内容 设定目标 认识Serilog 事件和级 ...
-
[C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤
作者: zyl910 一.缘由 NLog是一个很好用的日志类库.利用它,可以很方便的将日志输出到 调试器.文件 等目标,还支持输出到窗体界面中的RichTextBox等目标. 而且它还支持在运行时修改 ...
-
探索ASP.Net Core 3.0系列六:ASP.NET Core 3.0新特性启动信息中的结构化日志
前言:在本文中,我将聊聊在ASP.NET Core 3.0中细小的变化——启动时记录消息的方式进行小的更改. 现在,ASP.NET Core不再将消息直接记录到控制台,而是正确使用了logging 基 ...
-
重新整理 .net core 实践篇—————日志系统之结构化[十八]
前言 什么是结构化呢? 结构化,就是将原本没有规律的东西进行有规律话. 就比如我们学习数据结构,需要学习排序然后又要学习查询,说白了这就是一套,没有排序,谈如何查询是没有意义的,因为查询算法就是根据某 ...
随机推荐
-
KPI绩效考核为何在国内不管用?
很多外国很好的管理制度,到了中国都有水土不服,就像KPI绩效考核一样,到了中国执行得很不好,甚至还不如用本土的人治管理方法,那是为何呢?为什么国内学平衡计分法和KPI的热情非常高,效果却往往有限? 其 ...
-
网友对twisted deferr的理解
事實上Deferred的確就像是一連串的動作,用callback的形式被串在一起,我們用deferred或許可以這樣寫 d.addCallback(洗菜)d.addCallback(切菜)d.addC ...
-
简单方便地扩充Python的系统路径
参考: http://www.elias.cn/Python/PythonPath?from=Develop.PythonPath http://v2in.com/pth-file-usage-in- ...
-
《你不知道的JavaScript》读书笔记(二)词法作用域
JavaScript 采用的是 词法作用域 的工作模型. 定义 词法化:大部分标准语言编译器的第一个工作阶段叫词法化(单词化),这个过程会对源代码中的字符进行检查,如果是有状态的解析过程,还会赋予单词 ...
-
解决TIME_WAIT过多问题
http://bbs.linuxtone.org/thread-853-1-1.html http://bbs.linuxtone.org/thread-2327-1-1.html
-
ubuntu装机
备份: .bashrc profile .vimrc exports defults/ 各种workspace中的源码 */ 重转后安装: apt-get install openjdk- ...
-
读取xml格式文件
$v = [xml]get-content d:\vmconfig.xml $v.Domain.Computer.Name =========================== $v.GetElem ...
-
大数据笔记06:大数据之Hadoop的HDFS(文件的读写操作)
1. 首先我们看一看文件读取: (1)客户端(java程序.命令行等等)向NameNode发送文件读取请求,请求中包含文件名和文件路径,让NameNode查询元数据. (2)接着,NameNode返回 ...
-
jquery下php与ajax的数据交换方式
参考链接:http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2013/0122/11971.html 一.前台传递字符串变量,后台返回字符串变量( ...
-
流畅python学习笔记:第十七章:并发处理
第十七章:并发处理 本章主要讨论Python3引入的concurrent.futures模块.在python2.7中需要用pip install futures来安装.concurrent.futur ...