Skip to content

Commit 4f814f3

Browse files
ad-mfredericosilva
authored andcommitted
journal: Improve error handling, document filtering (#441)
* juornal: Improve error handling, document filtering * Update docs * Use single-quote in eslintrc
1 parent e46f23d commit 4f814f3

10 files changed

Lines changed: 65 additions & 87 deletions

File tree

.eslintrc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22

33
module.exports = {
4-
extends: '@hyperone'
4+
extends: '@hyperone',
5+
parser: 'babel-eslint',
56
};

bin/journal/examples.md

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,6 @@
1010
{{command_name}} credential password add --log my-server-log --name syslog --password my-strong-secret
1111
```
1212

13-
# Configure rsyslog
14-
15-
Open or create a new configuration file for rsyslog:
16-
17-
```
18-
sudo nano /etc/rsyslog.d/50-hyperone.conf
19-
```
20-
21-
Paste in this configuration:
22-
23-
```
24-
$template HyperOneFormat,"<%pri%>%protocol-version% %timestamp:::date-rfc3339% %HOSTNAME% %app-name% %procid% %msgid% [{log_id}:{secret}@HyperOne tag=\"Rsyslog\"]%msg%\n"
25-
26-
*.* @@{log_id}.logarchive.{region}.hyperone.cloud:6514; HyperOneFormat
27-
```
28-
29-
Replace the following values in the example:
30-
31-
* ```{log_id}``` - ID of log. To identify available logs use ```{{scope}} log list```.
32-
* ```{secret}``` - The password added to given log. See example above how to create a write-only password.
33-
* ```{region}``` - Region where resource exists eg. ```pl-waw-1```
34-
35-
Remember to restart rsyslog:
36-
37-
```
38-
sudo service rsyslog restart
39-
```
40-
4113
# Display today's log entries
4214

4315
```bash

bin/journal/filters.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
'use strict';
22
const Cli = require('lib/cli');
3-
3+
const { get } = require('../../lib/transform');
44

55
const handlers = {
6-
'^([a-zA-Z]+) *= *(.+?)$' : (key, val, data) => data[key] == val,
7-
'^([a-zA-Z]+) *> *(.+?)$' : (key, val, data) => data[key] > val,
8-
'^([a-zA-Z]+) *< *(.+?)$' : (key, val, data) => data[key] < val,
9-
'^([a-zA-Z]+) *~ *(.+?)$' : (key, val, data) => new RegExp(val).test(data[key]),
6+
'^([a-zA-Z0-9\.]+)\s*=~\s*(.+?)$': (key, val, data) => new RegExp(val).test(get(data, key)),
7+
'^([a-zA-Z0-9\.]+)\s*=\s*(.+?)$': (key, val, data) => get(data, key) == val,
8+
'^([a-zA-Z0-9\.]+)\s*>\s*(.+?)$': (key, val, data) => get(data, key) > val,
9+
'^([a-zA-Z0-9\.]+)\s*<\s*(.+?)$': (key, val, data) => get(data, key) < val,
1010
};
1111

12-
1312
const match = (filter, data) => {
14-
for (const pattern in handlers) {
13+
for (const [pattern, handler] of Object.entries(handlers)) {
1514
const res = new RegExp(pattern).exec(filter);
1615
if (!res) {
1716
continue;
1817
}
19-
const handler = handlers[pattern];
2018
return handler(res[1], res[2], data);
2119
}
2220
throw Cli.error.cancelled(`Unable to parse query '${filter}'`);

bin/journal/format.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,16 @@ const outputFormat = {
3232
header: () => {
3333
},
3434
row: (fields, row) => {
35-
const values = fields.map(field => row[field]);
35+
const values = fields.map(field => get(row, field));
3636
return values.map(value => {
3737
if (typeof value === 'number' || typeof value === 'boolean') {
38-
return value;
38+
return `${value}`;
3939
}
4040
if (typeof value === 'string') {
4141
return value.match(/\t/) ? `"${value}"` : value;
4242
}
4343
return '-';
4444
}).join('\t');
45-
4645
},
4746
},
4847
csv: {
@@ -60,7 +59,7 @@ const outputOptions = {
6059
},
6160
fields: {
6261
type: (val) => val.split(','),
63-
description: 'Fields displayed. Not apply to "jsonl" output.',
62+
description: 'Fields displayed. Apply only to "tsv" & "csv" output.',
6463
defaultValue: default_fields.join(','),
6564
},
6665
filter: {

bin/journal/stream/examples.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,17 @@
77
# View live-stream of log entries for the Nginx application
88

99
```bash
10-
{{command_name}} --log my-server-log --follow --filter appName~nginx
10+
{{command_name}} --log my-server-log --follow --filter appName=~nginx
1111
```
12+
13+
# Filtering
14+
15+
Parameter ```--filter``` accept following query format:
16+
17+
* `{fieldName}=~{value}` - filter by regexp pattern. Example ```--filter 'message=~.*isAuthenticated: true.*'```
18+
* `{fieldName}={value}` - filter by exact match field to value. Example: ```--filter 'tag.containerId=1234'```
19+
* `{fieldName}={value}` - filter by values higher than ```{value}``
20+
* `{fieldName}={value}` - filter by values lower than ```{value}``
21+
22+
```{fieldName}``` is name of property of log entry. It can contains any character in range of ```A-Za-z.``` .
23+
The ```.``` sign is specially treated and is used to refer to the nested properties of the object.

bin/journal/stream/index.js

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,14 @@ module.exports = resource => {
7979
const url = `${resource.url(args)}/${args[resource.name]}/log?${qs.stringify(query)}`;
8080
let count = 0;
8181
const stream = await args.helpers.api.stream(url);
82-
return new Promise((resolve, reject) => stream
83-
.on('data', jsonl => {
84-
if (formatter.print_jsonl(jsonl)) {
85-
count += 1;
86-
}
87-
if (args.head && count >= args.head) {
88-
stream.end();
89-
}
90-
})
91-
.on('error', reject)
92-
.on('end', resolve)
93-
.resume()
94-
);
82+
for await (const jsonl of stream) {
83+
if (formatter.print_jsonl(jsonl)) {
84+
count += 1;
85+
}
86+
if (args.head && count >= args.head) {
87+
stream.end();
88+
}
89+
}
9590
},
9691
});
9792

bin/journal/tests.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
'use strict';
2-
const fs = require('fs');
2+
const fs = require('fs').promises;
33
const ava = require('ava');
44

55
require('../../scope/h1');
@@ -27,8 +27,9 @@ ava.serial('journal logger & stream', async t => {
2727
try {
2828
await tests.run(`journal credential password add --journal ${journal.id} --name my-token --password ${token}`);
2929
await tests.run(`journal logger --journal ${journal.id} --token ${token} --log-file ${log_file}`);
30+
await tests.delay(3 * 1000);
3031
await tests.run(`journal stream --head 1 --journal ${journal.id} --jsonl-file ${output_file}`);
31-
const log_content = fs.readFileSync(output_file, 'utf-8');
32+
const log_content = await fs.readFile(output_file, 'utf-8');
3233
t.true(!!log_content);
3334
t.true(JSON.parse(log_content).message === content);
3435
} finally {
@@ -48,8 +49,9 @@ ava.serial('journal logger & stream with tags', async t => {
4849
try {
4950
await tests.run(`journal logger --journal ${journal.id} --token ${token} --log-file ${log_file_with_tag} --tag host=123`);
5051
await tests.run(`journal logger --journal ${journal.id} --token ${token} --log-file ${log_file_without_tag}`);
52+
await tests.delay(3 * 1000);
5153
await tests.run(`journal stream --journal ${journal.id} --jsonl-file ${output_file} --tag host=123`);
52-
const log_content = fs.readFileSync(output_file, 'utf-8');
54+
const log_content = await fs.readFile(output_file, 'utf-8');
5355
t.true(!!log_content);
5456
const logs = log_content.split('\n').filter(x => !!x).map(x => JSON.parse(x));
5557
t.true(logs.some(x => x.message === content_with_tag));

docs/journal.md

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,34 +53,6 @@ h1 journal create --name my-server-log
5353
h1 journal credential password add --log my-server-log --name syslog --password my-strong-secret
5454
```
5555

56-
#### Configure rsyslog
57-
58-
Open or create a new configuration file for rsyslog:
59-
60-
```
61-
sudo nano /etc/rsyslog.d/50-hyperone.conf
62-
```
63-
64-
Paste in this configuration:
65-
66-
```
67-
$template HyperOneFormat,"<%pri%>%protocol-version% %timestamp:::date-rfc3339% %HOSTNAME% %app-name% %procid% %msgid% [{log_id}:{secret}@HyperOne tag=\"Rsyslog\"]%msg%\n"
68-
69-
*.* @@{log_id}.logarchive.{region}.hyperone.cloud:6514; HyperOneFormat
70-
```
71-
72-
Replace the following values in the example:
73-
74-
* ```{log_id}``` - ID of log. To identify available logs use ```h1 log list```.
75-
* ```{secret}``` - The password added to given log. See example above how to create a write-only password.
76-
* ```{region}``` - Region where resource exists eg. ```pl-waw-1```
77-
78-
Remember to restart rsyslog:
79-
80-
```
81-
sudo service rsyslog restart
82-
```
83-
8456
#### Display today's log entries
8557

8658
```bash
@@ -294,9 +266,21 @@ h1 journal stream --log my-server-log
294266
#### View live-stream of log entries for the Nginx application
295267

296268
```bash
297-
h1 journal stream --log my-server-log --follow --filter appName~nginx
269+
h1 journal stream --log my-server-log --follow --filter appName=~nginx
298270
```
299271

272+
#### Filtering
273+
274+
Parameter ```--filter``` accept following query format:
275+
276+
* `{fieldName}=~{value}` - filter by regexp pattern. Example ```--filter 'message=~.*isAuthenticated: true.*'```
277+
* `{fieldName}={value}` - filter by exact match field to value. Example: ```--filter 'tag.containerId=1234'```
278+
* `{fieldName}={value}` - filter by values higher than ```{value}``
279+
* `{fieldName}={value}` - filter by values lower than ```{value}``
280+
281+
```{fieldName}``` is name of property of log entry. It can contains any character in range of ```A-Za-z.``` .
282+
The ```.``` sign is specially treated and is used to refer to the nested properties of the object.
283+
300284
### Required arguments
301285

302286
| Name | Default | Description |

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"@hyperone/eslint-config": "^1.0.4",
6767
"ajv": "^6.10.2",
6868
"ava": "^2.4.0",
69+
"babel-eslint": "^10.0.3",
6970
"dns-socket": "^4.2.0",
7071
"eslint": "^6.4.0",
7172
"fast-glob": "^3.0.4",

0 commit comments

Comments
 (0)