@hyperwatch/hyperwatch 3.8.1 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/default.js +69 -42
- package/config/example.js +131 -105
- package/docs/configuration.md +1 -1
- package/docs/tutorials/apache_input.md +30 -20
- package/docs/tutorials/express_input.md +26 -16
- package/package.json +23 -22
- package/src/format/apache.js +1 -1
- package/src/format/nginx.js +1 -1
- package/src/index.js +5 -4
- package/src/lib/formatter.js +3 -0
- package/src/lib/pipeline.js +4 -1
- package/src/modules/address.js +4 -4
- package/src/modules/agent.js +2 -2
- package/src/modules/cloudflare.js +2 -2
- package/src/modules/dnsbl.js +2 -2
- package/src/modules/geoip.js +4 -4
- package/src/modules/hostname.js +2 -2
- package/src/modules/identity.js +18 -5
- package/src/modules/index.js +8 -8
- package/src/modules/language.js +2 -2
- package/src/modules/logs.js +2 -2
- package/src/modules/signature.js +4 -4
- package/src/modules/sparkline.js +2 -2
- package/src/modules/status.js +2 -2
- package/start.js +8 -2
package/config/default.js
CHANGED
|
@@ -1,61 +1,88 @@
|
|
|
1
|
-
const
|
|
1
|
+
const defaultConfig = function (hyperwatch) {
|
|
2
|
+
const { pipeline, input, format, logger } = hyperwatch;
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/* Init Hyperwatch (will load modules) */
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
====================== */
|
|
6
|
+
hyperwatch.init();
|
|
7
7
|
|
|
8
|
-
/*
|
|
9
|
-
|
|
8
|
+
/* Input configuration */
|
|
9
|
+
/* =================== */
|
|
10
10
|
|
|
11
|
-
/* Syslog
|
|
11
|
+
/* Syslog inputs */
|
|
12
|
+
/* ------------- */
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
name: 'Syslog (nginx combined format)',
|
|
15
|
-
port: 1514,
|
|
16
|
-
parse: format.nginx.parser({ format: format.nginx.formats.combined }),
|
|
17
|
-
});
|
|
14
|
+
/* Syslog input in Nginx 'combined' format */
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
const syslogNginxCombinedInput = input.syslog.create({
|
|
17
|
+
name: 'Syslog (nginx combined format)',
|
|
18
|
+
port: 1514,
|
|
19
|
+
parse: format.nginx.parser({ format: format.nginx.formats.combined }),
|
|
20
|
+
});
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
pipeline.registerInput(syslogNginxCombinedInput);
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
name: 'Syslog (nginx access_watch format)',
|
|
25
|
-
port: 1515,
|
|
26
|
-
parse: format.nginx.parser({ format: format.nginx.formats.accessWatch }),
|
|
27
|
-
});
|
|
24
|
+
/* Syslog input in Nginx 'hyperwatch_combined' format */
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
const syslogNginxHyperwatchCombinedInput = input.syslog.create({
|
|
27
|
+
name: 'Syslog (nginx hyperwatch_combined format)',
|
|
28
|
+
port: 1515,
|
|
29
|
+
parse: format.nginx.parser({
|
|
30
|
+
format: format.nginx.formats.hyperwatchCombined,
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
pipeline.registerInput(syslogNginxHyperwatchCombinedInput);
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
name: 'Syslog (JSON standard format)',
|
|
35
|
-
port: 1516,
|
|
36
|
-
});
|
|
36
|
+
/* Syslog input in Hyperwatch JSON format */
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
const syslogInput = input.syslog.create({
|
|
39
|
+
name: 'Syslog (JSON standard format)',
|
|
40
|
+
port: 1516,
|
|
41
|
+
});
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
-------------- */
|
|
43
|
+
pipeline.registerInput(syslogInput);
|
|
42
44
|
|
|
43
|
-
/* HTTP
|
|
45
|
+
/* HTTP inputs */
|
|
46
|
+
/* ----------- */
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
name: 'HTTP server (JSON standard format)',
|
|
47
|
-
path: '/input/log',
|
|
48
|
-
});
|
|
48
|
+
/* HTTP input in Hyperwatch JSON format */
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
const httpInput = input.http.create({
|
|
51
|
+
name: 'HTTP server (JSON standard format)',
|
|
52
|
+
path: '/input/log',
|
|
53
|
+
});
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
name: 'WebSocket server (JSON standard format)',
|
|
54
|
-
type: 'server',
|
|
55
|
-
path: '/input/log',
|
|
56
|
-
});
|
|
55
|
+
pipeline.registerInput(httpInput);
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
const webSocketServerInput = input.websocket.create({
|
|
58
|
+
name: 'WebSocket server (JSON standard format)',
|
|
59
|
+
type: 'server',
|
|
60
|
+
path: '/input/log',
|
|
61
|
+
});
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
pipeline.registerInput(webSocketServerInput);
|
|
64
|
+
|
|
65
|
+
/* Pipeline configuration */
|
|
66
|
+
/* ====================== */
|
|
67
|
+
|
|
68
|
+
pipeline
|
|
69
|
+
.getNode('main')
|
|
70
|
+
.map((log) => console.log(logger.defaultFormatter.format(log, 'console')));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (require.main === module) {
|
|
74
|
+
let hyperwatch;
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
hyperwatch = require('../hyperwatch');
|
|
78
|
+
} catch (e) {
|
|
79
|
+
// eslint-disable-next-line node/no-missing-require
|
|
80
|
+
hyperwatch = require('@hyperwatch/hyperwatch');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
defaultConfig(hyperwatch);
|
|
84
|
+
|
|
85
|
+
hyperwatch.start();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = defaultConfig;
|
package/config/example.js
CHANGED
|
@@ -1,151 +1,177 @@
|
|
|
1
|
-
const
|
|
1
|
+
const exampleConfig = function (hyperwatch) {
|
|
2
|
+
const { pipeline, input, format, logger } = hyperwatch;
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/* Init Hyperwatch (will load modules) */
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
====================== */
|
|
6
|
+
hyperwatch.init();
|
|
7
7
|
|
|
8
|
-
/*
|
|
9
|
-
|
|
8
|
+
/* Input configuration */
|
|
9
|
+
/* =================== */
|
|
10
10
|
|
|
11
|
-
/* Syslog
|
|
11
|
+
/* Syslog inputs */
|
|
12
|
+
/* ------------- */
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
name: 'Syslog (nginx combined format)',
|
|
15
|
-
port: 1514,
|
|
16
|
-
parse: format.nginx.parser({ format: format.nginx.formats.combined }),
|
|
17
|
-
});
|
|
14
|
+
/* Syslog input in Nginx 'combined' format */
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
const syslogNginxCombinedInput = input.syslog.create({
|
|
17
|
+
name: 'Syslog (nginx combined format)',
|
|
18
|
+
port: 1514,
|
|
19
|
+
parse: format.nginx.parser({ format: format.nginx.formats.combined }),
|
|
20
|
+
});
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
pipeline.registerInput(syslogNginxCombinedInput);
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
name: 'Syslog (nginx access_watch format)',
|
|
25
|
-
port: 1515,
|
|
26
|
-
parse: format.nginx.parser({ format: format.nginx.formats.accessWatch }),
|
|
27
|
-
});
|
|
24
|
+
/* Syslog input in Nginx 'hyperwatch_combined' format */
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
const syslogNginxHyperwatchCombinedInput = input.syslog.create({
|
|
27
|
+
name: 'Syslog (nginx hyperwatch_combined format)',
|
|
28
|
+
port: 1515,
|
|
29
|
+
parse: format.nginx.parser({
|
|
30
|
+
format: format.nginx.formats.hyperwatchCombined,
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
pipeline.registerInput(syslogNginxHyperwatchCombinedInput);
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
name: 'Syslog (JSON standard format)',
|
|
35
|
-
port: 1516,
|
|
36
|
-
});
|
|
36
|
+
/* Syslog input in Hyperwatch JSON format */
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
const syslogInput = input.syslog.create({
|
|
39
|
+
name: 'Syslog (JSON standard format)',
|
|
40
|
+
port: 1516,
|
|
41
|
+
});
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
pipeline.registerInput(syslogInput);
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
// port: 1517,
|
|
44
|
-
// parse: format.apache.parser({
|
|
45
|
-
// format: format.apache.formats.combined
|
|
46
|
-
// })
|
|
47
|
-
// })
|
|
45
|
+
/* Syslog input in Apache 'combined' format */
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
const syslogApacheCombinedInput = input.syslog.create({
|
|
48
|
+
name: 'Syslog (apache combined format)',
|
|
49
|
+
port: 1517,
|
|
50
|
+
parse: format.apache.parser({
|
|
51
|
+
format: format.apache.formats.combined,
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
50
54
|
|
|
51
|
-
|
|
55
|
+
pipeline.registerInput(syslogApacheCombinedInput);
|
|
52
56
|
|
|
53
|
-
|
|
54
|
-
// port: 1518,
|
|
55
|
-
// parse: format.apache.parser({
|
|
56
|
-
// format: format.apache.formats.accessWatchCombined
|
|
57
|
-
// })
|
|
58
|
-
// })
|
|
57
|
+
/* Syslog input in Apache 'hyperwatch_combined' format */
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
const syslogApacheHyperwatchCombinedInput = input.syslog.create({
|
|
60
|
+
name: 'Syslog (apache hyperwatch_combined format)',
|
|
61
|
+
port: 1518,
|
|
62
|
+
parse: format.apache.parser({
|
|
63
|
+
format: format.apache.formats.hyperwatchCombined,
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
-------------- */
|
|
67
|
+
pipeline.registerInput(syslogApacheHyperwatchCombinedInput);
|
|
64
68
|
|
|
65
|
-
/* HTTP
|
|
69
|
+
/* HTTP inputs */
|
|
70
|
+
/* ----------- */
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
name: 'HTTP server (JSON standard format)',
|
|
69
|
-
path: '/input/log',
|
|
70
|
-
});
|
|
72
|
+
/* HTTP input in Hyperwatch JSON format */
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
const httpInput = input.http.create({
|
|
75
|
+
name: 'HTTP server (JSON standard format)',
|
|
76
|
+
path: '/input/log',
|
|
77
|
+
});
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
------------------- */
|
|
79
|
+
pipeline.registerInput(httpInput);
|
|
76
80
|
|
|
77
|
-
/* WebSocket
|
|
81
|
+
/* WebSocket inputs */
|
|
82
|
+
/* ---------------- */
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
// name: 'WebSocket server (JSON standard format)',
|
|
81
|
-
// type: 'server',
|
|
82
|
-
// path: '/input/log'
|
|
83
|
-
// })
|
|
84
|
+
/* WebSocket server input in Hyperwatch JSON format (listening for logs) */
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
const webSocketServerInput = input.websocket.create({
|
|
87
|
+
name: 'WebSocket server (JSON standard format)',
|
|
88
|
+
type: 'server',
|
|
89
|
+
path: '/input/log',
|
|
90
|
+
});
|
|
86
91
|
|
|
87
|
-
|
|
92
|
+
pipeline.registerInput(webSocketServerInput);
|
|
88
93
|
|
|
89
|
-
|
|
90
|
-
// address: 'ws://HOST:PORT/logs'
|
|
91
|
-
// })
|
|
94
|
+
/* WebSocket client input in Hyperwatch JSON format (subscribing to logs) */
|
|
92
95
|
|
|
93
|
-
//
|
|
96
|
+
// const websocketClientInput = input.websocket.create({
|
|
97
|
+
// name: 'WebSocket client (JSON standard format)',
|
|
98
|
+
// address: 'ws://HOST:PORT/logs',
|
|
99
|
+
// });
|
|
94
100
|
|
|
95
|
-
|
|
96
|
-
-------------- */
|
|
101
|
+
// pipeline.registerInput(websocketClientInput);
|
|
97
102
|
|
|
98
|
-
/* File
|
|
103
|
+
/* File inputs */
|
|
104
|
+
/* ----------- */
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
// path: '/var/log/nginx/access.log',
|
|
102
|
-
// parse: format.nginx.parser({
|
|
103
|
-
// format: format.nginx.formats.combined
|
|
104
|
-
// })
|
|
105
|
-
// })
|
|
106
|
+
/* File input in Nginx 'combined' format */
|
|
106
107
|
|
|
107
|
-
//
|
|
108
|
+
// const fileNginxCombinedInput = input.file.create({
|
|
109
|
+
// name: 'File input (nginx combined format)',
|
|
110
|
+
// path: '/var/log/nginx/access.log',
|
|
111
|
+
// parse: format.nginx.parser({
|
|
112
|
+
// format: format.nginx.formats.combined,
|
|
113
|
+
// }),
|
|
114
|
+
// });
|
|
108
115
|
|
|
109
|
-
|
|
116
|
+
// pipeline.registerInput(fileNginxCombinedInput);
|
|
110
117
|
|
|
111
|
-
|
|
112
|
-
// path: '/var/log/nginx/access_watch.log',
|
|
113
|
-
// parse: format.nginx.parser({
|
|
114
|
-
// format: format.nginx.formats.accessWatch
|
|
115
|
-
// })
|
|
116
|
-
// })
|
|
118
|
+
/* File input in Nginx 'hyperwatch' format */
|
|
117
119
|
|
|
118
|
-
//
|
|
120
|
+
// const fileNginxHyperwatchCombinedInput = input.file.create({
|
|
121
|
+
// name: 'File input (nginx hyperwatch_combined format)',
|
|
122
|
+
// path: '/var/log/nginx/hyperwatch.log',
|
|
123
|
+
// parse: format.nginx.parser({
|
|
124
|
+
// format: format.nginx.formats.hyperwatchCombined,
|
|
125
|
+
// }),
|
|
126
|
+
// });
|
|
119
127
|
|
|
120
|
-
|
|
121
|
-
Pipeline configuration
|
|
122
|
-
======================
|
|
123
|
-
*/
|
|
128
|
+
// pipeline.registerInput(fileNginxHyperwatchCombinedInput);
|
|
124
129
|
|
|
125
|
-
|
|
130
|
+
/* File input in Apache 'combined' format */
|
|
126
131
|
|
|
127
|
-
const
|
|
132
|
+
// const fileApacheCombinedInput = input.file.create({
|
|
133
|
+
// name: 'File input (nginx combined format)',
|
|
134
|
+
// path: '/var/log/apache2/access.log',
|
|
135
|
+
// parse: format.nginx.parser({
|
|
136
|
+
// format: format.nginx.formats.combined,
|
|
137
|
+
// }),
|
|
138
|
+
// });
|
|
128
139
|
|
|
129
|
-
|
|
140
|
+
// pipeline.registerInput(fileApacheCombinedInput);
|
|
130
141
|
|
|
131
|
-
|
|
142
|
+
/* File input in Apache 'hyperwatch' format */
|
|
132
143
|
|
|
133
|
-
|
|
144
|
+
// const fileApacheHyperwatchCombinedInput = input.file.create({
|
|
145
|
+
// name: 'File input (nginx hyperwatch_combined format)',
|
|
146
|
+
// path: '/var/log/apache2/hyperwatch.log',
|
|
147
|
+
// parse: format.nginx.parser({
|
|
148
|
+
// format: format.apache.formats.hyperwatchCombined,
|
|
149
|
+
// }),
|
|
150
|
+
// });
|
|
134
151
|
|
|
135
|
-
.
|
|
136
|
-
log.set(
|
|
137
|
-
'address',
|
|
138
|
-
proxy.detectAddress(
|
|
139
|
-
log.getIn(['request', 'address']),
|
|
140
|
-
log.getIn(['request', 'headers'])
|
|
141
|
-
)
|
|
142
|
-
)
|
|
143
|
-
)
|
|
152
|
+
// pipeline.registerInput(fileApacheHyperwatchCombinedInput);
|
|
144
153
|
|
|
145
|
-
/*
|
|
154
|
+
/* Pipeline configuration */
|
|
155
|
+
/* ====================== */
|
|
146
156
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
stream,
|
|
157
|
+
pipeline
|
|
158
|
+
.getNode('main')
|
|
159
|
+
.map((log) => console.log(logger.defaultFormatter.format(log, 'console')));
|
|
151
160
|
};
|
|
161
|
+
|
|
162
|
+
if (require.main === module) {
|
|
163
|
+
let hyperwatch;
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
hyperwatch = require('../hyperwatch');
|
|
167
|
+
} catch (e) {
|
|
168
|
+
// eslint-disable-next-line node/no-missing-require
|
|
169
|
+
hyperwatch = require('@hyperwatch/hyperwatch');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
exampleConfig(hyperwatch);
|
|
173
|
+
|
|
174
|
+
hyperwatch.start();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
module.exports = exampleConfig;
|
package/docs/configuration.md
CHANGED
|
@@ -14,7 +14,7 @@ Here is an example of how this file can look like :
|
|
|
14
14
|
}
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
This example would make the app be served on the 4000 port
|
|
17
|
+
This example would make the app be served on the 4000 port.
|
|
18
18
|
|
|
19
19
|
You can find below the list of all configurable constants:
|
|
20
20
|
|
|
@@ -16,7 +16,15 @@ As a prerequirement, you'll need Node.js >= 7. Use nvm if you're in trouble.
|
|
|
16
16
|
nvm install node
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
#### Install from npm
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @hyperwatch/hyperwatch
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
#### Install from Git
|
|
26
|
+
|
|
27
|
+
Alternatively, for developemnt purpose, you can use Git and clone the public repository:
|
|
20
28
|
|
|
21
29
|
```bash
|
|
22
30
|
git clone https://github.com/hyperwatch/hyperwatch.git
|
|
@@ -30,31 +38,33 @@ In our suggested configuration, Hyperwatch will be listening for access logs in
|
|
|
30
38
|
|
|
31
39
|
We always recommand using the `access_watch_combined` format, which is logging more detailed information and allows for a much better analysis than the regular `combined` format.
|
|
32
40
|
|
|
33
|
-
To get more familiar, you can inspect default and example configurations in
|
|
41
|
+
To get more familiar, you can inspect default and example configurations in [`config/default.js`](<(../../config/default.js)>) and [`config/example.js`](../../config/example.js) file.
|
|
34
42
|
|
|
35
|
-
Now, you can create your own configuration in
|
|
43
|
+
Now, you can create your own configuration in `apache_syslog_example.js`:
|
|
36
44
|
|
|
37
45
|
```javascript
|
|
38
|
-
|
|
46
|
+
module.exports = function (hyperwatch) {
|
|
47
|
+
const { pipeline, input, format } = hyperwatch;
|
|
39
48
|
|
|
40
|
-
|
|
49
|
+
hyperwatch.init();
|
|
41
50
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
});
|
|
51
|
+
const syslogApacheHyperwatchCombinedInput = input.syslog.create({
|
|
52
|
+
port: 1518,
|
|
53
|
+
parse: format.apache.parser({
|
|
54
|
+
format: format.apache.formats.hyperwatchCombined,
|
|
55
|
+
}),
|
|
56
|
+
});
|
|
48
57
|
|
|
49
|
-
pipeline.registerInput(
|
|
58
|
+
pipeline.registerInput(syslogApacheHyperwatchCombinedInput);
|
|
59
|
+
};
|
|
50
60
|
```
|
|
51
61
|
|
|
52
62
|
### Configure Apache
|
|
53
63
|
|
|
54
|
-
First, if you're following our recommendation and opted for the `
|
|
64
|
+
First, if you're following our recommendation and opted for the `hyperwatch_combined` format, you need to define it in the Apache configuration. This will not replace the standard log format, just create an additional one.
|
|
55
65
|
|
|
56
66
|
```
|
|
57
|
-
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" \"%{Accept}i\" \"%{Accept-Charset}i\" \"%{Accept-Encoding}i\" \"%{Accept-Language}i\" \"%{Connection}i\" \"%{Dnt}i\" \"%{From}i\" \"%{Host}i\""
|
|
67
|
+
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" \"%{Accept}i\" \"%{Accept-Charset}i\" \"%{Accept-Encoding}i\" \"%{Accept-Language}i\" \"%{Connection}i\" \"%{Dnt}i\" \"%{From}i\" \"%{Host}i\"" hyperwatch_combined
|
|
58
68
|
```
|
|
59
69
|
|
|
60
70
|
Note that you're free to use whatever `LogFormat`, you just need to properly report it in the Hyperwatch configuration.
|
|
@@ -62,18 +72,18 @@ Note that you're free to use whatever `LogFormat`, you just need to properly rep
|
|
|
62
72
|
Second, you need to instruct Apache where to send the access logs. If it's not the same, you need to make sure that Apache can reach the server where Hyperwatch is running.
|
|
63
73
|
|
|
64
74
|
```
|
|
65
|
-
CustomLog "|/usr/bin/logger -n localhost -P 1518 --rfc3164"
|
|
75
|
+
CustomLog "|/usr/bin/logger -n localhost -P 1518 --rfc3164" hyperwatch_combined
|
|
66
76
|
```
|
|
67
77
|
|
|
68
|
-
Note: This is known to be working on _Ubuntu 16.04_ with _logger 2.27.1_, let us know if you're in trouble and using something else.
|
|
78
|
+
Note: This is known to be working on _Ubuntu 16.04, 18.04_ with _logger 2.27.1, 2.31.1_, let us know if you're in trouble and using something else.
|
|
69
79
|
|
|
70
80
|
In this example, there are 3 important things:
|
|
71
81
|
|
|
72
82
|
1. If Hyperwatch is running on the same server, we can use `localhost` as IP address.
|
|
73
83
|
If it's on a different server, replace `localhost` by the proper private or public IP address.
|
|
74
|
-
2. We configured Hyperwatch to listen for syslog messages in the `
|
|
84
|
+
2. We configured Hyperwatch to listen for syslog messages in the `hyperwatch_combined` format on port `1518`.
|
|
75
85
|
We're properly passing that port in the configuration
|
|
76
|
-
3. Finally, we're asking Apache to use the `
|
|
86
|
+
3. Finally, we're asking Apache to use the `hyperwatch_combined` log format we previously configured.
|
|
77
87
|
|
|
78
88
|
Don't forget to reload Aapche with the updated configuration. On Ubuntu, it would be:
|
|
79
89
|
|
|
@@ -83,10 +93,10 @@ service apache2 reload
|
|
|
83
93
|
|
|
84
94
|
### Start Hyperwatch
|
|
85
95
|
|
|
86
|
-
Ok, now go back to where
|
|
96
|
+
Ok, now go back to where you wrote the config.
|
|
87
97
|
|
|
88
98
|
```bash
|
|
89
|
-
|
|
99
|
+
hyperwatch apache_syslog_example.js
|
|
90
100
|
```
|
|
91
101
|
|
|
92
102
|
### Browse the interface
|
|
@@ -16,7 +16,15 @@ As a prerequirement, you'll need Node.js >= 7. Use nvm if you're in trouble.
|
|
|
16
16
|
nvm install node
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
#### Install from npm
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g @hyperwatch/hyperwatch
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
#### Install from Git
|
|
26
|
+
|
|
27
|
+
Alternatively, for developement purpose, you can use Git and clone the public repository:
|
|
20
28
|
|
|
21
29
|
```bash
|
|
22
30
|
git clone https://github.com/hyperwatch/hyperwatch.git
|
|
@@ -28,22 +36,24 @@ npm install
|
|
|
28
36
|
|
|
29
37
|
In our suggested configuration, Hyperwatch will be listening for access logs using the Websocket protocol.
|
|
30
38
|
|
|
31
|
-
All communications between your Node/Express application and Hyperwatch will be happening in clear,
|
|
39
|
+
All communications between your Node/Express application and Hyperwatch will be happening in clear, please only use that setup on your internal network. If on the public internet, we're advising to use the Websocket Secure protocol (wss) which is straightforward but out of the scope of this tutorial.
|
|
32
40
|
|
|
33
|
-
Now, you can create your own configuration in
|
|
41
|
+
Now, you can create your own configuration in `express_websocket_example.js`:
|
|
34
42
|
|
|
35
43
|
```javascript
|
|
36
|
-
|
|
44
|
+
module.exports = function (hyperwatch) {
|
|
45
|
+
const { pipeline, input } = hyperwatch;
|
|
37
46
|
|
|
38
|
-
|
|
47
|
+
hyperwatch.init();
|
|
39
48
|
|
|
40
|
-
const webSocketServerInput = input.websocket.create({
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
49
|
+
const webSocketServerInput = input.websocket.create({
|
|
50
|
+
name: 'WebSocket server (JSON standard format)',
|
|
51
|
+
type: 'server',
|
|
52
|
+
path: '/input/log',
|
|
53
|
+
});
|
|
45
54
|
|
|
46
|
-
pipeline.registerInput(webSocketServerInput);
|
|
55
|
+
pipeline.registerInput(webSocketServerInput);
|
|
56
|
+
};
|
|
47
57
|
```
|
|
48
58
|
|
|
49
59
|
### Configure Node/Express
|
|
@@ -51,18 +61,18 @@ pipeline.registerInput(webSocketServerInput);
|
|
|
51
61
|
Now, install the Hyperwatch Express Logger middleware in your Node application:
|
|
52
62
|
|
|
53
63
|
```bash
|
|
54
|
-
npm install --save
|
|
64
|
+
npm install --save @hyperwatch/express-logger
|
|
55
65
|
```
|
|
56
66
|
|
|
57
67
|
Then simply configure it like any other middlewares:
|
|
58
68
|
|
|
59
69
|
```javascript
|
|
60
70
|
const express = require('express');
|
|
61
|
-
const
|
|
71
|
+
const hyperwatchExpressLogger = require('@hyperwatch/express-logger');
|
|
62
72
|
|
|
63
73
|
const app = express();
|
|
64
74
|
|
|
65
|
-
app.use(
|
|
75
|
+
app.use(hyperwatchExpressLogger('websocket', 'ws://localhost:3000/input/log'));
|
|
66
76
|
```
|
|
67
77
|
|
|
68
78
|
In this example, there are 3 important things:
|
|
@@ -78,10 +88,10 @@ Note: The Hyperwatch middleware is also capable of logging using the HTTP(s) or
|
|
|
78
88
|
|
|
79
89
|
### Start Hyperwatch
|
|
80
90
|
|
|
81
|
-
Ok, now go back to where
|
|
91
|
+
Ok, now go back to where you wrote the config.
|
|
82
92
|
|
|
83
93
|
```bash
|
|
84
|
-
|
|
94
|
+
hyperwatch express_websocket_example.js
|
|
85
95
|
```
|
|
86
96
|
|
|
87
97
|
### Browse the interface
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperwatch/hyperwatch",
|
|
3
|
+
"version": "3.9.0",
|
|
3
4
|
"description": "Open Source HTTP Traffic Manager",
|
|
4
5
|
"license": "Apache-2.0",
|
|
5
6
|
"author": "François Hodierne <francois@hodierne.net>",
|
|
@@ -11,7 +12,6 @@
|
|
|
11
12
|
"type": "git",
|
|
12
13
|
"url": "https://github.com/hyperwatch/hyperwatch.git"
|
|
13
14
|
},
|
|
14
|
-
"version": "3.8.1",
|
|
15
15
|
"main": "hyperwatch.js",
|
|
16
16
|
"bin": {
|
|
17
17
|
"hyperwatch": "./bin/hyperwatch"
|
|
@@ -27,38 +27,39 @@
|
|
|
27
27
|
"prettier:write": "npm run prettier -- --write"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@hyperwatch/useragent": "^3.
|
|
30
|
+
"@hyperwatch/useragent": "^3.9.1",
|
|
31
31
|
"accept-language-parser": "^1.5.0",
|
|
32
|
-
"ajv": "^
|
|
32
|
+
"ajv": "^8.11.0",
|
|
33
|
+
"ajv-formats": "^2.1.1",
|
|
33
34
|
"chalk": "^4.1.0",
|
|
34
|
-
"country-code-emoji": "^
|
|
35
|
-
"debug": "^4.3.
|
|
35
|
+
"country-code-emoji": "^2.3.0",
|
|
36
|
+
"debug": "^4.3.4",
|
|
36
37
|
"dnsbl": "^3.2.0",
|
|
37
|
-
"express": "^4.
|
|
38
|
-
"express-ws": "^
|
|
39
|
-
"geoip-lite": "^1.4.
|
|
40
|
-
"immutable": "^4.
|
|
41
|
-
"ip-cidr": "^
|
|
42
|
-
"lodash": "^4.17.
|
|
43
|
-
"lru-cache": "^
|
|
38
|
+
"express": "^4.18.2",
|
|
39
|
+
"express-ws": "^5.0.2",
|
|
40
|
+
"geoip-lite": "^1.4.6",
|
|
41
|
+
"immutable": "^4.1.0",
|
|
42
|
+
"ip-cidr": "^3.0.10",
|
|
43
|
+
"lodash": "^4.17.21",
|
|
44
|
+
"lru-cache": "^7.14.0",
|
|
44
45
|
"micro-strptime": "^0.2.3",
|
|
45
|
-
"proxy-addr": "^2.0.
|
|
46
|
+
"proxy-addr": "^2.0.7",
|
|
46
47
|
"rc": "^1.2.8",
|
|
47
48
|
"syslog-parse": "^1.3.1",
|
|
48
|
-
"tail": "^2.
|
|
49
|
-
"uuid": "^
|
|
50
|
-
"ws": "^
|
|
49
|
+
"tail": "^2.2.4",
|
|
50
|
+
"uuid": "^9.0.0",
|
|
51
|
+
"ws": "^8.9.0"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
|
-
"depcheck": "^1.3
|
|
54
|
-
"eslint": "^
|
|
55
|
-
"eslint-plugin-import": "^2.
|
|
54
|
+
"depcheck": "^1.4.3",
|
|
55
|
+
"eslint": "^8.25.0",
|
|
56
|
+
"eslint-plugin-import": "^2.26.0",
|
|
56
57
|
"eslint-plugin-node": "^11.1.0",
|
|
57
58
|
"husky": "^4.3.5",
|
|
58
59
|
"lint-staged": "^10.5.3",
|
|
59
|
-
"mocha": "^
|
|
60
|
-
"prettier": "^2.
|
|
61
|
-
"prettier-package-json": "^2.
|
|
60
|
+
"mocha": "^10.0.0",
|
|
61
|
+
"prettier": "^2.7.1",
|
|
62
|
+
"prettier-package-json": "^2.7.0"
|
|
62
63
|
},
|
|
63
64
|
"engines": {
|
|
64
65
|
"node": ">=12.0"
|
package/src/format/apache.js
CHANGED
|
@@ -94,7 +94,7 @@ function parser({ format }) {
|
|
|
94
94
|
|
|
95
95
|
const formats = {
|
|
96
96
|
combined: '%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i"',
|
|
97
|
-
|
|
97
|
+
hyperwatchCombined:
|
|
98
98
|
'%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i" "%{Accept}i" "%{Accept-Charset}i" "%{Accept-Encoding}i" "%{Accept-Language}i" "%{Connection}i" "%{Dnt}i" "%{From}i" "%{Host}i"',
|
|
99
99
|
};
|
|
100
100
|
|
package/src/format/nginx.js
CHANGED
|
@@ -97,7 +97,7 @@ const formats = {
|
|
|
97
97
|
'$remote_addr - $remote_user [$time_local] "$request" $status $bytes_sent "$http_referer" "$http_user_agent"',
|
|
98
98
|
accessWatch:
|
|
99
99
|
'"$time_iso8601" "$remote_addr" "$http_host" "$request" $status "$http_user_agent" "$http_accept" "$http_accept_language" "$http_accept_charset" "$http_accept_encoding" "$http_from" "$http_dnt" "$http_connection" "$http_referer"',
|
|
100
|
-
|
|
100
|
+
hyperwatchCombined:
|
|
101
101
|
'$remote_addr - $remote_user [$time_local] "$request" $status $bytes_sent "$http_referer" "$http_user_agent" "$http_accept" "$http_accept_charset" "$http_accept_encoding" "$http_accept_language" "$http_connection" "$http_dnt" "$http_from" "$http_host"',
|
|
102
102
|
};
|
|
103
103
|
|
package/src/index.js
CHANGED
|
@@ -8,17 +8,17 @@ const lib = require('./lib');
|
|
|
8
8
|
const modules = require('./modules');
|
|
9
9
|
const plugins = require('./plugins');
|
|
10
10
|
|
|
11
|
-
const { cache, pipeline, util } = lib;
|
|
11
|
+
const { cache, logger, pipeline, util } = lib;
|
|
12
12
|
|
|
13
13
|
let initialized = false;
|
|
14
14
|
|
|
15
15
|
function init(config = {}) {
|
|
16
16
|
if (initialized) {
|
|
17
|
-
console.warn(`Can't init, Hyperwatch was already initialized
|
|
17
|
+
console.warn(`Can't init, Hyperwatch was already initialized.`);
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
20
|
merge(constants, config);
|
|
21
|
-
modules.
|
|
21
|
+
modules.init();
|
|
22
22
|
initialized = true;
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -27,7 +27,7 @@ function start() {
|
|
|
27
27
|
console.warn(`Can't start, Hyperwatch was not initialized.`);
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
|
-
modules.
|
|
30
|
+
modules.start();
|
|
31
31
|
return Promise.all([app.start(), pipeline.start()]);
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -42,6 +42,7 @@ module.exports = {
|
|
|
42
42
|
format,
|
|
43
43
|
input,
|
|
44
44
|
lib,
|
|
45
|
+
logger,
|
|
45
46
|
modules,
|
|
46
47
|
pipeline,
|
|
47
48
|
plugins,
|
package/src/lib/formatter.js
CHANGED
|
@@ -28,6 +28,9 @@ const request = (log) => {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
const executionTime = (log, output) => {
|
|
31
|
+
if (!log.get('executionTime')) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
31
34
|
return log.get('executionTime') <= 100
|
|
32
35
|
? colorize('green', `${log.get('executionTime')}ms`, output)
|
|
33
36
|
: log.get('executionTime') >= 1000
|
package/src/lib/pipeline.js
CHANGED
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*
|
|
10
10
|
* This modules provides functions to build a pipeline, a tree of stream processors.
|
|
11
11
|
*/
|
|
12
|
-
const Ajv = require('ajv');
|
|
12
|
+
const Ajv = require('ajv').default;
|
|
13
|
+
const addFormats = require('ajv-formats').default;
|
|
13
14
|
const { Map } = require('immutable');
|
|
14
15
|
|
|
15
16
|
const schema = require('../format/log-schema.json');
|
|
@@ -18,6 +19,8 @@ const monitoring = require('./monitoring');
|
|
|
18
19
|
const { complement } = require('./util');
|
|
19
20
|
|
|
20
21
|
const validator = new Ajv();
|
|
22
|
+
addFormats(validator);
|
|
23
|
+
|
|
21
24
|
const validate = validator.compile(schema);
|
|
22
25
|
|
|
23
26
|
function errorLog(log, severity = 'warn') {
|
package/src/modules/address.js
CHANGED
|
@@ -11,11 +11,11 @@ function fill(log) {
|
|
|
11
11
|
return log;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
function
|
|
14
|
+
function init() {
|
|
15
15
|
pipeline.getNode('main').map(fill).registerNode('main');
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function
|
|
18
|
+
function start() {
|
|
19
19
|
const aggregator = new Aggregator();
|
|
20
20
|
|
|
21
21
|
aggregator.setIdentifier(identifier);
|
|
@@ -26,6 +26,6 @@ function beforeStart() {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
module.exports = {
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
init,
|
|
30
|
+
start,
|
|
31
31
|
};
|
package/src/modules/agent.js
CHANGED
|
@@ -66,7 +66,7 @@ const osFormat = (log) => {
|
|
|
66
66
|
return agentOs.get('family');
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
function
|
|
69
|
+
function init() {
|
|
70
70
|
pipeline.getNode('main').map(augment).registerNode('main');
|
|
71
71
|
|
|
72
72
|
aggregator.defaultFormatter.insertFormat('agent', agentFormat, {
|
|
@@ -84,7 +84,7 @@ function load() {
|
|
|
84
84
|
module.exports = {
|
|
85
85
|
lookup,
|
|
86
86
|
augment,
|
|
87
|
-
|
|
87
|
+
init,
|
|
88
88
|
agentFormat,
|
|
89
89
|
osFormat,
|
|
90
90
|
};
|
package/src/modules/dnsbl.js
CHANGED
|
@@ -33,7 +33,7 @@ const xblFormat = (log, output) => {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
function
|
|
36
|
+
function init() {
|
|
37
37
|
pipeline.getNode('main').map(augment).registerNode('main');
|
|
38
38
|
|
|
39
39
|
aggregator.defaultFormatter.insertFormat('xbl', xblFormat, {
|
|
@@ -44,5 +44,5 @@ function load() {
|
|
|
44
44
|
|
|
45
45
|
module.exports = {
|
|
46
46
|
augment,
|
|
47
|
-
|
|
47
|
+
init,
|
|
48
48
|
};
|
package/src/modules/geoip.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const { default: flag } = require('country-code-emoji');
|
|
2
2
|
const geoip = require('geoip-lite');
|
|
3
3
|
const { fromJS } = require('immutable');
|
|
4
4
|
|
|
@@ -30,11 +30,11 @@ const city = (log) => {
|
|
|
30
30
|
const country = (log, output) => {
|
|
31
31
|
const cc = log.getIn(['geoip', 'country']);
|
|
32
32
|
if (cc) {
|
|
33
|
-
return output === 'html' ? `${
|
|
33
|
+
return output === 'html' ? `${flag(cc)} ${cc}` : cc;
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
function
|
|
37
|
+
function init() {
|
|
38
38
|
pipeline.getNode('main').map(augment).registerNode('main');
|
|
39
39
|
|
|
40
40
|
aggregator.defaultFormatter.insertFormat('country', country, {
|
|
@@ -53,6 +53,6 @@ function load() {
|
|
|
53
53
|
|
|
54
54
|
module.exports = {
|
|
55
55
|
lookup,
|
|
56
|
-
|
|
56
|
+
init,
|
|
57
57
|
augment,
|
|
58
58
|
};
|
package/src/modules/hostname.js
CHANGED
|
@@ -78,12 +78,12 @@ async function augment(log, { fast = false } = {}) {
|
|
|
78
78
|
return log;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
function
|
|
81
|
+
function init() {
|
|
82
82
|
pipeline.getNode('main').map(augment).registerNode('main');
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
module.exports = {
|
|
86
86
|
lookup,
|
|
87
87
|
augment,
|
|
88
|
-
|
|
88
|
+
init,
|
|
89
89
|
};
|
package/src/modules/identity.js
CHANGED
|
@@ -74,7 +74,7 @@ function augment(log) {
|
|
|
74
74
|
? log.set('identity', 'WebMeUp')
|
|
75
75
|
: log;
|
|
76
76
|
case 'PetalBot':
|
|
77
|
-
return hostname && hostname.endsWith('.
|
|
77
|
+
return hostname && hostname.endsWith('.petalsearch.com')
|
|
78
78
|
? log.set('identity', family)
|
|
79
79
|
: log;
|
|
80
80
|
case 'AhrefsBot':
|
|
@@ -174,6 +174,10 @@ function augment(log) {
|
|
|
174
174
|
return hostname && hostname.endsWith('.arquivo.pt')
|
|
175
175
|
? log.set('identity', 'Arquivo')
|
|
176
176
|
: log;
|
|
177
|
+
case 'SeekportBot':
|
|
178
|
+
return hostname && hostname.endsWith('.007ac9.net')
|
|
179
|
+
? log.set('identity', 'Seekport')
|
|
180
|
+
: log;
|
|
177
181
|
|
|
178
182
|
// Per hostname + CIDR
|
|
179
183
|
case 'Twitterbot':
|
|
@@ -236,6 +240,15 @@ function augment(log) {
|
|
|
236
240
|
return hostname && hostname.endsWith('.compute-1.amazonaws.com')
|
|
237
241
|
? log.set('identity', 'Common Crawl')
|
|
238
242
|
: log;
|
|
243
|
+
case 'TransferWise-Webhook':
|
|
244
|
+
return hostname &&
|
|
245
|
+
hostname.endsWith('.eu-central-1.compute.amazonaws.com')
|
|
246
|
+
? log.set('identity', 'Wise')
|
|
247
|
+
: log;
|
|
248
|
+
case 'Amazonbot':
|
|
249
|
+
return hostname && hostname.endsWith('.compute-1.amazonaws.com')
|
|
250
|
+
? log.set('identity', 'Amazonbot')
|
|
251
|
+
: log;
|
|
239
252
|
|
|
240
253
|
// GCE
|
|
241
254
|
case 'VelenPublicWebCrawler':
|
|
@@ -301,11 +314,11 @@ const identifier = (log) =>
|
|
|
301
314
|
log.getIn(['address', 'value']) ||
|
|
302
315
|
log.getIn(['request', 'address']);
|
|
303
316
|
|
|
304
|
-
function
|
|
317
|
+
function init() {
|
|
305
318
|
pipeline.getNode('main').map(augment).registerNode('main');
|
|
306
319
|
}
|
|
307
320
|
|
|
308
|
-
function
|
|
321
|
+
function start() {
|
|
309
322
|
const aggregator = new Aggregator();
|
|
310
323
|
|
|
311
324
|
aggregator.setIdentifier(identifier);
|
|
@@ -317,6 +330,6 @@ function beforeStart() {
|
|
|
317
330
|
|
|
318
331
|
module.exports = {
|
|
319
332
|
augment,
|
|
320
|
-
|
|
321
|
-
|
|
333
|
+
init,
|
|
334
|
+
start,
|
|
322
335
|
};
|
package/src/modules/index.js
CHANGED
|
@@ -45,25 +45,25 @@ function activeModules() {
|
|
|
45
45
|
.filter((m) => m);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
function
|
|
48
|
+
function init() {
|
|
49
49
|
for (const module of activeModules()) {
|
|
50
|
-
if (module && module.
|
|
51
|
-
module.
|
|
50
|
+
if (module && module.init) {
|
|
51
|
+
module.init();
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function
|
|
56
|
+
function start() {
|
|
57
57
|
for (const module of activeModules()) {
|
|
58
|
-
if (module && module.
|
|
59
|
-
module.
|
|
58
|
+
if (module && module.start) {
|
|
59
|
+
module.start();
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
module.exports = {
|
|
65
65
|
get,
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
init,
|
|
67
|
+
start,
|
|
68
68
|
activeModules,
|
|
69
69
|
};
|
package/src/modules/language.js
CHANGED
|
@@ -29,7 +29,7 @@ const language = (log) => {
|
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
function
|
|
32
|
+
function init() {
|
|
33
33
|
pipeline.getNode('main').map(augment).registerNode('main');
|
|
34
34
|
|
|
35
35
|
aggregator.defaultFormatter.insertFormat('language', language, {
|
|
@@ -40,5 +40,5 @@ function load() {
|
|
|
40
40
|
|
|
41
41
|
module.exports = {
|
|
42
42
|
augment,
|
|
43
|
-
|
|
43
|
+
init,
|
|
44
44
|
};
|
package/src/modules/logs.js
CHANGED
|
@@ -2,7 +2,7 @@ const { api, websocket } = require('../app');
|
|
|
2
2
|
const { defaultFormatter } = require('../lib/logger');
|
|
3
3
|
const pipeline = require('../lib/pipeline');
|
|
4
4
|
|
|
5
|
-
function
|
|
5
|
+
function start() {
|
|
6
6
|
for (const [name, stream] of Object.entries(pipeline.nodes)) {
|
|
7
7
|
websocket.streamToWebsocket(`/logs/${name}`, stream, {
|
|
8
8
|
name: `WebSocket (${name} logs)`,
|
|
@@ -16,4 +16,4 @@ function beforeStart() {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
module.exports = {
|
|
19
|
+
module.exports = { start };
|
package/src/modules/signature.js
CHANGED
|
@@ -56,11 +56,11 @@ function augment(log) {
|
|
|
56
56
|
return log;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function
|
|
59
|
+
function init() {
|
|
60
60
|
pipeline.getNode('main').map(augment).registerNode('main');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
function
|
|
63
|
+
function start() {
|
|
64
64
|
const aggregator = new Aggregator();
|
|
65
65
|
|
|
66
66
|
aggregator.setIdentifier((log) => log.getIn(['signature', 'id']));
|
|
@@ -127,6 +127,6 @@ function beforeStart() {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
module.exports = {
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
init,
|
|
131
|
+
start,
|
|
132
132
|
};
|
package/src/modules/sparkline.js
CHANGED
|
@@ -21,12 +21,12 @@ sparkline ('${id}', ${JSON.stringify(points)}, '#797979', 14, 5);
|
|
|
21
21
|
</script>`;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
function
|
|
24
|
+
function init() {
|
|
25
25
|
aggregator.defaultFormatter.insertFormat('activity', (entry) =>
|
|
26
26
|
sparkline(entry, 'per_minute')
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
module.exports = {
|
|
31
|
-
|
|
31
|
+
init,
|
|
32
32
|
};
|
package/src/modules/status.js
CHANGED
|
@@ -22,7 +22,7 @@ function mapper(entry, format) {
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function
|
|
25
|
+
function start() {
|
|
26
26
|
api.get('/status(.:format(txt|json))?', (req, res) => {
|
|
27
27
|
const raw = req.query.raw ? true : false;
|
|
28
28
|
const format = req.params.format || (raw ? 'json' : null);
|
|
@@ -48,4 +48,4 @@ function beforeStart() {
|
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
module.exports = {
|
|
51
|
+
module.exports = { start };
|
package/start.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
|
|
3
|
+
const { isFunction } = require('lodash');
|
|
4
|
+
|
|
3
5
|
const hyperwatch = require('./hyperwatch');
|
|
4
6
|
|
|
5
7
|
// Load configuration
|
|
6
8
|
|
|
9
|
+
let config;
|
|
7
10
|
if (process.argv[2]) {
|
|
8
|
-
require(path.resolve(process.cwd(), process.argv[2]));
|
|
11
|
+
config = require(path.resolve(process.cwd(), process.argv[2]));
|
|
9
12
|
} else {
|
|
10
|
-
require(path.resolve(__dirname, './config/default'));
|
|
13
|
+
config = require(path.resolve(__dirname, './config/default'));
|
|
14
|
+
}
|
|
15
|
+
if (isFunction(config)) {
|
|
16
|
+
config(hyperwatch);
|
|
11
17
|
}
|
|
12
18
|
|
|
13
19
|
// Start
|