記事ディレクトリ
1.概要
mtailは、アプリケーションログからメトリックを抽出して、アラートとダッシュボード表示のために時系列データベースまたは時系列計算機にエクスポートするためのツールです。簡単に言うと、アプリケーションのログをリアルタイムで読み取り、独自に作成したスクリプトを通じてリアルタイムで分析し、最終的に時系列インジケーターを生成するツールです。
公式ウェブサイトのアドレス:クリックしてアクセスする
ダウンロードアドレス:クリックして
CSDN にアクセスするダウンロードアドレス:クリックしてアクセスする
2.詳細なパラメータ
パラメータ | 説明文 |
---|---|
-住所 | HTTPリスナーにバインドされたホストまたはIPアドレス |
-alsologtostderr | 標準エラーとドキュメントを記録する |
-block_profile_rate | goroutineブロッキングイベントを報告するまでのナノ秒時間 |
-collectd_prefix | collectdに送信されるメトリックのメトリックプレフィックス |
-collectd_socketpath | メトリックを書き込むために使用されるcollectd unixsockパス |
-compile_only | mtailスクリプトプログラムのコンパイルのみを試み、実行せず、スクリプトのテストに使用 |
-disable_fsnotify | 動的ファイル検出メカニズムを無効にするかどうか。trueの場合、動的ロードによって検出された新しいファイルは監視されず、プログラムの起動時のファイルのみが監視されます。 |
-dump_ast | 解析後のダンププログラムのAST(デフォルトは/tmp/mtail.INFO) |
-dump_ast_types | 型チェックの後、型注釈を付けてプログラムのASTをダンプします(デフォルトは/tmp/mtail.INFOです) |
-dump_bytecode | ダンププログラムのバイトコード |
-emit_metric_timestamp | メトリックレコードのタイムスタンプを送信します。無効(デフォルト設定)の場合、明示的なタイムスタンプはコレクターに送信されません。 |
-emit_prog_label | エクスポートされた変数の「prog」に対応するラベルを表示します。デフォルトはtrueです |
-expired_metrics_gc_interval | メトリックガベージコレクタの実行間隔(デフォルトは1h0m0s) |
-graphite_host_port | グラファイトカーボンサーバーアドレス、フォーマットホスト:ポート。メトリックをグラファイトカーボンサーバーに書き込むために使用されます |
-graphite_prefix | グラファイトインジケーターに送信されるメトリックのプレフィックス |
-ignore_filename_regex_pattern | 無視するログファイル名は正規表現に対応しています。使用シナリオ:-logsパラメーターがディレクトリを指定する場合、ignore_filename_regex_patternパラメーターを使用して一部のファイルを無視できます |
-jaeger_endpoint | trueに設定すると、トレースをJaegerトレースコレクターにエクスポートできます。–jaeger_endpointフラグを使用して、JaegerエンドポイントURLを指定します |
-log_backtrace_at | ログレコードが設定された行Nに到達したら、スタックトレースを発行します。 |
-log_dir | mtailプログラムのログファイルディレクトリは、logtostderrに似ています。logtostderrパラメータも構成されている場合、log_dirパラメータは無効です。 |
-ログ | 監視対象のログファイルのリストを使用して、複数のファイルを分離したり、-logsパラメータを複数回使用したり、ファイルディレクトリを指定したりできます。ワイルドカード*がサポートされています。ファイルディレクトリを指定する場合、ディレクトリには一重引用符を使用する必要があります。例: -logs a.log、b.log、c.log -logs a.log -logs b.log -logs c.log -logs '/export/logs/*.log' |
-logtostderr | 標準エラーメッセージの直接出力とコンパイルの問題 |
-metric_push_interval_seconds | メトリックプッシュ間隔、単位:秒、デフォルトは60秒 |
-metric_push_write_deadline | エラーで終了する前に、成功したプッシュを待機する時間。(デフォルト10秒) |
-mtailDebug | パーサーのデバッグレベルを設定する |
-mutex_profile_fraction | 報告されたミューテックス競合イベントのスコア。0クローズ。(このパラメーターは文字どおりの翻訳です。意味がわかりません) |
-one_shot | このパラメーターは、mtailプログラムをコンパイルして実行し、指定したファイルの先頭からログを読み取り(リアルタイムの末尾ではなく、最初からログを読み取り)、収集したすべてのメトリックをログに出力します。このパラメーターは、mtailプログラムに期待される出力があり、実稼働環境では使用されないかどうかを確認するために使用されます。 |
-override_timezone | タイムゾーンを設定します。このパラメーターを使用すると、タイムスタンプ変換でUTCの代わりに指定したタイムゾーンが使用されます。 |
-poll_interval | データのすべてのログファイルをポーリングする間隔を設定します。ゼロを指定するとポーリングが無効になる場合は、正の値でなければなりません。ポーリングモードを使用すると、mtailの開始時に見つかったファイルのみがポーリングされます |
-港 | リスニングhttpポート、デフォルト3903 |
-progs | mtailスクリプトプログラムが配置されているパス |
-stale_log_gc_interval | staleのガベージコレクタの実行間隔(デフォルトは1h0m0s) |
-statsd_hostport | statsdアドレス、フォーマットホスト:ポート。メトリックをstatsdに書き込むために使用されます |
-statsd_prefix | statsdインジケーターに送信されるメトリックのプレフィックス |
-stderrthreshold | ログファイルの書き込みに加えて、重大度レベルがしきい値を超えるログ情報もstderrに出力する必要があります。各重大度に対応する値:INFO-0、WARNING-1、ERROR-2、FATAL-3、デフォルト値は2。 |
-syslog_use_current_year | タイムスタンプに年がない場合、現在の年に置き換えられます。(デフォルトはtrue) |
-trace_sample_period | トラッキングのサンプリング頻度とコレクターへの送信頻度を設定するために使用されます。100に設定し、100トレースを収集します。 |
-v | v日志的日志级别,该设置可能被 vmodule标志给覆盖.默认为0. |
-version | 打印mtail版本 |
-vmodule | 按文件或模块来设置日志级别,如:-vmodule=mapreduce=2,file=1,gfs*=3 |
3.安装启动
安装包为可执行二进制文件,官网目前(2020-04-19)最新版本为mtail_v3.0.0-rc35_linux_amd64,下载地址见本文概述。将其重命名为mtail,移动至/usr/local/sbin下即可,验证是否可用:
mtail -version
安装成功输出如下:
mtail version v3.0.0-rc34 git revision 7b4270cb6e8b6ed1f2febe48e370cb68d38681f9 go version go1.12.15 go arch amd64 go os linux
mtail后台启动:
nohup mtail -port 3903 -logtostderr -progs /root/chuangmi.mtail -logs /home/ubuntu/video_server_for_ai/media_server.log &
查看是否启动成功:
ps -ef | grep mtail
4.mtail脚本语法
4.1.mtail脚本标准格式
标准格式为:
COND {
ACTION
}
其中COND
是一个条件表达式。它可以是正则表达式,也可以boolean类型的条件语句。如下:
/foo/ {
ACTION1
}
variable > 0 {
ACTION2
}
/foo/ && variable > 0 {
ACTION3
}
COND
表达式可用的运算符如下:
- 关系运算符:
< , <= , > , >= , == , != , =~ , !~ , || , && , !
- 算术运算符:
| , & , ^ , + , - , * , /, << , >> , **
导出的指标变量可用的运算符如下:
= , += , ++ , –
mtail
的目的是从日志中提取信息并将其传递到监控系统。因此,必须导出指标变量并命名,命名可以使用counter、、gauge等指标类型,并且命名的变量必须在COND
脚本之前。
如,导出一个counter类型的指标lines_total:统计日志行数,脚本内容如下:
# simple line counter
counter lines_total
/$/ {
lines_total++
}
4.2.mtail支持的类型
mtail中的counter、gauge、histogram三种类型与prometheus类型中描述的作用一致。
4.2.1.counter
counter 类型的数据是单调递增的指标,即只增不减。如,你可以使用 counter 类型的指标来表示服务的请求数、成功任务数、失败的任务数等。
4.2.2.gauge
gauge类型的数据是指可以任意变化的指标,可增可减。如,可以提取正则匹配到的数据,直接赋值给指标变量返回,或者计算后返回。
4.2.3.histogram
histogram(直方图)将数据分段统计,引用prometheus中对histogram的描述:
在大多数情况下人们都倾向于使用某些量化指标的平均值,例如 CPU 的平均使用率、页面的平均响应时间。这种方式的问题很明显,以系统 API 调用的平均响应时间为例:如果大多数 API 请求都维持在 100ms 的响应时间范围内,而个别请求的响应时间需要 5s,那么就会导致某些 WEB 页面的响应时间落到中位数的情况,而这种现象被称为长尾问题。
为了区分是平均的慢还是长尾的慢,最简单的方式就是按照请求延迟的范围进行分组。例如,统计延迟在 0~10ms 之间的请求数有多少而 10~20ms 之间的请求数又有多少。通过这种方式可以快速分析系统慢的原因。Histogram 和 Summary 都是为了能够解决这样问题的存在,通过 Histogram 和 Summary 类型的监控指标,我们可以快速了解监控样本的分布情况。
Histogram 在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等),并将其计入可配置的存储桶(bucket)中,后续可通过指定区间筛选样本,也可以统计样本总数,最后一般将数据展示为直方图。
mtail
支持将直方图作为第一类度量标准,使用桶(bucket)范围列表创建histogram,如下:
histogram foo buckets 1, 2, 4, 8
以上脚本创建了一个新的直方图foo,其桶的范围为[0-1),[1-2),[2-4),[4-8),[8, +∞)。
注意:0-1和8-无穷大是自动创建的。
如下一个例子,展示使用Histogram 统计服务器延迟情况:
- 日志格式如下:
GET /foo/bar.html latency=1s httpcode=200
GET /foo/bar.html latency=2s httpcode=200
GET /foo/bar.html latency=1s httpcode=200
GET /foo/baz.html latency=0s httpcode=200
- mtail脚本如下:
histogram webserver_latency buckets 0, 1, 2, 4, 8
/latency=(?P<latency>\d+)/ {
webserver_latency = $latency
}
- 统计到的指标如下:
webserver_latency_by_code_bucket{httpcode="200",prog="software_errors.mtail",le="1"} 1
webserver_latency_by_code_bucket{httpcode="200",prog="software_errors.mtail",le="2"} 1
webserver_latency_by_code_bucket{httpcode="200",prog="software_errors.mtail",le="4"} 1
webserver_latency_by_code_bucket{httpcode="200",prog="software_errors.mtail",le="8"} 1
webserver_latency_by_code_bucket{httpcode="200",prog="software_errors.mtail",le="+Inf"} 1
webserver_latency_by_code_sum{httpcode="200",prog="software_errors.mtail"} 1
webserver_latency_by_code_count{httpcode="200",prog="software_errors.mtail"} 2
4.3.更改导出metrics的变量名称
像sql中给字段起别名一样,此处放在定义变量的地方,如下:
counter lines_total as "lines-total"
4.4.可复用常量
如匹配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++
}
与标准正则一样,小括号()内的内容可以使用$1,$2等方式获取到,mtail
脚本中此处MATCH_IP 中使用的?P<ip>则用来代替$1,$2等,可以直接使用$ip来获取匹配到的内容.
4.5.解析日志行时间戳
- 如果解析日志行中的时间戳,是为了导出变量使用,那么建议直接使用正则匹配到相应格式的时间戳,通过别名返回。
- 如果解析日志行中的时间戳是为了记录当前时间戳并且后续使用,那么就可以通过strptime(x,y)函数来解析日志中的时间戳,但是这个函数对日志时间戳格式有要求,可参考本文“内置函数”章节中的strptime()函数。
如,统计日志中时间格式包含“2006-01-02 15:04:05”格式类型的请求总数,脚本如下:
counter request_total
/(?P<date>\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*/ {
strptime($date, "2006-01-02 15:04:05")
request_total++
}
4.6.通用时间戳解析
可复用常量解决了表达式中重复使用子表达式的问题,而通用时间戳解析则是为了解决,多个变量之中重复解析设置时间戳的问题。
- 定义的格式如下:
def syslog {
/(?P<date>\w+\s+\d+\s+\d+:\d+:\d+)/ {
strptime($date, "Jan 2 15:04:05")
next
}
}
使用def
关键字定义名称,使用大括号块定义内容,使用next
关键字,跳转到导出变量的代码块执行。
- 使用的格式如下:
@syslog {
/some event/ {
variable++
}
}
@syslog表示该块首先由syslog装饰器执行,先提取日志的时间戳,然后使用next
跳转到
“/some event/”块内执行。
例:
def syslog {
/(?P<date>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}).*/ {
strptime($date, "2006-01-02 15:04:05")
next
}
}
gauge sumVal
@syslog {
/-------(?P<val>\d)+--------/ {
sumVal+=$val
}
}
4.7.条件判断
通常情况下,当条件表达式不匹配时,会直接跳过。而通过else
关键字可实现表达式不匹配时执行其他的动作。而通过otherwise
关键字则可以实现像java中的switch一样的多条件判断的功能,如下:
#如果foo不匹配,则执行ACTION2
/foo/ {
ACTION1
} else {
ACTION2
}
/foo/ {
#当匹配foo时,才会进行foo1、foo2、otherwise的比配
#当匹配foo1时,执行ACTION1,匹配foo2时执行ACTION2,否则执行ACTION3
/foo1/ {
ACTION1
}
/foo2/ {
ACTION2
}
otherwise {
ACTION3
}
}
4.8.临时变量
临时变量就是只在mtail脚本程序中使用,不导出为metrics指标的变量。通过在gauge
定义时前面加上hidden
关键字来定义。临时变量使用完后,需要使用del
关键字来删除临时变量控制内存。
hidden gauge connection_time by pid
gauge connection_time_total by pid
...
# 记录连接开始时间
/connect from \S+ \(\d+\.\d+\.\d+\.\d+\)/ {
# 此处记录开始时间,需要先使用strptime或者settime函数设置时间戳,timestamp才能正常执行
connection_time[$pid] = timestamp()
}
...
# 记录连接关闭时间
/sent (?P<sent>\d+) bytes received (?P<received>\d+) bytes total size \d+/ {
# 记录总时间
connection_time_total[$pid] += timestamp() - connection_time[$pid]
# 删除中间变量,控制内存
del connection_time[$pid]
}
此示例中,连接时间戳记录在临时变量connection_time
中,并且connection_time
通过pid来区分不同的链接.在链接结束时,通过当前时间戳-开始时间戳来计算增量,并且删除临时变量connection_time
。
4.9.内置函数
函数 | 描述 |
---|---|
timestamp() | 获取时间戳。 注:需要使用strptime或者settime函数设置时间戳之后才能使用timestamp函数 |
strptime($date, “2006-01-02 15:04:05”) | 第一个参数为日志中解析的时间格式,第二个参数为格式模板,此函数作用为使用第二个参数的格式来解析日志中的时间戳,并设置当前时间戳,将变量导出至上游收集器时使用此时间戳。 注:如果第二个参数格式不对,则编译抛出异常;如果日志解析出的时间格式不匹配,则抛出运行时异常。第二个参数必须使用这个特定的时间:2006-01-02 15:04:05。若需要其他格式,可参考Go的时间.parse()格式字符串中的const 部分下的ANSIC等格式。 |
len(str) | 获取字符串长度 |
getfilename() | 获取文件名 |
tolower(x) | 字符串转小写 |
int(x) | 将x转换为整数,如果x的类型支持转为整型,则转为整型;如果x的类型不支持转为整型,则触发编译错误;如果x的值不支持转为整型,则触发运行时错误。 |
float(x) | 将x转换为浮点数,规则同int(x) |
string(x) | 将x转为字符串 |
strtol(x, y) | 使用base将字符串x转为整数y。用于转换日志消息中的八进制、十六进制值 |
settime(x) | x为整型,用于设置当前时间戳,将变量导出至上游收集器时使用此时间戳 |
5.示例
5.1.mtail读取多个文件时,按照文件名输出metrics
此场景针对监听目录,或者多个文件的情况,需要使用到内置函数getfilename(),脚本如下:
counter request_total by filename
/-------(?P<val>\d)+--------/ {
request_total[getfilename()]+=$val
}
6.总结
目前网上关于mtail的文档,除了github官网之外,几乎没有其他的文档,而网上的中文文档几乎都是简单的介绍几句。而我最近刚好在搞mtail相关的,就写一些经验总结,文中例子有官网的demo,也有自己写的demo。如有错漏,望留言指正。