Nginx请求日志输出到ELK,同时通过Elastalert监控ELK日志中的关键信息(如http状态500+错误,耗时较长的请求数达到阈值等等),这几乎是中小型互联网公司的标配。
Elastalert自带的报警方式虽然多种多样,但是不能实现根据报警信息分组发送,如研发人员也很关心这些指标,需要接受本项目的报警,运维需要接受所有项目的报警,报警方式要支持电话语音、短信、邮件、钉钉群。要实现这些,只能自己撸脚本了。
yunwei:
member:
zhangshan:
phone: 15895820001
mail: [email protected]
lisi:
phone: 15895820002
mail: [email protected]
dingtoken:
e802cb4b5791bb08e1bc79cfd62c0a6bae4b77e8758b4b52522d5119478f1234
project1:
member:
zhouwu:
phone: 15895820003
mail: [email protected]
wangliu:
phone: 15895820004
mail: [email protected]
dingtoken:
0a30c27cbb9bb17e5dbcb721578b7a6a490810c2fc237e1af5a1289557d31234
project2:
member:
liudehua:
phone: 15895820005
mail: [email protected]
说明:
以监控500状态为例说明配置
es_host: 10.10.10.1
es_port: 9200
name: freq-status-500
type: frequency
index: nginx-*
num_events: 30
timeframe:
minutes: 1
filter:
- bool:
must:
- terms:
status: ["500","501","502","503","504"]
use_terms_query: true
doc_type: doc
terms_size: 10
query_key:
- domain
- status
realert:
minutes: 60
alert:
- command
new_style_string_format: true
command: ["/root/elastalert-0.1.38/myalert/elastalert-alarm/alarm.py","--level=warning","--domain={domain,status}","--rulename=freq-status-500","--type=frequency","--num_events=30","--timeframe=1min"]
说明:
parser.add_argument('--level',dest='level',help='warning, distater')
parser.add_argument('--domain',dest='domain',help='for instance: sina_www, if rule_name start with freq-500,then sina_www-500')
parser.add_argument('--rulename', dest='rulename', help='rulename')
parser.add_argument('--type', dest='type', help='frequence, flatline')
parser.add_argument('--num_events', dest='num_events', help='num_events')
parser.add_argument('--timeframe', dest='timeframe', help='timeframe')
parser.add_argument('--reqtime_gt', dest='reqtime_gt', help='request time greater than')
多query_key是非常实用的,如上文中,我要监控每个域名每种HTTP 500状态的请求数,一个rule就能实现了。可惜作者没支持好,需要稍微改造下。
配置举例(use_terms_query必须配置):
use_terms_query: true
query_key:
- domain
- status
修改elastalert.py中的方法get_terms_query:
修改前:
else:
aggs_query = query
aggs_query['aggs'] = {'counts': {'terms': {'field': field, 'size': size}}}
return aggs_query
修改后(暂且只支持2个字段):
else:
aggs_query = query
field_list = field.split(",")
if len(field_list) == 1:
aggs_query['aggs'] = {'counts': {'terms': {'field': field, 'size': size}}}
elif len(field_list) == 2:
source= "doc['" + field_list[0] + "'].value + '-' + doc['" + field_list[1] + "'].value"
aggs_query['aggs'] = {'counts': {'terms': {'script': {'source': source}, 'size': size}}}
else:
elastalert_logger.inof("Not support more than 2 fields in query_key")
return aggs_query
alert中获取具体domain和status方式如下:
command: ["/tmp/alert_log.sh", "warning - freq 500 exceed, domain: {domain,status}"]
文件说明:
alarm.py --程序入口,参数解析
alert_channel.py --报警发送通道(短信、语音、邮件、钉钉群)
alert.py --构造发送对象和消息内容
aliyunsdk_SingleCallByTtsRequest.py --阿里电话语音第三方库
config-contact.yaml --报警对象配置文件
config.py --加载配置文件
requirements.txt --依赖
util.py --工具方法
代码地址:https://github.com/meishd/elastalert-alarm
如域名www.sina.com的502请求数每分钟超过30个,则报警内容如下:
注:我们ELK中将domain改成“ 一级域名_二级域名 ”的格式入库
warning: sina_www status of 502 exceed 30 per 1min