2022 年,作者团队在一个分布式集群(20 多台主机)中工作,该服务每小时打印约 200 - 300 万条日志,使用 Graylog 时查询一小时日志不超过 1 - 3 秒,速度较快。但基础设施人员讨厌 Graylog,需他们进行烦人的维护,于是决定切换到 Splunk。然而,Splunk 非常缓慢,“Smart”模式查询一小时日志需几分钟,“Fast”模式也需 30 - 60 秒,且有其他限制,没人知道如何或不想修复,显然一旦 Graylog 关闭,将无法快速查询日志,这让作者团队很沮丧。
作者认为 2 - 300 万条日志不算多,用普通日志文件的老式 shell 技巧,无需集中式日志服务器,应该能像 Graylog 一样快(或至少比 Splunk 快得多),且能满足大部分需求。于是作者利用一周时间进行个人黑客马拉松,实现了一个带有简单终端 UI 的概念验证日志获取器和查看器,直接通过 ssh 连接主机并使用bash
、tail
、head
、awk
等技巧分析普通日志文件。
目标
- 实现一个日志获取器和查看器,满足大部分 Graylog 的需求,97%的情况下只需获取过去一小时或一天的带有时间线直方图的日志并进行各种模式过滤,且要快速;3%的情况下使用更高级的功能,如获取消息统计(通常是特定消息出现的次数)。
- 具体目标包括:同时从多个远程主机获取日志、按时间范围和模式过滤日志、为所选时间范围的过滤日志绘制时间线直方图、UI 只显示最新日志并能分页获取旧日志、日志查询要足够快,目标是达到 Graylog 级别的性能(处理过去一小时的 2 - 300 万条日志需 1 - 3 秒)。
实现:遇见 Nerdlog
- 客户端是一个用 Go 编写的终端 UI 应用,利用tview库显示日志和时间线直方图,建立到每个需要收集日志的主机的单独 ssh 连接,通过在 ssh 连接上使用
bash
、awk
等标准 GNU 工具从主机过滤相关日志并生成时间线直方图数据,在客户端聚合所有远程主机的响应并在 UI 上呈现。 - 由于终端 UI 带有一定的“书呆子气”,且受 Graylog 启发(即使是松散的),作者将该项目命名为Nerdlog。
- 代理脚本:在远程主机上运行的部分,用于实际的日志过滤,是一个 bash 脚本,利用其他 GNU 工具。首先确定从何处读取日志,有从普通日志文件(如
/var/log/syslog
)和使用journalctl
两种主要选项,2022 年作者选择了普通日志文件,因为其性能更高且不会丢失日志,journalctl
虽方便但速度慢很多(在作者的测试中慢 90 倍)且在 FreeBSD 上不可用。 - 过滤日志:需要按时间范围和模式两种方式过滤,快速确定使用
awk
作为数据处理工具,模式过滤很简单,通过!/foo/ && (/bar/ || /baz/)
等方式实现。时间范围过滤较复杂,最初尝试直接比较时间字符串,速度不够快,后来通过维护从时间戳到行号(或字节偏移)的索引来快速选择相关日志段,先按时间顺序处理日志生成索引文件,再利用tail
和head
根据索引裁剪日志,使用字节偏移索引可进一步提速 2 - 3 倍。 - 打印有用数据:通过
awk
脚本处理匹配过滤器的日志,为时间线直方图生成映射(以分钟为单位的时间字符串到消息数量的映射),并维护一个包含最后 N 条日志消息的循环缓冲区,最终打印这两个映射的数据,此过程增加 2 - 3 倍时间,但仍足够快。 - 缺失细节:实际实现中省略了很多细节,如错误处理、从多个文件读取连续日志、索引无效和重新生成、数据压缩传输、打印进度信息、处理时间范围超出可用日志范围等角落情况,目前的代理脚本较混乱且难以阅读,作者希望有时间进行重写。
- 客户端应用:包括 UI(耗时最多的是让时间线直方图按要求工作,需创建新的小部件并手动处理绘图和事件处理)和连接管理及日志聚合,实现相对简单,可查看 Github 仓库了解更多细节。
黑客马拉松结果
查询性能比预期好,处理过去一小时的 2 - 300 万条日志的查询通常低于 2 秒,比 Graylog 更快且更可靠,不会重新排序或丢失消息。使用简单的文本文件和标准工具通过 ssh 处理,体现了简单的力量。
演示
展示了 Nerdlog 在四个远程主机上工作的快速演示。
项目状态
自 2022 年初始实现以来,代码仍有黑客马拉松风格的痕迹,需进一步打磨,但项目已显著成熟,只下载最小量数据节省时间和带宽,大部分数据在传输中压缩节省带宽,除普通日志文件外还支持journalctl
,可在多个主要平台上运行(客户端可在 Windows 上运行,但不能从 Windows 主机获取日志),作者已在工作和个人项目中使用多年,认为可在实际生产系统中使用,但仍有一些功能待实现。
与 Graylog 的比较
- 不是 Graylog 的等价物,但对作者来说是一个非常可行的替代方案,在大多数日志需求上足够,甚至在某些方面更好,如不会丢失或重新排序日志,使用键盘导航的终端应用比有点笨拙的 Web UI 更清爽。而且无需设置或集中式服务器,适合小项目和 DevOps / 系统管理员使用。
- Graylog 有一些 Nerdlog 没有的优势,如某些有用的功能(目前 Nerdlog 尚未实现)。
显著缺失功能:
- 自定义字段解析:目前 Nerdlog 对日志的解析是硬编码的,无法自定义,作者计划集成 Lua 脚本让用户自定义消息解析逻辑,以实现更多自定义字段。
- 统计:缺少像 Graylog 中的“Quick Values”功能,即获取不同消息及其出现次数的统计,目前可通过正则表达式实现类似功能,但尚未实现。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。