Rust实现的日至收集工具.md
2020-06-25

【Rust Crate】vector 多能的日志监听工具


最近在公司需要对内部项目上日志监控, 最基本的需求是发现有 ERROR 日志时发送邮件或通过飞书 Bot 发送 消息, 这个项目大部分运维的事情都是我在做, 项目规模也不大.之前用过 filebeat, logstash 和 elasticsearch 那套, 但为了一个日志监控上那么多服务反而增加了运维成本. 刚好之前在 Crates.io 上闲逛时发现 Vector 这个工具. 试用下来 Vector 确实满足了 我的需求, 而且安装和配置都非常方便. 下面简单介绍下 Vector.

  1. 简介
  2. 安装
  3. 配置和使用
  4. 总结

简介

按照官方的说法, Vector 是一个轻量, 超快和开源的可观察管道构建工具, 与 Logstash 一族的工具相比, Vector 在显著减少 CPU 和内存占用的同时吞吐量提升了大约10倍.

官方上也给出了很多评测数据, 虽然图表标注有些问题, 而且不是 每项性能都领先, 但综合来看 Vector 确实兼顾了性能和资源.

vector IO测试

实际使用下来, Vector 性能完全够用, 而且就冲着这么好的测试数据, 有什么理由不试试呢?

Vector 最让我喜欢的一项功能是可以编写 lua 脚本自定义转换器, 把各种事件源转换成你需要的数据, 这无疑提供了强大的灵活性.

Vector 的文档非常详细, 其优点和使用场景都在文档中有详细说明, 这里不再赘述.

安装

Vector 支持三大主流操作系统, 甚至可以在树莓派中安装, 而且是纯静态文件(0.9.1版本约9mb大小), 无需担心依赖问题.

以 Ubuntu 为例

通过官网脚本

curl --proto '=https' --tlsv1.2 -sSf https://sh.vector.dev | sh

或者下载 deb 文件

curl --proto '=https' --tlsv1.2 -O https://packages.timber.io/vector/0.9.1/vector-amd64.deb

sudo dpkg -i vector-amd64.deb

至此 Vector 已经安装完毕, vector.service 也已经创建完毕可以直接启动

sudo systemctl start vector

如果需要在容器中以 daemon 或 sidecar 形式安装, 官网有也提供了详细的文档

其他平台安装方式可以翻阅 Vector/install

配置和使用

Vector 的主要概念有三个

官方给出了非常形象的图表

Vector 概念

  • sources 即数据源, 它可以是文件, Kafka流, http socket 等
  • Transforms 即变形, 在一层你可以对数据进行变换, 采样或者聚合
  • sinks 本意为沉没, 引申为数据被存储在 S3 ES Prometheus 等服务

Vector 的配置大部分都和这三个概念有关.

Vector 使用 TOML 文件作为配置文件, 如果对 TOML 不熟悉可以参考 TOML 教程

Vector 默认配置位于 /etc/vector/vector.toml, 也可以通过 --config 使用其他配置文件. 示例配置文件则位于 /etc/vector/examples/ 下.

一个最小配置示例如下

# 数据源, 这里使用 docker 容器日志
[sources.docker]
  type = "docker"
  include_containers = ["redis"]

# 数据最终输出, 这里让数据直接输出到终端上
[sinks.out]
  inputs   = ["docker"]
  type     = "console"
  encoding = "text"

启动 Vector vector --config <config_file>, 接着在另一个终端启动名为 redis 的容器, 你可以在启动 vector 的终端看到 redis 的日志

1:signal-handler (1592405245) Received SIGTERM scheduling shutdown...
1:M 17 Jun 2020 14:47:25.277 # User requested shutdown...
1:M 17 Jun 2020 14:47:25.277 * Calling fsync() on the AOF file.
1:M 17 Jun 2020 14:47:25.277 # Redis is now ready to exit, bye bye...
Jun 17 22:47:25.416  INFO vector::sources::docker: Stoped listening logs on docker container
...

另一个更复杂些的例子是监听错误日志文件, 提取错误信息(包括 Python trace back 信息)转换为内网报警系统需要的 json 数据, 最后通过 http 请求发送错误信息. 配置信息解释如下.

# 配置监听 /var/log/django/oa_error.log 文件
[sources.file]
type = "file"
include = ["/var/log/django/oa_error.log"]

# 对日志中的 trace back 信息进行处理, 合并为一个错误消息, 每个错误信息都以
# ERROR 开头
[sources.file.multiline]
start_pattern = "^ERROR"
# continue_through 告诉 vector 持续收集信息直到不满足 continue_pattern
mode = "continue_through"
condition_pattern = "^[^ERROR]"
timeout_ms = 1000

# 将原始 event 数据转换为适合发送到报警 api 的 json 数据
# 这里使用了 lua 扩展
[transforms.to_alert]
type = "lua"
inputs = ["file"]
version = "2"
# 去掉其他数据, 只使用 message 字段
hooks.process = """
function(event, emit)
    event.log.file = nil
    event.log.host = nil
    event.log.source_type = nil
    event.log.timestamps = nil
    event.log.task_data = {}
    event.log.task_data.msg = event.log.message
    event.log.task_data.channel = "xxxxx"
    event.log.task_type = "lark"
    event.log.message = nil
    emit(event)
end
"""

# 将 sinks 类型设置为 http, 可以想目标 uri 发送 post 请求
# ndjson 编码即以原始数据 post
[sinks.unotify]
type = "http"
inputs = ["to_alert"]
uri = "http://alert:6000/api/v1.0/syntasks"
encoding.codec = "ndjson"

最后效果报警展现在飞书的效果如下:

效果

总结

经过简单的使用, 我觉得 vector 在安装和使用上都非常方便, 而且有不俗的性能, 资源占用也比较小, 非常适合快速搭建监控体系的需求.