Serilog
,将JS设置为Bunyan
。这些将输入fluentd
,然后可以处理任何事情,我最初是在考虑elasticsearch + kibana
。我们已经有一个MySQL数据库,因此短期内我对获得Serilog + Bunyan设置和开发人员使用它更感兴趣,我们可以登录MySQL,同时花一些时间来流利地使用其余部分。 br /> 但是,我们经验丰富的编码人员之一宁愿只执行以下操作:使用
log.debug("Disk quota {0} exceeded by user {1}", quota, user);
执行log4net
,然后针对MySQL运行select语句,例如:SELECT text FROM logs WHERE text LIKE "Disk quota";
更好的方法和/或在选择日志系统类型时我们需要考虑什么?
#1 楼
结构化方法有两个基本的进步,如果不使用文本日志,那么(没有(有时是极端的)额外的努力)就无法使用文本日志进行模拟。事件类型
当您编写两个使用log4net的事件,例如:
log.Debug("Disk quota {0} exceeded by user {1}", 100, "DTI-Matt");
log.Debug("Disk quota {0} exceeded by user {1}", 150, "nblumhardt");
这些将产生类似的文本:
Disk quota 100 exceeded by user DTI-Matt
Disk quota 150 exceeded by user nblumhardt
但是就机器处理而言,它们只是两行不同的文本。
您可能希望找到所有“磁盘配额已超出”事件,但是查找事件的简单情况
like 'Disk quota%'
会很快掉线。当另一个事件发生时,如下所示:Disk quota 100 set for user DTI-Matt
文本记录会丢弃我们最初获得的有关事件源的信息,并且在读取日志时必须对其进行重构相比之下,当您编写以下两个Serilog事件时:
log.Debug("Disk quota {Quota} exceeded by user {Username}", 100, "DTI-Matt");
log.Debug("Disk quota {Quota} exceeded by user {Username}", 150, "nblumhardt");
它们产生相似的文本输出到lo g4net版本,但在幕后,两个事件都携带
"Disk quota {Quota} exceeded by user {Username}"
消息模板。使用适当的接收器,以后可以编写查询
where MessageTemplate = 'Disk quota {Quota} exceeded by user {Username}'
并确切获取超出磁盘配额的事件。 br /> 在每个日志事件中存储整个消息模板并不总是很方便,因此有些接收器会将消息模板散列为数字
EventType
值(例如0x1234abcd
),或者,您可以在日志记录管道中添加增强器以自己完成此操作。比下面的下一个差异要微妙,但是在处理大量日志时功能强大。
结构化数据
再次考虑到两个有关磁盘空间使用情况的事件,使用文本日志使用
like 'Disk quota' and like 'DTI-Matt'
查询特定用户可能很容易。但是,生产诊断并不总是那么简单。想象一下是否有必要查找超出磁盘配额的磁盘空间低于125 MB的事件?
使用Serilog,可以在大多数接收器中使用以下变体来实现:
Quota < 125
可以从正则表达式构造这种查询,但是它通常很快就会累人最终只能作为最后的选择。
现在向其中添加一个事件类型:
Quota < 125 and EventType = 0x1234abcd
您开始在这里看到这些功能的方式
另一个好处是,也许不是很容易预防,但是一旦将生产调试从工作中解放出来,这又是一个好处。在regex骇客之地,开发人员开始更加重视日志,并在编写日志时多加注意和考虑。更好的日志->更高质量的应用程序->更加幸福。
评论
我喜欢这个答案。写得非常好,由于某种原因我无法解释,这使我无法自拔。
– jokab
18年1月1日,1:15
#2 楼
当您收集日志进行处理时,无论是解析到某些数据库中和/或稍后搜索处理过的日志,使用结构化日志都会使某些处理更加容易/高效。解析器可以利用已知结构(例如JSON,XML,ASN.1等),并使用状态机进行解析,而不是使用正则表达式(相对于正则表达式而言,编译和执行在计算上相对昂贵)。诸如同事建议的那样,对自由格式文本的分析往往依赖于正则表达式,并且依赖于不变的文本。这会使解析自由格式的文本变得非常脆弱(即,解析与代码中的精确文本紧密耦合)。还考虑搜索/查找情况,例如:
SELECT text FROM logs WHERE text LIKE "Disk quota";
LIKE
条件需要与每个text
行值进行比较;再次,这在计算上是相对昂贵的,尤其是在使用通配符的情况下:SELECT text FROM logs WHERE text LIKE "Disk %";
使用结构化日志记录,与磁盘错误相关的日志消息在JSON中可能看起来像这样:
{ "level": "DEBUG", "user": "username", "error_type": "disk", "text": "Disk quota ... exceeded by user ..." }
这种结构的字段可以很容易地映射到例如SQL表列名称,这意味着查找可以更具体/更细粒度:
SELECT user, text FROM logs WHERE error_type = "disk";
您可以将索引放置在您希望经常搜索/查找其值的列上,只要您不对这些列值使用
LIKE
子句。您可以将日志消息细分为特定类别的内容越多,查找的对象就越有针对性。例如,除了上面示例中的error_type
字段/列外,您甚至可以将其设置为"error_category": "disk", "error_type": "quota"
或类似的名称。日志消息中的结构越多,解析/搜索系统就越多(例如
fluentd
,elasticsearch
,kibana
)可以利用该结构,并以更高的速度和更少的CPU /内存执行其任务。希望这会有所帮助!
评论
+1想补充一点,这不仅与速度和效率有关。使用结构化日志记录和“结构化查询”时,搜索结果的相关性将更高。如果没有这种搜索,那么在不同上下文中出现的任何单词都会给您带来大量无关的点击。
– Marjan Venema
16 Mar 10 '16 at 7:31
我也+1,我认为这很重要。在下面添加了稍微不同的表述,以扩展事件类型的情况。
–尼古拉斯·布鲁姆哈特(Nicholas Blumhardt)
16-3-13的3:53
#3 楼
当您的应用每天创建数百条日志消息时,您将不会从结构化日志中获得太多好处。当您每秒从许多不同的已部署应用程序发出几百条日志消息时,您肯定会做到这一点。相关的,日志消息最终存储在ELK堆栈中的设置也适合于将日志记录到SQL成为瓶颈的情况。
我已经看到使用SQL
select .. like
建立的“基本日志记录和搜索”设置,而正则表达式则被推到了极限,以至于无法解决-存在误报,遗漏,可怕的过滤器代码以及难以维护的knwon错误,而且没有-人们想触摸,不遵循过滤器假设的新日志消息,不愿触摸代码中的日志记录语句以免破坏报告等。因此,出现了一些软件包来更好地解决此问题。 。有Serilog,听说NLog团队正在研究它,我们为Nlog编写了
StructuredLogging.Json
,我还看到新的ASP.Net核心日志记录抽象“使日志记录提供程序可以实现...结构化日志记录”。 使用StructuredLogging的示例。您可以这样登录到NLog记录器:
logger.ExtendedError("Order send failed", new { OrderId = 1234, RestaurantId = 4567 } );
此结构化数据将发送至kibana。值
1234
存储在日志条目的OrderId
字段中。然后,您可以使用kibana查询语法进行搜索,例如现在@LogType:nlog AND Level:Error AND OrderId:1234
和Message
只是OrderId
和q4312079q的所有日志条目都可以根据需要搜索完全匹配或不完全匹配的字段,也可以合计计数。这是强大而灵活的。从StructuredLogging最佳实践开始:
每次记录的消息应该相同。它应该是一个
常量字符串,而不是格式化为包含诸如
id或数量之类的数据值的字符串。这样就很容易搜索。
记录的消息
应该是不同的,即与
不相关的日志语句产生的消息不同。然后搜索不匹配
无关的事物。
评论
我同意所做的编辑。我不是在试图向某人证明某些东西,而是在试图了解结构化日志记录和基本日志记录的好处和区别。在我看来,结构化为我们提供了更大的灵活性,尤其是在日志源以及如何显示其数据方面。根据我的理解,我无法解释为什么基本日志记录和搜索MySQL比结构化日志记录更好/更糟糕。@ DTI-Matt serilog的结构化日志记录只是基本的日志记录,只有它会格式化您要打印到其中的对象-您可以通过轻松地重写ToString来自己完成操作。一个更重要的方面是日志文件的配置和管理,而不是一种将字符串格式化为另一种的方式,而另一种则是性能。如果开发人员希望使用log4net(这是一个很好的日志记录库),那么您选择serilog(看起来很酷)就是那些“寻找问题的解决方案”。
@ DTI-Matt从serilog来看,它看起来与log4net非常相似。 log4net处理在config上创建结构化日志。您无需搜索日志消息,因为可以配置其他信息并将其写入表中。还要为流利的tiptuff.org/2014/05/…配置log4net。
@gbjbaanb Serilog在将事件表示为文本时,其工作方式与log4net相同,但是如果您使用结构化格式存储日志,它将把命名属性与所传递的参数相关联(即,支持不使用正则表达式的搜索/过滤等)。 )HTH!