@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 CHANGED
@@ -1,61 +1,88 @@
1
- const hyperWatch = require('../hyperwatch');
1
+ const defaultConfig = function (hyperwatch) {
2
+ const { pipeline, input, format, logger } = hyperwatch;
2
3
 
3
- const { pipeline, input, format } = hyperWatch;
4
+ /* Init Hyperwatch (will load modules) */
4
5
 
5
- /* Input configuration
6
- ====================== */
6
+ hyperwatch.init();
7
7
 
8
- /* Syslog inputs
9
- ---------------- */
8
+ /* Input configuration */
9
+ /* =================== */
10
10
 
11
- /* Syslog input in Nginx 'combined' format */
11
+ /* Syslog inputs */
12
+ /* ------------- */
12
13
 
13
- const syslogNginxCombinedInput = input.syslog.create({
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
- pipeline.registerInput(syslogNginxCombinedInput);
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
- /* Syslog input in Nginx 'access_watch' format */
22
+ pipeline.registerInput(syslogNginxCombinedInput);
22
23
 
23
- const syslogNginxAccessWatchInput = input.syslog.create({
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
- pipeline.registerInput(syslogNginxAccessWatchInput);
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
- /* Syslog input in Hyperwatch JSON format */
34
+ pipeline.registerInput(syslogNginxHyperwatchCombinedInput);
32
35
 
33
- const syslogInput = input.syslog.create({
34
- name: 'Syslog (JSON standard format)',
35
- port: 1516,
36
- });
36
+ /* Syslog input in Hyperwatch JSON format */
37
37
 
38
- pipeline.registerInput(syslogInput);
38
+ const syslogInput = input.syslog.create({
39
+ name: 'Syslog (JSON standard format)',
40
+ port: 1516,
41
+ });
39
42
 
40
- /* HTTP inputs
41
- -------------- */
43
+ pipeline.registerInput(syslogInput);
42
44
 
43
- /* HTTP input in Hyperwatch JSON format */
45
+ /* HTTP inputs */
46
+ /* ----------- */
44
47
 
45
- const httpInput = input.http.create({
46
- name: 'HTTP server (JSON standard format)',
47
- path: '/input/log',
48
- });
48
+ /* HTTP input in Hyperwatch JSON format */
49
49
 
50
- pipeline.registerInput(httpInput);
50
+ const httpInput = input.http.create({
51
+ name: 'HTTP server (JSON standard format)',
52
+ path: '/input/log',
53
+ });
51
54
 
52
- const webSocketServerInput = input.websocket.create({
53
- name: 'WebSocket server (JSON standard format)',
54
- type: 'server',
55
- path: '/input/log',
56
- });
55
+ pipeline.registerInput(httpInput);
57
56
 
58
- pipeline.registerInput(webSocketServerInput);
57
+ const webSocketServerInput = input.websocket.create({
58
+ name: 'WebSocket server (JSON standard format)',
59
+ type: 'server',
60
+ path: '/input/log',
61
+ });
59
62
 
60
- // Output to the console as JS object
61
- pipeline.map((log) => console.log(log.toJS()));
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 hyperWatch = require('../hyperwatch');
1
+ const exampleConfig = function (hyperwatch) {
2
+ const { pipeline, input, format, logger } = hyperwatch;
2
3
 
3
- const { pipeline, input, format, plugins } = hyperWatch;
4
+ /* Init Hyperwatch (will load modules) */
4
5
 
5
- /* Input configuration
6
- ====================== */
6
+ hyperwatch.init();
7
7
 
8
- /* Syslog inputs
9
- ---------------- */
8
+ /* Input configuration */
9
+ /* =================== */
10
10
 
11
- /* Syslog input in Nginx 'combined' format */
11
+ /* Syslog inputs */
12
+ /* ------------- */
12
13
 
13
- const syslogNginxCombinedInput = input.syslog.create({
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
- pipeline.registerInput(syslogNginxCombinedInput);
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
- /* Syslog input in Nginx 'access_watch' format */
22
+ pipeline.registerInput(syslogNginxCombinedInput);
22
23
 
23
- const syslogNginxAccessWatchInput = input.syslog.create({
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
- pipeline.registerInput(syslogNginxAccessWatchInput);
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
- /* Syslog input in Hyperwatch JSON format */
34
+ pipeline.registerInput(syslogNginxHyperwatchCombinedInput);
32
35
 
33
- const syslogInput = input.syslog.create({
34
- name: 'Syslog (JSON standard format)',
35
- port: 1516,
36
- });
36
+ /* Syslog input in Hyperwatch JSON format */
37
37
 
38
- pipeline.registerInput(syslogInput);
38
+ const syslogInput = input.syslog.create({
39
+ name: 'Syslog (JSON standard format)',
40
+ port: 1516,
41
+ });
39
42
 
40
- /* Syslog input in Apache 'combined' format */
43
+ pipeline.registerInput(syslogInput);
41
44
 
42
- // const syslogApacheCombinedInput = input.syslog.create({
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
- // pipeline.registerInput(syslogApacheCombinedInput)
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
- /* Syslog input in Apache 'access_watch_combined' format */
55
+ pipeline.registerInput(syslogApacheCombinedInput);
52
56
 
53
- // const syslogApacheAccessWatchCombinedInput = input.syslog.create({
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
- // pipeline.registerInput(syslogApacheAccessWatchCombinedInput)
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
- /* HTTP inputs
63
- -------------- */
67
+ pipeline.registerInput(syslogApacheHyperwatchCombinedInput);
64
68
 
65
- /* HTTP input in Hyperwatch JSON format */
69
+ /* HTTP inputs */
70
+ /* ----------- */
66
71
 
67
- const httpInput = input.http.create({
68
- name: 'HTTP server (JSON standard format)',
69
- path: '/input/log',
70
- });
72
+ /* HTTP input in Hyperwatch JSON format */
71
73
 
72
- pipeline.registerInput(httpInput);
74
+ const httpInput = input.http.create({
75
+ name: 'HTTP server (JSON standard format)',
76
+ path: '/input/log',
77
+ });
73
78
 
74
- /* WebSocket inputs
75
- ------------------- */
79
+ pipeline.registerInput(httpInput);
76
80
 
77
- /* WebSocket server input in Hyperwatch JSON format (listening for logs) */
81
+ /* WebSocket inputs */
82
+ /* ---------------- */
78
83
 
79
- // const webSocketServerInput = input.websocket.create({
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
- // pipeline.registerInput(webSocketServerInput)
86
+ const webSocketServerInput = input.websocket.create({
87
+ name: 'WebSocket server (JSON standard format)',
88
+ type: 'server',
89
+ path: '/input/log',
90
+ });
86
91
 
87
- /* WebSocket client input in Hyperwatch JSON format (subscribing to logs) */
92
+ pipeline.registerInput(webSocketServerInput);
88
93
 
89
- // const websocketClientInput = input.websocket.create({
90
- // address: 'ws://HOST:PORT/logs'
91
- // })
94
+ /* WebSocket client input in Hyperwatch JSON format (subscribing to logs) */
92
95
 
93
- // pipeline.registerInput(websocketClientInput)
96
+ // const websocketClientInput = input.websocket.create({
97
+ // name: 'WebSocket client (JSON standard format)',
98
+ // address: 'ws://HOST:PORT/logs',
99
+ // });
94
100
 
95
- /* File inputs
96
- -------------- */
101
+ // pipeline.registerInput(websocketClientInput);
97
102
 
98
- /* File input in Nginx 'combined' format */
103
+ /* File inputs */
104
+ /* ----------- */
99
105
 
100
- // const fileNginxCombinedInput = input.file.create({
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
- // pipeline.registerInput(fileNginxCombinedInput)
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
- /* File input in Nginx 'access_watch' format */
116
+ // pipeline.registerInput(fileNginxCombinedInput);
110
117
 
111
- // const fileNginxAccessWatchInput = input.file.create({
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
- // pipeline.registerInput(fileNginxAccessWatchInput)
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
- const { proxy } = plugins;
130
+ /* File input in Apache 'combined' format */
126
131
 
127
- const stream = pipeline
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
- /* Filter requests */
140
+ // pipeline.registerInput(fileApacheCombinedInput);
130
141
 
131
- // .filter(log => log.getIn(['request', 'host']) === 'example.com')
142
+ /* File input in Apache 'hyperwatch' format */
132
143
 
133
- /* Detect the public IP address if it's behind a proxy */
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
- .map((log) =>
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
- /* Output to the console as JS object */
154
+ /* Pipeline configuration */
155
+ /* ====================== */
146
156
 
147
- .map((log) => console.log(log.toJS()));
148
-
149
- module.exports = {
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;
@@ -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 and ask the metrics to be garbage collected if they are more than one hour old.
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
- During the beta phase, let's use Git and clone the public repository:
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 `./config/default.js` and `./config/example.js` file.
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 `./config/apache.js`:
43
+ Now, you can create your own configuration in `apache_syslog_example.js`:
36
44
 
37
45
  ```javascript
38
- const hyperWatch = require('../hyperwatch');
46
+ module.exports = function (hyperwatch) {
47
+ const { pipeline, input, format } = hyperwatch;
39
48
 
40
- const { pipeline, input, format } = hyperWatch;
49
+ hyperwatch.init();
41
50
 
42
- const syslogApacheAccessWatchCombinedInput = input.syslog.create({
43
- port: 1518,
44
- parse: format.apache.parser({
45
- format: format.apache.formats.accessWatchCombined,
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(syslogApacheAccessWatchCombinedInput);
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 `access_watch_combined` format, you need to define it in the Apache configuration. This will not replace the standard log format, just create an additional one.
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\"" access_watch_combined
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" access_watch_combined
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 `access_watch_combined` format on port `1518`.
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 `access_watch_combined` log format we previously configured.
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 Hyperwatch is installed and start it.
96
+ Ok, now go back to where you wrote the config.
87
97
 
88
98
  ```bash
89
- npm start config/apache.js
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 &gt;= 7. Use nvm if you're in trouble.
16
16
  nvm install node
17
17
  ```
18
18
 
19
- During the beta phase, let's use Git and clone the public repository:
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, so please only use that setup in 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.
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 `./config/config.js`:
41
+ Now, you can create your own configuration in `express_websocket_example.js`:
34
42
 
35
43
  ```javascript
36
- const hyperWatch = require('../hyperwatch');
44
+ module.exports = function (hyperwatch) {
45
+ const { pipeline, input } = hyperwatch;
37
46
 
38
- const { pipeline, input } = hyperWatch;
47
+ hyperwatch.init();
39
48
 
40
- const webSocketServerInput = input.websocket.create({
41
- name: 'WebSocket server (JSON standard format)',
42
- type: 'server',
43
- path: '/input/log',
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 access-watch-express-logger
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 accessWatchExpressLogger = require('access-watch-express-logger');
71
+ const hyperwatchExpressLogger = require('@hyperwatch/express-logger');
62
72
 
63
73
  const app = express();
64
74
 
65
- app.use(accessWatchExpressLogger('websocket', 'ws://localhost:3000/input/log'));
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 Hyperwatch is installed and start it.
91
+ Ok, now go back to where you wrote the config.
82
92
 
83
93
  ```bash
84
- npm start config/config.js
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.7.4",
30
+ "@hyperwatch/useragent": "^3.9.1",
31
31
  "accept-language-parser": "^1.5.0",
32
- "ajv": "^6.12.6",
32
+ "ajv": "^8.11.0",
33
+ "ajv-formats": "^2.1.1",
33
34
  "chalk": "^4.1.0",
34
- "country-code-emoji": "^1.0.0",
35
- "debug": "^4.3.1",
35
+ "country-code-emoji": "^2.3.0",
36
+ "debug": "^4.3.4",
36
37
  "dnsbl": "^3.2.0",
37
- "express": "^4.17.1",
38
- "express-ws": "^4.0.0",
39
- "geoip-lite": "^1.4.2",
40
- "immutable": "^4.0.0-rc.12",
41
- "ip-cidr": "^2.1.1",
42
- "lodash": "^4.17.20",
43
- "lru-cache": "^6.0.0",
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.6",
46
+ "proxy-addr": "^2.0.7",
46
47
  "rc": "^1.2.8",
47
48
  "syslog-parse": "^1.3.1",
48
- "tail": "^2.0.4",
49
- "uuid": "^8.3.2",
50
- "ws": "^7.4.1"
49
+ "tail": "^2.2.4",
50
+ "uuid": "^9.0.0",
51
+ "ws": "^8.9.0"
51
52
  },
52
53
  "devDependencies": {
53
- "depcheck": "^1.3.1",
54
- "eslint": "^7.15.0",
55
- "eslint-plugin-import": "^2.22.1",
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": "^8.2.1",
60
- "prettier": "^2.2.1",
61
- "prettier-package-json": "^2.1.3"
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"
@@ -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
- accessWatchCombined:
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
 
@@ -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
- accessWatchCombined:
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.load();
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.beforeStart();
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,
@@ -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
@@ -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') {
@@ -11,11 +11,11 @@ function fill(log) {
11
11
  return log;
12
12
  }
13
13
 
14
- function load() {
14
+ function init() {
15
15
  pipeline.getNode('main').map(fill).registerNode('main');
16
16
  }
17
17
 
18
- function beforeStart() {
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
- load,
30
- beforeStart,
29
+ init,
30
+ start,
31
31
  };
@@ -66,7 +66,7 @@ const osFormat = (log) => {
66
66
  return agentOs.get('family');
67
67
  };
68
68
 
69
- function load() {
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
- load,
87
+ init,
88
88
  agentFormat,
89
89
  osFormat,
90
90
  };
@@ -35,11 +35,11 @@ function augment(log) {
35
35
  return log;
36
36
  }
37
37
 
38
- function load() {
38
+ function init() {
39
39
  pipeline.getNode('main').map(augment).registerNode('main');
40
40
  }
41
41
 
42
42
  module.exports = {
43
43
  augment,
44
- load,
44
+ init,
45
45
  };
@@ -33,7 +33,7 @@ const xblFormat = (log, output) => {
33
33
  }
34
34
  };
35
35
 
36
- function load() {
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
- load,
47
+ init,
48
48
  };
@@ -1,4 +1,4 @@
1
- const countryCodeEmoji = require('country-code-emoji');
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' ? `${countryCodeEmoji(cc)} ${cc}` : cc;
33
+ return output === 'html' ? `${flag(cc)} ${cc}` : cc;
34
34
  }
35
35
  };
36
36
 
37
- function load() {
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
- load,
56
+ init,
57
57
  augment,
58
58
  };
@@ -78,12 +78,12 @@ async function augment(log, { fast = false } = {}) {
78
78
  return log;
79
79
  }
80
80
 
81
- function load() {
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
- load,
88
+ init,
89
89
  };
@@ -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('.aspiegel.com')
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 load() {
317
+ function init() {
305
318
  pipeline.getNode('main').map(augment).registerNode('main');
306
319
  }
307
320
 
308
- function beforeStart() {
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
- load,
321
- beforeStart,
333
+ init,
334
+ start,
322
335
  };
@@ -45,25 +45,25 @@ function activeModules() {
45
45
  .filter((m) => m);
46
46
  }
47
47
 
48
- function load() {
48
+ function init() {
49
49
  for (const module of activeModules()) {
50
- if (module && module.load) {
51
- module.load();
50
+ if (module && module.init) {
51
+ module.init();
52
52
  }
53
53
  }
54
54
  }
55
55
 
56
- function beforeStart() {
56
+ function start() {
57
57
  for (const module of activeModules()) {
58
- if (module && module.beforeStart) {
59
- module.beforeStart();
58
+ if (module && module.start) {
59
+ module.start();
60
60
  }
61
61
  }
62
62
  }
63
63
 
64
64
  module.exports = {
65
65
  get,
66
- load,
67
- beforeStart,
66
+ init,
67
+ start,
68
68
  activeModules,
69
69
  };
@@ -29,7 +29,7 @@ const language = (log) => {
29
29
  }
30
30
  };
31
31
 
32
- function load() {
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
- load,
43
+ init,
44
44
  };
@@ -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 beforeStart() {
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 = { beforeStart };
19
+ module.exports = { start };
@@ -56,11 +56,11 @@ function augment(log) {
56
56
  return log;
57
57
  }
58
58
 
59
- function load() {
59
+ function init() {
60
60
  pipeline.getNode('main').map(augment).registerNode('main');
61
61
  }
62
62
 
63
- function beforeStart() {
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
- load,
131
- beforeStart,
130
+ init,
131
+ start,
132
132
  };
@@ -21,12 +21,12 @@ sparkline ('${id}', ${JSON.stringify(points)}, '#797979', 14, 5);
21
21
  </script>`;
22
22
  };
23
23
 
24
- function load() {
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
- load,
31
+ init,
32
32
  };
@@ -22,7 +22,7 @@ function mapper(entry, format) {
22
22
  };
23
23
  }
24
24
 
25
- function beforeStart() {
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 = { beforeStart };
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