这篇主要是记录学习一个滴滴公司开发的日志监控组件用于监控系统的日志采集agent,可无缝对接open-falcon
1 安装
go get安装,肥肠简单
go get github.com/didi/falcon-log-agent
cd $GOPATH/src/github.com/didi/falcon-log-agent
make build
cp cfg/dev.cfg cfg/cfg.json
cp cfg/strategy.dev.json cfg/strategy.json
make pack
mkdir ~/open-falcon/falcon-log-agent
tar -xzvf falcon-log-agent.tar.gz -C ~/open-falcon/falcon-log-agent
2 测试
这个插件一共有两个配置文件,第一个是cfg.json,是插件的自身配置,第二个是strategy.json,配置你要监控的日志信息
cfg.json我基本都默认了,有一个log_level可以改成DEBUG,输出一些DEBUG信息方便调试
strategy.json默认
官方提供了一个api用来检测策略是否可以匹配日志的,命令如下
./control start #启动
curl -s -XPOST localhost:8003/check -d 'log=01/Jan/2018:12:12:12 service error 500, num=10 province=33' | python -m json.tool #测试这行日志是否能匹配当前策略
按照默认策略,这行日志应该是可以匹配到的,然而,我看到了如下的返回
我仔细观察了官方提供的默认策略
= =行吧,这里要求匹配的是空白符,给的例子是province=33,修改测试命令
curl -s -XPOST localhost:8003/check -d 'log=01/Jan/2018:12:12:12 service error 500, num=10 province= ' | python -m json.tool
成功了
3 监控
准备用于测试的文件是open-falcon的agent日志文件,如下
就采集那个每一行的Total好了
vim cfg/strategy.json
#创建一个新的日志监控如下
[
{
"id":1,
"name":"agent send num",
"file_path":"/home/tuan/open-falcon/agent/logs/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"",
"step":60,
"tags":{
"type":"log",
"file":"/home/tuan/open-falcon/agent/logs/app.log"
},
"func":"cnt",
"degree":6,
"comment":""
}
]
这个组件提供了http服务查看自身信息,默认端口是8003,定义在cfg/cfg.json里,可以按照需要修改,需要修改防火墙设置暴露端口
#开启一下防火墙的8003端口
sudo vi /etc/sysconfig/iptables
#在开放22端口的下一行添加如下规则
#-A INPUT -p tcp -m state --state NEW -m tcp --dport 8003 -j ACCEPT
sudo service iptables restart
打开http://IP:8003/health,就可以看见他的运行状态,界面大气简洁
api大概就是下面这几个:
- /health : 自身存活状态
- /strategy :当前生效的策略列表
- /cached : 最近1min内上报的点
运行,发现完蛋,啥都没有
尝试一下命令,返回为空
curl -s -XPOST localhost:8003/check -d 'log=2018/10/11 14:01:11 var.go:109: <= <Total=6, Invalid:0, Latency=0ms, Message:ok>' | python -m json.tool
实在无奈,在源代码里插了几个fmt,调的是http/check.go里的函数matchedStrategy(),代码里的fmt都是我写的
func matchedStrategy(content string, strategy *scheme.Strategy) (bool, map[string]string) {
fmt.Print("content is ");fmt.Println(content)
var detail = make(map[string]string, 0)
valid, patMap := getRegsFromOneStrategy(strategy)
if !valid {
return false, map[string]string{}
}
for key, pat := range patMap {
fmt.Print("key is ");fmt.Println(key)
fmt.Print("pat is ");fmt.Println(pat)
reg, err := regexp.Compile(pat)
fmt.Print("reg is ");fmt.Println(reg)
if err != nil {
return false, map[string]string{}
}
l := reg.FindStringSubmatch(content)
fmt.Println(l)
if len(l) == 0 {
if key != "exclude_" {
return false, map[string]string{}
}
detail[key] = ""
continue
}
detail[key] = l[0]
}
return true, detail
}
这个插件把标准输出定向到log/app.log这个文件了,打开一看,发现问题,他居然把我配置的tags里面的东西也当成了pattern,要求匹配
也就是说,strategy.json这个配置里的tags必须也是从日志文件中可以匹配到的一个正则表达式,不是直接配置的
再来看一下官方配置,tags里的provice也是从日志中匹配到的
不能写死
于是我去掉了tag,重新修改一下策略
vim cfg/strategy.json
#创建一个新的日志监控如下
[
{
"id":1,
"name":"agent send num",
"file_path":"/home/tuan/open-falcon/agent/logs/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"",
"step":60,
"tags":{
},
"func":"cnt",
"degree":6,
"comment":""
}
]
可以匹配到了
去open-falcon那里看一眼,Counter出来了!!
图像也有了,但是我配置的采集只是单纯计数,即每次有多少行日志符合我设置的pattern
做一点进阶的有意义的事情
agent的日志如下,每发送一堆监控数据就会打印两条日志,Total后面的数字是相等的,这个数字我估计就是每次发送的监控数据个数(不是也没有关系,假设他是就可以了)
现在我需要知道每60秒agent发送的监控数据个数,可以用日志监控插件提供的sum这个函数,还需要排除掉重复的一条日志(我打算把Invalid那一行排除掉,只保留Endpoint开头的)
好了,继续修改策略
vim cfg/strategy.json
#创建一个新的日志监控如下
[
{
"id":1,
"name":"agent send num",
"file_path":"/home/tuan/open-falcon/agent/logs/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"Invalid",
"step":60,
"tags":{
},
"func":"sum",
"degree":6,
"comment":""
}
]
数据出来了,不过日志滚的太多,不知道采集的数据对不对,为了学术,我进行了更严谨的测试
4 严谨的测试
用一个脚本生成一个模拟的日志,往模拟日志文件里插入给定的信息,看一下监控采集到的数据是否正确
生成模拟日志脚本如下,简单粗暴
#!/bin/bash
echo '2018/10/11 14:03:00 var.go:109: <= <Total=8, Invalid:0, Latency=0ms, Message:ok>' >> agent.log
echo '2018/10/11 14:03:11 gpu.go:31: Initialize error: could not load NVML library' >> agent.log
echo '2018/10/11 14:03:11 var.go:102: => <Total=120> <Endpoint:open-falcon-server, Metric:agent.alive, Type:GAUGE, Tags:, Step:60, Time:1539237791, Value:1>' >> agent.log
echo '2018/10/11 14:03:11 var.go:102: => <Total=7> <Endpoint:open-falcon-server, Metric:df.bytes.free.percent, Type:GAUGE, Tags:mount=/,fstype=ext4, Step:60, Time:1539237791, Value:32.156528701007986>' >> agent.log
echo '2018/10/11 14:03:11 var.go:109: <= <Total=120, Invalid:0, Latency=2ms, Message:ok>' >> agent.log
echo '2018/10/11 14:03:11 var.go:109: <= <Total=7, Invalid:0, Latency=0ms, Message:ok>' >> agent.log
echo '2018/10/11 14:03:11 var.go:102: => <Total=6> <Endpoint:open-falcon-server, Metric:ss.estab, Type:GAUGE, Tags:, Step:60, Time:1539237791, Value:48>' >> agent.log
echo '2018/10/11 14:03:11 var.go:109: <= <Total=6, Invalid:0, Latency=0ms, Message:ok>' >> agent.log
echo '2018/10/11 14:04:00 var.go:102: => <Total=8> <Endpoint:open-falcon-server, Metric:value, Type:GAUGE, Tags:name=pfc.push.size, Step:60, Time:1539237840, Value:8>' >> agent.log
sleep 70
echo '2018/10/11 14:01:11 var.go:102: => <Total=7> <Endpoint:open-falcon-server, Metric:df.bytes.free.percent, Type:GAUGE, Tags:mount=/,fstype=ext4, Step:60, Time:1539237671, Value:32.15721132115766>' >> agent.log
echo '2018/10/11 14:01:11 var.go:109: <= <Total=120, Invalid:0, Latency=0ms, Message:ok>' >> agent.log
echo '2018/10/11 14:01:11 var.go:109: <= <Total=7, Invalid:0, Latency=0ms, Message:ok>' >> agent.log
echo '2018/10/11 14:01:11 var.go:102: => <Total=6> <Endpoint:open-falcon-server, Metric:ss.estab, Type:GAUGE, Tags:, Step:60, Time:1539237671, Value:48>' >> agent.log
第一次采集到的数据总和应该是120+7+6+8=141,第二次采集到的数据总和应该是 7+6=13
把strategy.json里的路径改成我们的模拟日志,然后运行脚本生成模拟日志
睿智的人肯定不需要去等待open-falcon的图像,直接看插件的log/INFO日志
cat log/INFO.log | grep endpoint
看到如下的push信息,数值正确
现在来尝试一下所有的函数,目前log插件一共支持5个函数
- cnt:计数,匹配规则的日志条数
- avg:平均数,匹配规则的数据平均值
- sum:和,匹配规则的数据和
- max:最大值,匹配规则的最大数据
- min:最小值,匹配规则的最小数据
最终使用的strategy.json文件如下
[
{
"id":1,
"name":"agent total sum",
"file_path":"/home/tuan/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"Invalid",
"step":60,
"tags":{
},
"func":"sum",
"degree":6,
"comment":""
},
{
"id":2,
"name":"agent total min",
"file_path":"/home/tuan/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"Invalid",
"step":60,
"tags":{
},
"func":"min",
"degree":6,
"comment":""
},
{
"id":3,
"name":"agent total max",
"file_path":"/home/tuan/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"Invalid",
"step":60,
"tags":{
},
"func":"max",
"degree":6,
"comment":""
},
{
"id":4,
"name":"agent total cnt",
"file_path":"/home/tuan/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"Invalid",
"step":60,
"tags":{
},
"func":"cnt",
"degree":6,
"comment":""
},
{
"id":5,
"name":"agent total avg",
"file_path":"/home/tuan/agent.log",
"time_format":"yyyy/mm/dd HH:MM:SS",
"pattern":"Total=(\\d+)",
"exclude":"Invalid",
"step":60,
"tags":{
},
"func":"avg",
"degree":6,
"comment":""
}
]
看一下各项指标,都正确