Showing
8 changed files
with
304 additions
and
35 deletions
@@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
8 | }, | 8 | }, |
9 | "scripts": { | 9 | "scripts": { |
10 | "test": "echo \"Error: no test specified\" && exit 1", | 10 | "test": "echo \"Error: no test specified\" && exit 1", |
11 | - "dev": "nodemon --ignore ./examples src/server.js", | 11 | + "dev": "nodemon --ignore ./dist src/server.js", |
12 | "fix": "eslint --fix ./src" | 12 | "fix": "eslint --fix ./src" |
13 | }, | 13 | }, |
14 | "author": "", | 14 | "author": "", |
@@ -19,7 +19,7 @@ | @@ -19,7 +19,7 @@ | ||
19 | "debug": "^3.1.0", | 19 | "debug": "^3.1.0", |
20 | "express": "^4.15.4", | 20 | "express": "^4.15.4", |
21 | "http-proxy-middleware": "^0.19.0", | 21 | "http-proxy-middleware": "^0.19.0", |
22 | - "influx-batch-sender": "^0.1.5", | 22 | + "influx-batch-sender": "=0.1.10", |
23 | "ip2region": "=1.1.0", | 23 | "ip2region": "=1.1.0", |
24 | "knex": "^0.14.1", | 24 | "knex": "^0.14.1", |
25 | "koa-compose": "^4.1.0", | 25 | "koa-compose": "^4.1.0", |
@@ -16,10 +16,10 @@ module.exports = (app) => { | @@ -16,10 +16,10 @@ module.exports = (app) => { | ||
16 | // new yas | 16 | // new yas |
17 | app.get('/apm/yas2.gif', middleware.getip, middleware.clientApm); | 17 | app.get('/apm/yas2.gif', middleware.getip, middleware.clientApm); |
18 | 18 | ||
19 | - // 服务器端收集,最新的 | 19 | + // 老接口服务器端收集,老的格式 influx格式 |
20 | app.post('/write', middleware.serverApm); | 20 | app.post('/write', middleware.serverApm); |
21 | - | ||
22 | - // 监控 | ||
23 | app.post('/alert', middleware.alertApm); | 21 | app.post('/alert', middleware.alertApm); |
22 | + | ||
23 | + // 最新只有一个接口,所有的数据都过来, json 格式 | ||
24 | app.post('/collect', middleware.serverApm2); | 24 | app.post('/collect', middleware.serverApm2); |
25 | }; | 25 | }; |
src/middleware/msg2row2.js
0 → 100644
1 | +const _ = require('lodash'); | ||
2 | + | ||
3 | +function slowRouter(m) { | ||
4 | + let uid = _.get(m, 'uid', '0'); | ||
5 | + | ||
6 | + return { | ||
7 | + app: _.get(m.data, 'app', ''), | ||
8 | + type: _.get(m.data, 'type', ''), | ||
9 | + hostname: _.get(m.data, 'hostname', ''), | ||
10 | + preqid: _.get(m.data, 'preqid', ''), | ||
11 | + reqid: _.get(m.data, 'reqID', ''), | ||
12 | + uid: _.parseInt(uid), | ||
13 | + udid: _.get(m.data, 'udid', ''), | ||
14 | + api: _.get(m.data, 'api', ''), | ||
15 | + route: _.get(m.data, 'route', ''), | ||
16 | + duration: _.get(m.data, 'duration', ''), | ||
17 | + create_time: _.get(m.data, 'time', 0) | ||
18 | + }; | ||
19 | +} | ||
20 | + | ||
21 | +function errorRouter(m) { | ||
22 | + let uid = _.get(m.data, 'uid', '0'); | ||
23 | + let line = _.get(m.data, 'line', '0'); | ||
24 | + let column = _.get(m.data, 'column', '0'); | ||
25 | + | ||
26 | + return { | ||
27 | + app: _.get(m.data, 'app', ''), | ||
28 | + api: _.get(m.data, 'api', ''), | ||
29 | + type: _.get(m.data, 'type', ''), | ||
30 | + hostname: _.get(m.data, 'hostname', ''), | ||
31 | + preqid: _.get(m.data, 'preqid', ''), | ||
32 | + reqid: _.get(m.data, 'reqID', ''), | ||
33 | + uid: _.parseInt(uid), | ||
34 | + udid: _.get(m.data, 'udid', ''), | ||
35 | + route: _.get(m.data, 'path', ''), | ||
36 | + url: _.get(m.data, 'url', ''), | ||
37 | + ip: _.get(m.data, 'ip', ''), | ||
38 | + code: _.parseInt(_.get(m.data, 'code', -1)), | ||
39 | + line: _.parseInt(line), | ||
40 | + column: _.parseInt(column), | ||
41 | + script: _.get(m.data, 'script', ''), | ||
42 | + message: _.get(m.data, 'message', ''), | ||
43 | + stack: _.get(m.data, 'stack', ''), | ||
44 | + useragent: _.get(m.data, 'useragent', ''), | ||
45 | + create_time: _.get(m.data, 'time', 0) | ||
46 | + }; | ||
47 | +} | ||
48 | + | ||
49 | +module.exports = { | ||
50 | + slowRouter, | ||
51 | + errorRouter | ||
52 | +}; |
src/middleware/risk-service/index2.js
0 → 100644
1 | +const compose = require('koa-compose'); | ||
2 | +const _ = require('lodash'); | ||
3 | + | ||
4 | +const enable = require('./enable'); | ||
5 | +const qpsPath = require('./qps-path'); | ||
6 | + | ||
7 | +const disableBelow = require('./disable'); | ||
8 | +const ipFilter = require('./ip'); | ||
9 | +const userFilter = require('./user'); | ||
10 | +const userAgentFilter = require('./useragent'); | ||
11 | +const xhrFilter = require('./xhr'); | ||
12 | +const zk = require('./zk'); | ||
13 | +const whitelistIpFilter = require('./whitelist-ip'); | ||
14 | +const whitelistPathFilter = require('./whitelist-path'); | ||
15 | +const qps = require('./qps'); | ||
16 | + | ||
17 | +const logger = global.yoho.logger; | ||
18 | + | ||
19 | +const APP_NAME = { | ||
20 | + 'yohobuy-node': 'pc', | ||
21 | + 'yohobuywap-node': 'wap', | ||
22 | + UNKNOWN: '' | ||
23 | +}; | ||
24 | + | ||
25 | +const APP_TYPE = { | ||
26 | + 'yohobuy-node': 'web', | ||
27 | + 'yohobuywap-node': 'h5', | ||
28 | + UNKNOWN: '' | ||
29 | +}; | ||
30 | + | ||
31 | +module.exports = () => { | ||
32 | + const handlers = compose([ | ||
33 | + enable, | ||
34 | + qpsPath, | ||
35 | + | ||
36 | + disableBelow, | ||
37 | + userFilter, | ||
38 | + xhrFilter, | ||
39 | + whitelistIpFilter, | ||
40 | + whitelistPathFilter, | ||
41 | + ipFilter, | ||
42 | + userAgentFilter, | ||
43 | + qps | ||
44 | + ]); | ||
45 | + | ||
46 | + return async(playload, next) => { | ||
47 | + if (playload.type !== 'web-server-duration' && playload.data.type !== 'route') { | ||
48 | + return next(); | ||
49 | + } | ||
50 | + | ||
51 | + logger.debug('[request] %j', playload); | ||
52 | + | ||
53 | + const user = { | ||
54 | + uid: _.parseInt(_.get(playload, 'data.uid', '0'), 10), | ||
55 | + ip: _.get(playload, 'data.ip', ''), | ||
56 | + app: APP_NAME[_.get(playload, 'data.app', 'UNKNOWN')], | ||
57 | + appName: _.get(playload, 'data.app', ''), | ||
58 | + appType: APP_TYPE[_.get(playload, 'data.app', 'UNKNOWN')], | ||
59 | + path: decodeURIComponent(_.get(playload, 'data.path', '')), | ||
60 | + userAgent: decodeURIComponent(_.get(playload, 'data.userAgent', '')), | ||
61 | + ajax: _.parseInt(_.get(playload, 'data.ajax', 0)) | ||
62 | + }; | ||
63 | + | ||
64 | + if (!user.ip || !user.app) { | ||
65 | + if (_.get(zk, `${user.app}.open.logNoIp`, false)) { | ||
66 | + logger.error('miss ip or app %j but get %j', playload, user); | ||
67 | + } | ||
68 | + return; | ||
69 | + } | ||
70 | + | ||
71 | + await handlers({user}); | ||
72 | + | ||
73 | + next(); | ||
74 | + }; | ||
75 | +}; |
src/middleware/serverapm-service2.js
0 → 100644
1 | +const Sender = require('influx-batch-sender'); | ||
2 | +const MysqlSender = require('../lib/mysql-sender'); | ||
3 | +const config = require('../common/config'); | ||
4 | +const msg2row = require('./msg2row2'); | ||
5 | + | ||
6 | + | ||
7 | +const logger = global.yoho.logger; | ||
8 | +const errorSqlSender = new MysqlSender(config.table.error); | ||
9 | +const slowRouterSqlSender = new MysqlSender(config.table.slow); | ||
10 | + | ||
11 | +const routeInfluxSender = new Sender(config.reportRoute); | ||
12 | +const apiInfluxSender = new Sender(config.reportApi); | ||
13 | +const alertInfluxSender = new Sender(config.reportAlert); | ||
14 | + | ||
15 | +const _ = require('lodash'); | ||
16 | + | ||
17 | +const API_BLACK_LIST = [ | ||
18 | + 'app.shop.banner' | ||
19 | +]; | ||
20 | + | ||
21 | +async function handleWebServerDuration(playload, next) { | ||
22 | + if (playload.type !== 'web-server-duration') { | ||
23 | + return next(); | ||
24 | + } | ||
25 | + | ||
26 | + let duration = _.parseInt(playload.data.duration); | ||
27 | + | ||
28 | + if (duration > config.slowRoute.min / 10 && duration < config.slowRoute.max) { | ||
29 | + const newData = _.merge({}, playload, { | ||
30 | + fields: { | ||
31 | + duration | ||
32 | + } | ||
33 | + }); | ||
34 | + | ||
35 | + slowRouterSqlSender.addMessage(msg2row.slowRouter(newData)); | ||
36 | + } | ||
37 | + | ||
38 | + if (playload.data.type.toLowerCase() === 'api') { | ||
39 | + if (_.includes(API_BLACK_LIST, playload.tags.api)) { | ||
40 | + return; | ||
41 | + } | ||
42 | + | ||
43 | + logger.debug('[api] route info [%s]', JSON.stringify(playload)); | ||
44 | + | ||
45 | + apiInfluxSender.addMessage({ | ||
46 | + tags: { | ||
47 | + app: playload.data.app, | ||
48 | + host: playload.data.hostname, | ||
49 | + api: playload.data.api | ||
50 | + }, | ||
51 | + fields: { | ||
52 | + duration: duration, | ||
53 | + times: 1 | ||
54 | + } | ||
55 | + }); | ||
56 | + } | ||
57 | + | ||
58 | + if (playload.data.type.toLowerCase() === 'route') { | ||
59 | + logger.debug('[server] route info [%s]', JSON.stringify(playload)); | ||
60 | + | ||
61 | + routeInfluxSender.addMessage({ | ||
62 | + tags: { | ||
63 | + app: playload.data.app, | ||
64 | + host: playload.data.hostname, | ||
65 | + route: playload.data.route | ||
66 | + }, | ||
67 | + fields: { | ||
68 | + duration: duration | ||
69 | + } | ||
70 | + }); | ||
71 | + } | ||
72 | + | ||
73 | + next(); | ||
74 | +} | ||
75 | + | ||
76 | +function handleErrorReport(playload, next) { | ||
77 | + if (playload.type !== 'error-report') { | ||
78 | + return next(); | ||
79 | + } | ||
80 | + | ||
81 | + routeInfluxSender.addMessage({ | ||
82 | + measurement: 'error-info', | ||
83 | + tags: { | ||
84 | + app: playload.data.app, | ||
85 | + host: playload.data.hostname, | ||
86 | + route: playload.data.route, | ||
87 | + code: playload.data.code | ||
88 | + }, | ||
89 | + fields: { | ||
90 | + times: 1 | ||
91 | + } | ||
92 | + }); | ||
93 | + | ||
94 | + // 排除情况 | ||
95 | + const msg = _.get(playload, 'data.message', ''); | ||
96 | + | ||
97 | + if (!msg) { | ||
98 | + return; | ||
99 | + } | ||
100 | + | ||
101 | + if (msg === '""') { | ||
102 | + return; | ||
103 | + } | ||
104 | + | ||
105 | + const type = _.get(playload, 'data.type', ''); | ||
106 | + | ||
107 | + if (type === 'api') { | ||
108 | + logger.debug('[api] error info [%s]', JSON.stringify(playload)); | ||
109 | + } else { | ||
110 | + logger.debug('[server] error info [%s]', JSON.stringify(playload)); | ||
111 | + } | ||
112 | + | ||
113 | + errorSqlSender.addMessage(msg2row.errorRouter(playload)); | ||
114 | + | ||
115 | + next(); | ||
116 | +} | ||
117 | + | ||
118 | +function handleProcessInfo(playload, next) { | ||
119 | + if (playload.type !== 'process-info') { | ||
120 | + return next(); | ||
121 | + } | ||
122 | + | ||
123 | + logger.debug('[process] info [%s]', JSON.stringify(playload)); | ||
124 | + | ||
125 | + playload.measurement = 'process-info'; | ||
126 | + | ||
127 | + routeInfluxSender.addMessage({ | ||
128 | + measurement: 'process-info', | ||
129 | + tags: playload.tags, | ||
130 | + fields: playload.fields | ||
131 | + }); | ||
132 | + | ||
133 | + next(); | ||
134 | +} | ||
135 | + | ||
136 | +function handleAlertInfo(playload, next) { | ||
137 | + if (playload.type !== 'monitor_success_report') { | ||
138 | + return next(); | ||
139 | + } | ||
140 | + | ||
141 | + alertInfluxSender.addMessage({ | ||
142 | + measurement: playload.type, | ||
143 | + tags: playload.tags, | ||
144 | + fields: playload.fields | ||
145 | + }); | ||
146 | + | ||
147 | + next(); | ||
148 | +} | ||
149 | + | ||
150 | +module.exports = { | ||
151 | + handleErrorReport, | ||
152 | + handleProcessInfo, | ||
153 | + handleWebServerDuration, | ||
154 | + handleAlertInfo | ||
155 | +}; |
1 | -const lineparse = require('../lib/line-parse'); | ||
2 | const bb = require('bluebird'); | 1 | const bb = require('bluebird'); |
2 | +const compose = require('koa-compose'); | ||
3 | 3 | ||
4 | const logger = global.yoho.logger; | 4 | const logger = global.yoho.logger; |
5 | 5 | ||
6 | const { | 6 | const { |
7 | handleErrorReport, | 7 | handleErrorReport, |
8 | handleProcessInfo, | 8 | handleProcessInfo, |
9 | - handleWebServerDuration | ||
10 | -} = require('./serverapm-service'); | 9 | + handleWebServerDuration, |
10 | + handleAlertInfo | ||
11 | +} = require('./serverapm-service2'); | ||
11 | 12 | ||
12 | -const riskService = require('./risk-service'); | 13 | +const riskService = require('./risk-service/index2'); |
13 | const handleRisk = riskService(); | 14 | const handleRisk = riskService(); |
14 | 15 | ||
16 | +const handlers = compose([ | ||
17 | + handleWebServerDuration, | ||
18 | + handleRisk, | ||
19 | + handleErrorReport, | ||
20 | + handleProcessInfo, | ||
21 | + handleAlertInfo | ||
22 | +]); | ||
23 | + | ||
15 | const server = { | 24 | const server = { |
16 | async handle(msgs) { | 25 | async handle(msgs) { |
17 | try { | 26 | try { |
18 | await bb.map(msgs, async(m) => { | 27 | await bb.map(msgs, async(m) => { |
19 | - if (!m.measurement) { | 28 | + if (!m.type) { |
20 | return; | 29 | return; |
21 | } | 30 | } |
22 | 31 | ||
23 | - switch (m.measurement) { | ||
24 | - case 'web-server-duration': { | ||
25 | - handleWebServerDuration(m); | ||
26 | - | ||
27 | - if (m.tags.type === 'route') { | ||
28 | - await handleRisk(m); | ||
29 | - } | ||
30 | - break; | ||
31 | - } | ||
32 | - case 'error-report': { | ||
33 | - handleErrorReport(m); | ||
34 | - break; | ||
35 | - } | ||
36 | - case 'process-info': { | ||
37 | - handleProcessInfo(m); | ||
38 | - break; | ||
39 | - } | ||
40 | - default: { | ||
41 | - logger.error('[server] handle ERROR [%s]', JSON.stringify(m)); | ||
42 | - break; | ||
43 | - } | ||
44 | - } | 32 | + await handlers(m); |
45 | 33 | ||
46 | }, {concurrency: 2}); | 34 | }, {concurrency: 2}); |
47 | 35 | ||
@@ -53,7 +41,7 @@ const server = { | @@ -53,7 +41,7 @@ const server = { | ||
53 | }; | 41 | }; |
54 | 42 | ||
55 | module.exports = function(req, res) { | 43 | module.exports = function(req, res) { |
56 | - let data = req.body || ' '; | 44 | + let data = req.body || {}; |
57 | 45 | ||
58 | server.handle(data).catch(err => { | 46 | server.handle(data).catch(err => { |
59 | logger.error(err); | 47 | logger.error(err); |
yarn.lock
deleted
100644 → 0
This diff could not be displayed because it is too large.
-
Please register or login to post a comment