alert-manager.js
2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* Created by zhangwenxue on 2019/07/23.
*/
'use strict';
const _ = require('lodash');
const ddAlert = require('./dingding-alert');
const MIN_SEND_INTERVAL = 10 * 1000;
const moment = require('moment');
const logger = global.yoho.logger;
/**
* AlertManager
* 统一调度dingtalk的告警
*
*/
const AlertManager = {
isAtAll: false,
pendingAgents: {},
/**
* post agent信息到当前pending队列
* @param {AlertAgent} agent
*/
post(agent) {
if (!this.pendingAgents[agent.name]) {
this.pendingAgents[agent.name] = agent;
}
this.report();
},
/**
* 向dingtalk robot发消息,使用_.throttle
*/
report: _.throttle(() => AlertManager._report(), MIN_SEND_INTERVAL, {leading: true, trailing: true}),
/**
* 发消息到dingtalk robot
*/
_report() {
const now = Date.now();
let ats = [];
let text = [];
text.push(`**本次告警**: ${moment(now).format('YYYY-MM-DD HH:mm:ss')}\n`);
text.push(`**上次告警**: ${moment(this.lastSendTime).format('YYYY-MM-DD HH:mm:ss')}\n`);
text = text.concat(Object.keys(this.pendingAgents).map(agentName => {
const agent = this.pendingAgents[agentName];
ats = ats.concat(agent.ats);
return agent.getMarkdownReport();
}));
// 发送
ddAlert(text.join('\n'), _.uniq(ats), this.isAtAll)
.catch(e => {
logger.warn('AlertManager send dingtalk alert:', e);
});
// 重置状态
this.lastSendTime = now;
this.pendingAgents = {};
}
};
/**
* AlertAgent
* 模块告警Agent
*/
class AlertAgent {
/**
*
* @param {string} name 模块名
* @param {Object} subjectMap 模块告警信息类型,subjectId=>subject
* @param {Array[string]} ats 需要@的手机号
* @param {boolean} isAtAll 是否@全体人员, default=false
*/
constructor(name, subjectMap, ats = [], isAtAll = false) {
this.name = name;
this.subjectMap = subjectMap;
this.ats = ats;
if (isAtAll) {
AlertManager.isAtAll = true;
}
this.msgs = {};
}
/**
* 发送告警信息
* @param {string|number} subjectId 消息类型
* @param {string|null} text 附加信息, 注: 发dingtalk时只发最后一条的text
*/
send(subjectId, text = '') {
let msg = _.get(this.msgs, subjectId, {text, count: 0});
this.msgs[subjectId] = msg;
msg.count++;
AlertManager.post(this);
}
/**
* 生成当前Agent的 markdown 格式报文
*/
getMarkdownReport() {
let report = [`## ${this.name} `];
report.push(this.ats.map(at => `@${at}`).join(' '));
const msgs = Object.keys(this.msgs).map(id => {
const msg = this.msgs[id];
return `- ${this.subjectMap[id]} ${msg.text} ${msg.count}次`;
});
report = report.concat(msgs);
return report.join('\n');
}
}
module.exports = AlertAgent;