统计线上Nginx日志,将超时响应和>=500状态的请求抓取并整理,发送到指定邮箱
需求
对线上的Nginx入口的日志进行统计与报警,
以下是json格式的数据,数据已经存储elasticsearch中,并且通过kibana进行管理
报警
1. 采用sentinl插件,进行数据处理
2. 安装sentinl插件,建议先下载,然后离线安装,在线安装容易断网。速度特别慢
1${KIBANA_HOME}/kibana-plugin install file:/tmp/sentinl-version.zip
3. 配置kibana的启动sentinl的邮件功能
1# /etc/kibana/kibana.yml 在最后追加以下内容
2sentinl:
3 settings:
4 email:
5 active: true
6 user: no-reply@xx.com
7 password: xxxx
8 host: mail.xxxx.com
9 ssl: true
10 report:
11 active: true
12 tmp_path: /tmp/
重启kibana重新加载配置并生效
4. 登录kibana管理UI,点击Sentinl菜单创建Watchers
直接编辑raw配置文件,如果没有先保存一个,然后直接编辑raw
1#Watchers raw
2{
3 "_index": "watcher",
4 "_type": "sentinl-watcher",
5 "_id": "x8vo6ooqek8-94ql4qei88q-yx9dnrq7uth",
6 "_version": 127,
7 "found": true,
8 "_source": {
9 "title": "reponse_code(api.xx.com)",
10 "disable": false,
11 "report": false,
12 "trigger": {
13 "schedule": {
14 "later": "every 30 minutes"
15 }
16 },
17 "input": {
18 "search": {
19 "request": {
20 "index": [],
21 "body": {
22 "size": 128,
23 "query": {
24 "bool": {
25 "must": [
26 {
27 "range": {
28 "nginx.access.response_code": {
29 "gte": 500
30 }
31 }
32 },
33 {
34 "match": {
35 "nginx.access.host": "api.xx.com"
36 }
37 },
38 {
39 "range": {
40 "@timestamp": {
41 "from": "now-1h"
42 }
43 }
44 }
45 ]
46 }
47 }
48 }
49 }
50 }
51 },
52 "condition": {
53 "script": {
54 "script": "payload.hits.total > 100"
55 }
56 },
57 "actions": {
58 "api.xx.com": {
59 "throttle_period": "0h1m0s",
60 "email_html": {
61 "to": "xx@xx.com",
62 "from": "xx-xx@xx.com",
63 "subject": "Sentinl Alarm (api.xx.com 1h)",
64 "priority": "high",
65 "html": "统计响应状态码:500-505<br/> 一共 {{ payload.hits.total }} <br/> 只获取最近的128(当前{{payload.hits.hits.length}})记录,进行展示。<br/> 具体请求url如下<br/> <pre>{{payload.text}}</pre><br/>",
66 "save_payload": false
67 }
68 }
69 },
70 "transform": {
71 "script": {
72 "script": "payload.statistics = {}; payload.hits.hits.forEach( function(hit){ var url = hit._source.nginx.access.host + hit._source.nginx.access.url; if (url in payload.statistics){ payload.statistics[url] = payload.statistics[url] + 1; }else{ payload.statistics[url] = 1; } }); function jsonToText(jsonval){ var html = 'request url \\t times -> statistics times\\n'; for (var key in jsonval){ html += key +' \\t times -> '+ jsonval[key] +'\\n'; } return html; }; payload.text=jsonToText(payload.statistics);"
73 }
74 }
75 }
76}
transform script
1// 注意 字符串使用 单引号'进行包装,如果换行使用\\n 制表格\\t
2payload.statistics = {};
3payload.hits.hits.forEach(
4 function(hit){
5 var url = hit._source.nginx.access.host + hit._source.nginx.access.url;
6 if (url in payload.statistics){
7 payload.statistics[url] = payload.statistics[url] + 1;
8 } else{
9 payload.statistics[url] = 1;
10 }
11});
12function jsonToText(jsonval){
13 var html = 'request url \\t times -> statistics times\\n';
14 for (var key in jsonval){
15 html += key +' \\t times -> '+ jsonval[key] +'\\n';
16 }
17 return html;
18}
19payload.text= jsonToText(payload.statistics);
5. 脚本执行流程
- input中根据query向elasticsearch查询
- 根据condition判断结果是否满足
- 如果满足进行transform数据处理
- 根据处理后的数据进行actions操作
6. 注意事项
- transform 阶段script外面是双引号包裹,内部如果使用双引号需要增加反斜杠,内部脚本如果换行需要使用
\\n
- transform和condition阶段的script脚本需要是一行,所以编写js脚本需要用分号
;
分割防止一行出现错误编译 - actions中发送有邮件有两种
email
和email_html
,email
发送的内容在body中,次数数据都会被编码。email_html
发送的内容在html中,此时body失效,只支持html解析,但是在{{}}中的数据不会解析html
- query阶段,elasticsearch默认是size是10,所以根据每次查询结果进行评估选择合适的常量
附录
- 个人Github 个人编写的一些dockerfile,支持armhf、arrch64、x86_64平台
- Sentinal GitHub
注意: 采用elasticsearch对应的版本
- 文档
评论