【云原生•监控】mtail轻量日志监控体系
前言
「笔者已经在公有云上搭建了一套暂时环境,能够先登录体会下:」
http://124.222.45.207:17000/login
账号:root/root.2020
简介
「可观测性渠道三大支柱:日志监控、调用链监控和衡量目标监控,其间最为咱们熟知的是日志监控,因为咱们开发体系基本都离不开日志,也是处理问题最为常见的一种方法。日志的特色便是它是一个个离散的事情,因为一个事情的发生所以导致了一条日志的发生,用于问题剖析判断时供给更为翔实的头绪。」
举个比如:如程序忽然无法衔接MySQL数据库
,经过反常日志(如下)很简略发现是因为Too many connections
导致数据库衔接失败:
[ERROR][2023-05-2021:14:43]com.alibaba.druid.pool.DruidDataSource.init(629)|initdatasourceerror
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:Toomanyconnections
atsun.reflect.NativeConstructorAccessorImpl.newInstance0(NativeMethod)
atsun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
atjava.lang.reflect.Constructor.newInstance(Constructor.java:423)
atcom.mysql.jdbc.Util.handleNewInstance(Util.java:408)
atcom.mysql.jdbc.Util.getInstance(Util.java:383)
Too many connections
这种反常通常是因为超越MySQL
服务器允许的最大衔接数而引起的,能够经过增加数据库衔接数或封闭未运用的衔接来处理该问题。从这个示例能够看出:「日志监控对反常状况下问题剖析更加直接,比如恳求参数、反常事情等,为问题剖析判断供给更为翔实的头绪;调用链监控偏向恳求调用的链路剖析,往往用于发现链路间功能问题;而衡量目标监控特色是数值类型,往往用于核算聚合或供给功能目标的运转趋势状况,需求丰厚经验才能发现潜在问题,一般为问题剖析定位过程中可能的猜想供给有效的数据支撑依据,如上述Too many connections导致数据库衔接反常,就能够经过衡量目标查看MySQL的衔接数进行佐证,并经过衔接数趋势线查看什么时间点开端呈现衔接数反常上升进行进一步的剖析排查。」
「说到日志监控,咱们榜首反响的可能是ELK的计划,或许Loki的计划,这两个计划都是把日志采集了发到中心,在中心存储、查看、剖析。这种日志计划问题是运用elasticsearch,存储量十分大,巨大的全文索引开支,如一套ELK监控体系一天新增的日志存储量可能会上TB;另一个问题便是这些日志是离散的,而且是海量的,不太方便进行聚合核算。」
然后,在实际出产中往往还有如下需求:
-
如依据日志核算某个事务接口一天的调用量,然后获取事务订单量、付出金额等;
-
日志中触发Error的次数,以及想知道每天都触发了哪些Error,每种Error触发次数核算等;
-
依据日志关键字告警:
- 如上述
MySQL
衔接反常:Too many connections
- 如
jvm
内存溢出:java.lang.OutOfMemoryError: Java heap space
- 如衔接拒绝:
java.net.ConnectException: Connection refused
- 如上述
如上述需求并不需求全量的日志,所以,能够经过日志转衡量目标处理:「将日志流消息转换核算后生成衡量目标,然后监控体系抓取运用PromQL语法进行聚合核算剖析」。
这儿给咱们介绍一个Google
出品的东西mtail
,mtail
便是流式读取日志,经过正则表达式匹配的方法从日志中提取metrics
目标,这种方法能够利用目标机器的算力,别的一个好处是无侵入性,不需求事务埋点,如果事务程序是第三方供货商供给的,咱们改不了其代码,mtail
此时就十分合适了。
mtail装置运用
1、mtail装置:
[root@VM-4-14-centostools]#mkdir/disk/tools/mtail
[root@VM-4-14-centostools]#cd/disk/tools/mtail
[root@VM-4-14-centosmtail]#tar-zxvfmtail_3.0.0-rc51_Linux_x86_64.tar.gz
2、mtail发动:
[root@VM-4-14-centosmtail]#./mtail--progs/disk/tools/mtail/conf--logs'/disk/tools/mtail/logs/*.log'--logs/var/log/messages--log_dir/disk/tools/mtail/logdir--poll_interval250ms
❝
「中心参数如下:」
1、
--progs
:指定一个目录,这个目录里放置一堆的*.mtail
文件,每个mtail
文件便是描绘的正则提取规矩2、
--logs
: 监控的日志文件列表,能够运用,分隔多个文件,也能够多次运用--logs
参数,也能够指定一个文件目录,支撑通配符,指定文件目录时需求对目录运用单引号。如:--logs a.log,b.log,c.log
--logs a.log
--logs b.log
--logs c.log
--logs '/export/logs/*.log'
3、
--log_dir
:mtail
组件本身日志寄存目录4、
--port
:mtail
组件http
监听端口,默许3903❞
mtail
发动之后会主动监听一个端口3903,在3903的/metrics
接口露出契合Prometheus
协议的监控数据,Prometheus
或许 Categraf
或许 Telegraf
等就能够从 /metrics
接口提取监控数据。
这样看起来,原理就很明晰了,mtail
发动之后,依据 --logs
找到相关日志文件,seek
到文件结尾,开端流式读取,每读到一行,就依据 --progs
指定的那些规矩文件做匹配,看是否契合某些正则,从中提取时序数据,然后经过3903的/metrics
露出采集到的监控目标。
规矩语法
mtail
的目的是从日志中提取信息并将其传递到监控体系。因此,有必要导出目标变量并命名,目标支撑counter
、gauge
和histogram
三种类型,而且命名的变量有必要在COND
脚本之前。
标准格式为:
COND{
ACTION
}
其间COND
是一个条件表达式。它能够是正则表达式,也能够boolean
类型的条件句子。如下:
/foo/{
ACTION1
}
variable>0{
ACTION2
}
/foo/&&variable>0{
ACTION3
}
COND
表达式可用的运算符如下:
- 联系运算符:
❝
< , <= , > , >= , == , != , =~ , !~ , || , && , !
❞
- 算术运算符:
❝
| , & , ^ , + , – , * , /, << , >> , **
❞
**「导出的目标变量」**可用的运算符如下:
❝
= , += , ++ , –
❞
规矩示例
「1、导出一个counter类型的目标lines_total:核算日志行数」
#simplelinecounter
counterlines_total
/$/{
lines_total++
}
「2、导出一个counter类型的目标error_count:核算呈现ERROR、error、Failed、faild这四个关键字的日志行数」
countererror_count
/ERROR|error|Failed|faild/{
error_count++
}
「3、导出一个counter类型的目标out_of_memory_count:核算内存溢出呈现次数」
counterout_of_memory_count
/java.lang.OutOfMemoryError/{
out_of_memory_count++
}
转成衡量目标后,结合PromQL
语法很简略进行预警规矩配置:
groups:
-name:memory.rules
rules:
-alert:OutOfMemoryError
expr:increase(out_of_memory_count[1m])>0
labels:
severity:series
annotations:
summary:"java.lang.OutOfMemoryError"
description:"{{$labels.instance}}呈现JVM内存溢出过错"
「4、这儿我用mtail监控一下n9e-server的日志,从中提取一下各个告警规矩触发的 notify 的数量,这个日志举例:」
2021-12-2710:00:30.537582INFOengine/logger.go:19event(cbb8d4be5efd07983c296aaa4dec5737triggered)notify:rule_id=9[__name__=net_response_result_codeauthor=qinident=10-255-0-34port=4567protocol=tcpserver=localhost]2@1640570430
很明显,日志中有这么个关键字:notify: rule_id=9
,能够用正则来匹配,核算呈现的行数,ruleid 也能够从中提取到,这样,咱们能够把 ruleid 作为标签上报,于是乎,咱们就能够写出这样的 mtail 规矩了:
countermtail_alert_rule_notify_totalbyruleid
/notify:rule_id=(?P<ruleid>\d+)/{
mtail_alert_rule_notify_total[$ruleid]++
}
「5、java反常类型核算」
counterexception_countbyexception,log
/(?P<exception>[A-Z]*(.[A-Za-z]*)*(Exception|Error)):(?P<log>.*)/{
exception_count[$exception][$log]++
}
然后向日志文件中输入空指针反常和jvm内存溢出反常:
java.lang.NullPointerException:Someerrormessagehere.
atcom.example.myapp.MyClass.someMethod(MyClass.java:123)
atcom.example.myapp.OtherClass.doSomething(OtherClass.java:45)
java.lang.OutOfMemoryError:Javaheapspace
Dumpingheaptod://\java_pid10000.hprof...
Exceptioninthread"main"java.lang.OutOfMemoryError:Javaheapspace
atcn.intsmaze.dump.OOMDump$OOMIntsmaze.<init>(OOMDump.java:27)
atcn.intsmaze.dump.OOMDump.fillHeap(OOMDump.java:34)
atcn.intsmaze.dump.OOMDump.main(OOMDump.java:47)
atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)
atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
atjava.lang.reflect.Method.invoke(Method.java:498)
Heapdumpfilecreated[10195071bytesin0.017secs]
atcom.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
访问/metrics
端点就能够看到目标数据:
#HELPexception_countdefinedatgj.mtail:7:9-23
#TYPEexception_countcounter
exception_count{exception="java.lang.NullPointerException",log="Someerrormessagehere.",prog="gj.mtail"}3
exception_count{exception="java.lang.OutOfMemoryError",log="Javaheapspace",prog="gj.mtail"}2
❝
exception标签标识java反常类型,log标签标识简略反常描绘。
注意:实际出产log标签是不太合适的,因为log标签基数太多会导致目标膨胀。
❞
将反常目标转成衡量目标,运用PromQL
语法就很简略核算出每种反常类型每天触发的次数,或许结合Grafana
实时展示核算数据、趋势线等。