mtail语法详解
mtail是谷歌研发的一款,从应用程序的日志中提取指标到时序库的工具。由于最近要用到夜莺categraf采集器的mtail插件,碍于网络上mtail的资料比较少,所以专门记录一下mtail的语法。
1 处理流程
mtail会在日志尾每接收到一行日志时,执行脚本中的所有规则去匹配,大概的流程如下:
for line in lines:
for regex in regexes:
if match:
do something
2 基础语法
mtail的语法分为三个部分,分别是声明变量,匹配操作和定义装饰器。
exported variable
pattern {
action statements
}
def decorator {
pattern and action statements
}
3 变量
3.1 变量类型
mtail的变量分为三种类型,分别是 counter、gauge 和 histogram。
counter 类型是单调递增的指标,可以用来记录请求次数、任务的成功失败次数等。
gauge 类型的指标可以任意变化,可以用来提取正则匹配到的数据,并进行简单的计算。
下面的例子是 counter 和 gauge 变量的简单使用方法。
##统计日志中INFO日志的行数
counter lines
/INFO.*/ {
lines++
}
histogram 类型可以简单理解为直方图,可以将指标进行分段统计。其原理是将一段时间内的数据进行采样,并将其计入可配置的存储桶中,以便后续通过指定的区间对数据进行筛选。
histogram 变量的使用方法如下。
##声明一个responseTime变量,并定义桶,这个桶的意思是将数据分为[0-1),[1-2),[2-4),[4-8),[8, +∞)几个区间进行统计。
histogram response_time buckets 0, 1, 2, 4, 8
/time=(?P<time_in_log>\d+)ms/ {
response_time = $time_in_log
}
日志的格式是这样的
test,url=/base64/testApi,time=5ms
test,url=/base64/testApi,time=2ms
test,url=/base64/testApi,time=2ms
统计到的指标如下:
10:27:53 mtail_response_time_count agent_hostname=matoooo 0
10:27:53 mtail_response_time_sum agent_hostname=matoooo 0
10:27:53 mtail_response_time_bucket agent_hostname=matoooo le=+Inf 0
10:27:53 mtail_response_time_bucket agent_hostname=matoooo le=1 0
10:27:53 mtail_response_time_bucket agent_hostname=matoooo le=2 0
10:27:53 mtail_response_time_bucket agent_hostname=matoooo le=4 2
10:27:53 mtail_response_time_bucket agent_hostname=matoooo le=8 1
10:27:53 mtail_response_time_bucket agent_hostname=matoooo le=+Inf 0
3.2 更改变量名称
更改变量名称同sql,使用as关键字即可。
counter lines as total_line
3.3 常量
mtail中的常量使用const关键字声明。
const IP /\d+(\.\d+){3}/
3.4 临时变量
临时变量是指只需要在处理过程中使用的内部变量,不会被导出到外部,使用hidden关键字来声明。
hidden counter record_time
临时变量使用完之后需要使用del关键字来进行删除。
gauge duration by session
hidden session_start by session
/end/ {
duration[$session] = timestamp() - session_start[$session]
del session_start[$session]
}
3.5 分组
mtail中的分组与sql类似,使用by关键字。
counter lines by bucket
比如上文的 response_time ,我们还可以根据url来进行分组计数。
counter count_by_url by url_in_log
/url=(?P<url_in_log>\/\w+)/ {
count_by_url[$url_in_log]++
}
4 运算
上文在讲述变量的同时,已经写了一部分mtail运算的例子了,其实mtail的运算语法基本如下。
COND {
ACTION
}
其中COND是条件表达式,可以是正则、关系表达式。ACTION表示具体要进行的操作。
4.1 运算符
mtail支持的关系运算符为:
<
小于<=
小于或等于>
大于>=
大于或等于==
相等!=
不相等=~
模式匹配!~
否定模式匹配||
logical 或&&
逻辑和!
一元逻辑否定
mtail支持的算术运算符为:|
按位或&
按位和^
按位异或+
加法-
减法*
乘法/
除法<<
按位左移>>
按位右移**
指数=
赋值++
递增+=
增加--
递减
4.2 流程控制
4.2.1 if…else…
mtail中的条件判断例子如下:
/foo/ {
ACTION1
} else {
ACTION2
}
4.2.2 switch…case…
switch语句在mtail中这样写,otherwise相当于default。
/foo/ {
/foo1/ {
ACTION1
}
/foo2/ {
ACTION2
}
otherwise {
ACTION3
}
}
4.3 内置函数
mtail中包含的内置函数如下:
len(x)
获取字符串的长度tolower(x)
将字符串转为全小写subst(old, new, val)
替换函数,将val中的old子串替换为new,old可以写正则int(x)
将数字字符串转为整数float(x)
将数字字符串转为浮点数string(x)
将值转为字符串strtol(x, y)
使用base将字符串x转为整数y。用于转换日志消息中的八进制、十六进制值getfilename()
获取当前日志的文件名settime(x)
x为整型,用于设置当前时间戳strptime(x, y)
解析时间字符串中的时间戳,x为日志中的时间格式,y为格式模板,例如y可以随便写成"2023-11-24 12:00:00"timestamp()
获取当前时间戳,必须使用settime(x)
或strptime(x, y)
设置过时间戳之后才能使用
4.4 修饰器
mtail不支持自定义函数,但是提供了修饰器功能,可以在一定程度上代替自定义函数,修饰器使用def关键字声明。
比如解析时间的操作,大部分日志都是以时间开头,因此我们可以用修饰器将解析时间的方法提取出来。
def syslog {
/(?P<date>\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*/ {
strptime($date, "2023-11-24 12:00:00")
next
}
}
代码中的next关键字是必须的,用来跳转到调用该修饰器的代码块中继续执行。
调用修饰器的代码如下:
counter lines
@syslog {
/INFO.*/ {
lines++
}
}
当然其实上述写法写可以写成嵌套的操作:
counter lines
/(?P<date>\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*/ {
strptime($date, "2023-11-24 12:00:00")
/INFO.*/ {
lines++
}
/ERROR.*/ {
lines--
}
}
4.5 停止
停止的关键字是stop,例如当我们想要同时监控一个文件夹下的多个日志文件,但是跳过其中某些文件时,可以这样写:
getfilename() !~ /apache.access.log/ {
stop
}