如何利用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向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的视频结构化解决方案
视频结构化的定义 利用深度学习技术实时分析视频中有价值的内容,并输出结构化数据.相比数据库中每条结构化数据记录,视频.图片.音频等属于非结构化数据,计算机程序不能直接识别非结构化数据,因此需要先将这些 ...
- 视频结构化 AI 推理流程
「视频结构化」是一种 AI 落地的工程化实现,目的是把 AI 模型推理流程能够一般化.它输入视频,输出结构化数据,将结果给到业务系统去形成某些行业的解决方案. 换个角度,如果你想用摄像头来实现某些智能 ...
- 有效的结构化思维训练,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 基 ...
随机推荐
- The solution for apt-get update Err 404
最近在ubuntu 12.10上执行sudo apt-get update 命令后出现了如下错误: Ign http://extras.ubuntu.com natty/main Translatio ...
- 网络编程-UDP、TCP
总结
- bzoj2016[Usaco2010]Chocolate Eating*
bzoj2016[Usaco2010]Chocolate Eating 题意: n块巧克力,每次吃可以增加ai点快乐,每天早晨睡觉起来快乐值会减半,求如何使d天睡觉前的最小快乐值最大.n,d≤5000 ...
- 测试人员应该掌握的oracle知识体系
闲来无事,总结了一下,软件测试人员应该掌握的基本的oracle数据库知识体系 1.安装 1.1 oracle安装 1.2 oracle升级 1.3 oracle补丁 2.管理 2.1数据库创建(dbc ...
- Ethical Hacking - GAINING ACCESS(1)
Gaining Access Introduction Everything is a computer Two main approaches (1)Server Side Do not requi ...
- spring oauth2获取当前登录用户信息。
使用spring oauth2框架做授权鉴定.想获取当前用户信息怎么办? 我们知道spring oauth2是基于spring security的实现的. spring security可以通过Sec ...
- C++语法小记---异常处理
异常处理(C语言) 异常是对代码中可以预知的问题进行处理:代码中不可以预知的问题叫Bug: if () { ... } else { ... } setjmp和longjmp #include < ...
- 请解释ASP.NET中的web页面与其隐藏类之间的关系
其实页面与其隐藏类之间就是一个部分类的关系,你在页面上放一个一个的控件就是在这个类中定义一个一个的属性, 因为是同一个类的部分类的关系,所以隐藏类可以访问到页面上控件,这样做是为了把展现与处理逻辑分开 ...
- java代码之美(17) ---Java8 LocalDateTime
Java8 LocalDateTime 在java8之前我们在处理时间的时候都是用的Date,但它其实有很明显的缺点. 1.我们也会对日期做一些操作,比如加几天.加几分,当月的最后一天等等.有些计算实 ...
- IO、NIO实现简单聊天室,附带问题解析
本篇文章主要使用IO和NIO的形式来实现一个简单的聊天室,并且说明IO方法存在的问题,而NIO又是如何解决的. 大概的框架为,先提供思路和大概框架图--代码--问题及解决方式,这样会容易看一点 ...