求救!!!!有没有大佬能解决我下面的问题的!!!
1.概述
mtail 是用于从应用程序日志中提取指标以导出到时间序列数据库或时间序列计算器以进行警报和仪表板显示的工具。简单来说,就是实时读取应用程序的日志,并且通过自己编写的脚本实时分析,最终生成时间序列指标的工具。
开源仓库地址:mtail
2、参数详解
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/*),默认开启
-http_info_endpoint # 是否开始info接口(/progz,/varz),默认开启
-ignore_filename_regex_pattern string # 需要忽略的日志文件名字,支持正则表达式。使用场景:当-logs参数指定的为一个目录时,可以使用ignore_filename_regex_pattern 参数来忽略一部分文件
-jaeger_endpoint string # 如果设为true,可以将跟踪导出到Jaeger跟踪收集器。使用–jaeger_endpoint标志指定Jaeger端点URL
-log_backtrace_at value # 当日志记录命中设置的行N时,发出堆栈跟踪
-log_dir string # mtail程序的日志文件的目录,与logtostderr作用类似,如果同时配置了logtostderr参数,则log_dir参数无效
-logs value # 监控的日志文件列表,可以使用,分隔多个文件,也可以多次使用-logs参数,也可以指定一个文件目录,支持通配符*,指定文件目录时需要对目录使用单引号。
-logtostderr # 直接输出标准错误信息,编译问题也直接输出
-max_recursion_depth int # 以解析的标记来衡量mtail语句的最大长度。过长的mtail表达式可能会导致编译和运行时的性能问题。(默认为100)
-max_regexp_length int # 一个mtail regexp表达式的最大长度。过长的模式可能会导致编译和运行时的性能问题。(默认为1024)
-metric_push_interval duration # metric推送时间间隔,单位:秒,默认60秒
-metric_push_interval_seconds int # 弃用,用--metric_push_interval代替
-metric_push_write_deadline duration # 在出现错误退出之前等待推送成功的时间。(默认10s)
-mtailDebug int # 设置解析器debug级别
-mutex_profile_fraction int # 报告的互斥争夺事件的比例。 0将关闭
-one_shot # 此参数将编译并运行mtail程序,然后从指定的文件开头开始读取日志(从头开始读取日志,不是实时tail),然后将收集的所有metrics打印到日志中。此参数用于验证mtail程序是否有预期输出,不用于生产环境。
-one_shot_format string # 与-one_shot一起使用的格式。这只是一个调试标志,不适合生产使用。支持的格式: json, prometheus. (默认为 "json")
-override_timezone string # 设置时区,如果使用此参数,将在时间戳转换中使用指定的时区来替代UTC
-poll_interval duration # 设置轮询所有日志文件以获取数据的间隔;必须为正,如果为零将禁用轮询。使用轮询模式,将仅轮询在mtail启动时找到的文件
-poll_log_interval duration # 设置找到所有匹配的日志文件进行轮询的时间间隔;必须是正数,或者是0来禁用轮询。 在轮询模式下,只有在mtail启动时发现的文件会被轮询。(默认250ms)
-port string # 监听的http端口,默认3903
-progs string # mtail脚本程序所在路径
-stale_log_gc_interval duration # stale的垃圾收集器运行间隔(默认为1h0m0s)
-statsd_hostport string # statsd地址,格式Host:port。用于向statsd写入metrics
-statsd_prefix string # 发送给statsd指标的metrics前缀
-stderrthreshold value # 严重性级别达到阈值以上的日志信息除了写入日志文件以外,还要输出到stderr。各严重性级别对应的数值:INFO—0,WARNING—1,ERROR—2,FATAL—3,默认值为2.
-syslog_use_current_year # 如果时间戳没有年份,则用当前年替代。(默认为true)
-trace_sample_period int # 用于设置跟踪的采样频率和发送到收集器的频率。将其设置为100,则100条收集一条追踪。
-unix_socket string # socket监控地址
-v value # v日志的日志级别,该设置可能被 vmodule标志给覆盖.默认为0.
-version # 打印mtail版本
-vm_logs_runtime_errors # 启用运行时错误的记录到标准日志。 如果设置为false,则只将错误打印到HTTP控制台。(默认为true)
-vmodule value # 按文件或模块来设置日志级别,如:-vmodule=mapreduce=2,file=1,gfs*=3
3.mtail脚本语法
标准格式为:
COND {
ACTION
}
其中COND
是一个条件表达式。它可以是正则表达式,也可以boolean类型的条件语句。如下:
/foo/ {
ACTION1
}
variable > 0 {
ACTION2
}
/foo/ && variable > 0 {
ACTION3
}
COND
表达式可用的运算符如下:
- 关系运算符:
< , <= , > , >= , == , != , =~ , !~ , || , && , !
- 算术运算符:
| , & , ^ , + , - , * , /, << , >> , **
- 导出的指标变量可用的运算符如下:
= , += , ++ , –
4、mtail支持的数据类型(对应prometheus中的指标类型)
counter 单调递增的指标,只增不减
gauge 可以任意变化的指标,可增可减
histogram 数据直方图
5、一些参数与内置变量
修改导出指标名称因为默认指标只支持C类型名称,就是不支持下划线,可通过别名的形式导出
# 原名称:lines_total,变更后导出名称:lines-total
counter lines_total as "lines-total"
导出指标tag新增
# 这里为gauge类型的指标err_count新增两个tag(date、level)
gauge err_count by date, level
/.*/ {
err_count["date", "level"] # 在一个中括号也行,分开也可以
}
命名提取
# level就是变量名
# 原始日志:
# 2025-07-25 11:32:56.168 WARN 13623 --- [http-nio-9208-exec-225] c.a.druid.pool.DruidAbstractDataSource : discard long time none received connection. , jdbcUrl
/(?P<level>[A-Z]{4,5})/ {
counts[$level] += 1
}
删除指标**(感觉没啥用,不清楚是不是用错了)**
PS:有用!!!会自动清理指标
/.*/ {
err_conut++
del err_conut after 1h # 按照官方文档的意思是一小时后清理指标,但是我这里不会清理,不清楚原因,可能是我一直有数据进入?
}
限制指标大小**(同样感觉完全没用)**
counter bytes_total by operation limit 500
# 按照官方文档,当大小限制超过其大小限制的变量时,它将删除最旧的值,直到整个指标再次低于其限制。最旧的值由基准的时间戳选择。
# 同样完全没用
可复用常量
与标准正则一样,小括号()内的内容可以使用$1,$2等方式获取到,mtail
脚本中此处MATCH_IP 中使用的?P<ip>则用来代替$1,
2
等,可以直接使用
2等,可以直接使用
2等,可以直接使用ip来获取匹配到的内容.
const IP /\d+(\.\d+){3}/
const MATCH_IP /(?P<ip>/ + IP + /)/
...
# Duplicate lease
/uid lease / + MATCH_IP + / for client .* is duplicate on / {
duplicate_lease++
}
内置参数 getfilename()
用于获取目录名称
# test.mtail
gauge conuts by files
/.*/ {
conuts[getfilename()]++
}
# 输出
# HELP conuts defined at tt.mtail:1:7-15
# TYPE conuts gauge
conuts{files="/usr/local/nginx/logs/111/test.log",prog="tt.mtail"} 6
其它内置函数感觉没啥用
6、使用范例
范例日志
2025-07-25 12:18:05.782 INFO 16656 --- [http-nio-9221-exec-1279] c.a.druid.pool.utils.http.HttpClientUtil : XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2025-07-25 00:00:00.032 WARN 16656 --- [http-nio-9221-exec-428] c.a.druid.pool.DruidAbstractDataSource : XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
2025-07-25 00:00:00.190 ERROR 16656 --- [http-nio-9221-exec-441] c.a.druid.pool.JdVopServiceAbstractImpl : 获取结果异常, ResultJson={XXXXXXXXXXXXXXXXXXXXXX}
mtail文件
/^/ +
/(?P<date>\d{4}-\d{2}-\d{2} )/ +
/(?P<time>\d{2}:\d{2}:\d{2}\.\d{3})( *)/ +
/(?P<level>[A-Z]{4,5}) / +
/(?P<pid>[0-9]{1,5}) / +
/(-*) / +
/(?P<xx>\[.*\]) / +
/(?P<exception>.*:) / +
/(?P<msg>\S+).*/ +
/$/
# 这一部分为将日志完全通过通配符拆分解析
counter err_conut by datetime, errStatus
/^/ +
/(?P<date>\d{4}-\d{2}-\d{2} )/ +
/(?P<time>\d{2}:\d{2}:\d{2}\.\d{3})( *)/ +
/(?P<level>[A-Z]{4,5}) / +
/(?P<pid>[0-9]{1,5}) / +
/(-*) / +
/(?P<xx>\[.*\]) / +
/(?P<exception>.*:) / +
/(?P<msg>\S+).*/ +
/$/ {
strptime($date, "2006-01-02 ")
err_conut[$date][$level]++
del err_conut[$date][$level] after 1h
}
执行命令
# -logs 指定日志文件
# -progs 指定mtail文件路径
# -one_shot 从文件开头读取
# -one_shot_format prometheus 指定输出格式
# -port 指定端口
./mtail -logs './123.log' -progs ./ -one_shot -one_shot_format prometheus -port 5566
输出结果
# HELP err_conut defined at items-test.mtail:1:9-17
# TYPE err_conut counter
err_conut{datetime="2025-07-25 ",errStatus="ERROR",prog="items-test.mtail"} 1
err_conut{datetime="2025-07-25 ",errStatus="INFO",prog="items-test.mtail"} 1
err_conut{datetime="2025-07-25 ",errStatus="WARN",prog="items-test.mtail"}
7、未解决问题
1、**【已解决】**通过getfilename()获取的目录没法进行分割
原本想法是通过getfilename()函数获取整体路径,例如:/usr/local/nginx/logs/111/test.log
,然后通过切割等方式分离出test.log
等作为prometheus
的tag
使用,但是完全不行。
解决方案:
通过修改源码后新增getsvcname(x)
函数,该函数通过对文件完成路径的分割来获取具体的服务名称,X为分割索引。
二次编译版本:https://download.youkuaiyun.com/download/weixin_45409343/91555774?spm=1001.2014.3001.5503
2、通过解析日志获取日期(不要精确到分秒的那种)
参考日志:
# 需要获取2025-07-25作为tag使用
2025-07-25 12:18:05.782 INFO 16656 --- [http-nio-9221-exec-1279] c.a.druid.pool.utils.http.HttpClientUtil
参考配置文件:
counter err_conut by datetime
/^(?P<date>\d{4}-\d{2}-\d{2}).*/ {
err_conut[$date]++
}
结局:
mtail
会自动将"2025-07-25"
这玩意儿识别成数字,然后转换失败。
I0725 14:48:48.126296 20475 vm.go:109] Set logging verbosity higher (-v1 or more) to see full VM state dump.
I0725 14:48:48.126315 20475 vm.go:107] tt.mtail: Runtime error: strconv.ParseInt: parsing "2025-07-25": invalid syntax
Error occurred at instruction 23 {s2i, <nil>}, originating in tt.mtail at line 19
Full input text from "/usr/local/nginx/logs/111/test.log" was "2025-07-25 12:18:05.937 INFO 16656 --- [http-nio-9221-exec-1279] c.l.t.api.jd.utils.http.HttpClientUtil"