文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

【夜莺监控】从日志中提取指标的瑞士军刀

2024-11-30 14:53

关注

mtail是谷歌开源的一款从应用日志提取 metrics 的工具,它会实时读取应用程序的日志,然后通过自己编写的脚本分析日志,最终生成时间序列的指标,项目地址是:https://github.com/google/mtail。

夜莺的Categraf对日志指标的收集也是采用的 mtail,不过做了一些优化,具体优化了什么我们慢慢道来。

现在,我们先从谷歌的mtail开始聊起,再慢慢聊到夜莺的 mtail 插件。

mtail 的安装

前面已经对mtail做了简短的介绍,其实那就是全部。

所以,我们直接从安装开始。

从https://github.com/google/mtail/releases下载需要的版本,操作如下:

# 下载
$ wget https://github.com/google/mtail/releases/download/v3.0.0-rc51/mtail_3.0.0-rc51_Linux_x86_64.tar.gz
$ tar xf mtail_3.0.0-rc51_Linux_x86_64.tar.gz
$ cp mtail /usr/local/bin

# 查看mtail版本
$ mtail --version
mtail version 3.0.0-rc51 git revision 6fdbf8ec96a63c674c53148eeb9ec96043a2ec9c go version go1.19.4 go arch amd64 go os linux

# mtail后台启动
$ nohup mtail -port 3903 -logtostderr -progs test.mtail -logs test.log &

# 默认端口是3903
$ nohup ./mtail -progs test.mtail -logs test.log &

# 查看是否启动成功
$ ps -ef | grep mtail

# 查看mtail的帮助文档
$ mtail -h

mtail 参数详解

安装完mtail之后,如果对mtail的参数一无所知的话,也就不知道如何下手了,本小节就带大家来了解一下 mtail 有哪些参数。

我们可以通过mtail -h来查看mtail支持的参数列表,下面我对这些参数加一些中文注释,应该能够帮助你了解它们的意思了。

$ mtail -h
mtail version 3.0.0-rc51 git revision 6fdbf8ec96a63c674c53148eeb9ec96043a2ec9c go version go1.19.4 go arch amd64 go os linux

Usage:
  -address string # 绑定HTTP监听器的主机或者IP地址
  -alsologtostderr # 记录标准错误和文件
  -block_profile_rate int # 报告goroutine阻塞事件之前的阻塞时间的纳秒数。0表示关闭。
  -collectd_prefix string # 发送给collectd的指标前缀
  -collectd_socketpath string # collectd socket路径,用于向其写入metrics
  -compile_only # 仅禅师编译mtail脚本程序,不执行
  -disable_fsnotify # 是否禁用文件动态发现机制。为true时,不会监听动态加载发现的新文件,只会监听程序启动时的文件。
  -dump_ast # 解析后dump程序的AST(默认到/tmp/mtail.INFO)
  -dump_ast_types # 在类型检查之后dump带有类型注释的程序的AST(默认到/tmp/mtail.INFO)
  -dump_bytecode # dump程序字节码
  -emit_metric_timestamp # 发出metric的记录时间戳。如果禁用(默认设置),则不会向收集器发送显式时间戳。
  -emit_prog_label # 在导出的变量里面展示prog对应的标签。默认为true
  -expired_metrics_gc_interval duration # metric的垃圾收集器运行间隔(默认为1h0m0s)
  -graphite_host_port string # graphite carbon服务器地址,格式Host:port。用于向graphite carbon服务器写入metrics
  -graphite_prefix string # 发送给graphite指标的metrics前缀
  -http_debugging_endpoint # 是否开启调式接口(/debug +
/$/ {
    strptime($date, "2006/01/02 15:04:05")
}

条件判断

/pattern/ { action }是 mtail 程序中正常的条件控制流结构。

如果模式匹配,那么该块中的动作就会被执行。如果模式不匹配,则跳过该块。

else关键字允许程序在模式不匹配的情况下执行动作。

/pattern/ {
  action
} else {
  alternative
}

除此之外,还可以使用 otherwise 来处理没有匹配到的规则,如下:

{
/pattern1/ { _action1_ }
/pattern2/ { _action2_ }
otherwise { _action3_ }
}

这种语法类似于switch case default语法。

精准匹配

上面的/pattern/ { _action_ }形式隐含地匹配了当前的输入日志行。

如果想与另一个字符串变量匹配,可以使用=~操作符,或者用!~来否定匹配,像这样:

$1 =~ /GET/ {
    ...
  }

解析非数字类型的数字字段

有时候遇到的日志里输出的数字是字符串,而非数字,mtail 可以对其进行解析,如下:

counter total

/^[a-z]+ ((?P\d+)|-)$/ {
  $1 != "-" {
    total = $response_size
  }
}

解析带有额外字符的数字

一些日志包含除了包含数字,还包含分隔符,我们可以用 subst 函数删除它们:

/sent (?P[\d,]+) bytes  received (?P[\d,]+) bytes/ {
    # Sum total bytes across all sessions for this process
    bytes_total["sent"] += int(subst(",", "", $sent))
    bytes_total["received"] += int(subst(",", "", $received))
}

过滤操作

如果你想过滤一些不必要的日志被mtail采集,你可以使用stop,如下:

getfilename() !~ /apache.access.?log/ {
  stop
}

重写操作

一些日志,如网络服务器日志,描述了一些常见的元素,其中有独特的标识符,如果不加处理,会导致大量的度量衡键,而没有有用的计数。要重写这些捕获组,可以使用 subst(),将模式作为第一个参数:

hidden text route
counter http_requests_total by method, route

/(?P\S+)/ {
  route = subst(/\/d+/, "/:num", $url)
  http_requests_total[method][route]++
}

这里我们把$url中/后面的任何数字部分替换为字面字符串/:num,所以我们最终只计算 URL 路由的静态部分。

mtail 实操

说一千,道一万,不如真正来一遍。

当然,我这里也不会把上面说的都来一次。

为了方便阐述,我把本次操作的脚本都放到~/Desktop/mtail目录中。

单日志采集

# 创建prog1,里面用于保存日志处理的规则脚本
$ mkdir prog1

# 在prog1里创建prog1.mtail文件并写入以下内容
$ cat prog1.mtail
counter foo_count
/foo/{
  foo_count++
}

# 创建log1目录
$ mkdir log1

# 在log1中创建a.log文件
¥ touch a.log

# 启动mtail
$ mtail -progs ~/Desktop/mtail/prog1 -logs ~/Desktop/mtail/log1/a.log

# 向a.log中写入foo
$ echo "foo" > ~/Desktop/mtail/log1/a.log

# 查看指标明细
$ curl 127.0.0.1:3903/metrics
# HELP foo_count defined at prog1.mtail:1:9-17
# TYPE foo_count counter
foo_count{prog="prog1.mtail"} 1 # 可以看到foo_count指标数为1了

多日志采集

如果多日志在同一个文件夹里,这时候采集的指标就可能混淆。

# 在log1目录中创建b.log
$ touch b.log

# 然后为b.log重新创建一个指标脚本
$ cat prog1/prog2.mtail
counter bar_count
/bar/{
  bar_count++
}

# 启动mtail
$ mtail -progs ~/Desktop/mtail/prog1 -logs ~/Desktop/mtail/log1/a.log -logs ~/Desktop/mtail/log1/b.log

# 向b.log写入日志
$ echo "bar" >>  ~/Desktop/mtail/log1/b.log

# 查看指标
$ curl 127.0.0.1:3903/metrics
# HELP bar_count defined at prog2.mtail:1:9-17
# TYPE bar_count counter
bar_count{prog="prog2.mtail"} 2
# HELP foo_count defined at prog1.mtail:1:9-17
# TYPE foo_count counter
foo_count{prog="prog1.mtail"} 0

可以看到能正常收集指标,但是如果我们向 a.log 也写入 bar 日志,指标会增加吗?

# 向a.log写入日志
$ echo "bar" >>  ~/Desktop/mtail/log1/a.log

# 查看指标
$ curl 127.0.0.1:3903/metrics
# HELP bar_count defined at prog2.mtail:1:9-17
# TYPE bar_count counter
bar_count{prog="prog2.mtail"} 3
# HELP foo_count defined at prog1.mtail:1:9-17
# TYPE foo_count counter
foo_count{prog="prog1.mtail"} 0

可以看到指标依然会增加。其实我们的期望是prog1.mtail只收集a.log的日志指标,prog2.mtail只收集b.log的指标,不要相互影响。

如果要解决这个问题,就需要启动不同的mtail才行。换句话说有多少日志文件,如果想分开收集,则要启动多少个mtail,可以想想这是一个非常恐怖的事情。

鉴于此,Categraf 对 mtail 插件做了一些优化,优化后的 mtail 插件可以做到一个 Categraf 进程同时解析多个服务的日志,改造后的示例图如下:

Categraf 操作

在前面的夜莺监控系列中,对 Categraf 基本都有一个印象。默认情况下它的配置都在 conf 目录下,其中插件都在以 input 开头的文件夹里。

我们进入input.mtail文件夹,编辑mtail.toml并增加如下配置:

[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog1"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/a.log"]
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" #string type

[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog2"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/b.log"]
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" # string type

然后添加需要的目录以及脚本:

# 创建文件夹
$ mkdir {prog1,prog2,log1}

# 增加规则文件
$ cat prog1/a.mtail
counter foo_count
/foo/ {
  foo_count++
}

$ cat prog2/b.mtail
counter bar_count
/bar/ {
  bar_count++
}

# 增加日志文件
$ touch {log1/a.log,log1/b.log}

启动 categraf:

# 使用测试模式启动
$ ./categraf -test -inputs mtail

然后往a.log写入foo日志。

echo "foo" >> log1/a.log

然后看到指标增加了:

再往b.log写入bar日志。

echo "bar" >> log1/b.log

bar_count的指标也相应增加了。

那如果我们向a.log增加bar的日志,bar_count会增加么?我们来测试一下:

echo "bar" >> log1/a.log

通过观察bar_count指标不会增加。

Categraf 就完美解决了不同日志指标错乱的问题。

除了正常的处理指标,如果想给不同的instance指定label,也是可以的,如下:

[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog1"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/a.log"]
labels = {"app"= "foo"}
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" #string type

[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog2"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/b.log"]
labels = {"app"= "bar"}
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" # string type

重启 Categraf 就可以看到指标多了一个 label。

其他的脚本语法和原生的 mtail 一致,这里不再追溯了。

总结

相比于谷歌的mtail,categraf对mtail做了一些优化,可以更好的处理多日志的问题。而且 categraf 本身集成了很多插件,都可以统一使用它实现。

另外,还是相同的问题,假设插件开启比较多,categraf 的具体性能如何以及会不会影响主机的整体性能,这还有待研究。

来源:运维开发故事内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯