/
tail.ts
117 lines (105 loc) · 2.89 KB
/
tail.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import BaseCommand from '../../base';
import * as chalk from 'chalk';
interface LogContent {
t: string;
s: string;
m: string;
}
interface LogEntry {
createdAt: string;
content: LogContent[];
extensionContribution: {
identifier: string;
};
}
interface ExtensionLogResult {
body?: {
data: {
extensionLogs: {
nodes: LogEntry[];
};
};
};
}
const colorizeSeverity = (s: string) => {
let color;
switch (s) {
case 'e':
color = chalk.bgRed.dim.bold;
break;
case 'w':
color = chalk.bgYellow.dim.bold;
break;
case 'i':
color = chalk.bgCyan.dim.bold;
break;
case 'd':
color = chalk.bgWhite.dim.bold;
break;
default:
color = chalk.dim.bold;
}
return color(` ${s.toUpperCase()} `);
};
const outputLog = (logGroup: LogEntry, log: LogContent) => {
process.stdout.write(chalk.blue(log.t));
process.stdout.write(' ');
process.stdout.write(chalk.dim(logGroup.extensionContribution.identifier));
process.stdout.write(' ');
process.stdout.write(colorizeSeverity(log.s));
process.stdout.write(' ');
if (typeof log.m === 'string') process.stdout.write(log.m);
else process.stdout.write(JSON.stringify(log.m));
process.stdout.write('\n');
};
export default class Tail extends BaseCommand {
static needsAuth = true;
static description = 'Live tail extension logs';
static flags = {
...BaseCommand.flags,
};
async run() {
let lastTimestamp = new Date().toISOString();
const loopDelayStart = 100;
const loopDelayMax = 5000;
let loopDelayMs = loopDelayStart;
const startTime = new Date().getTime();
while (true) {
// Only loop for one hour so this can't use infinite resources.
if (startTime + 60 * 60 * 1000 < new Date().getTime()) {
process.stdout.write('Stopping after one hour.\n');
break;
}
const result = (await this.api.post(`/api/v2/graphql`, {
body: {
query: `{
extensionLogs(filters: {createdSince: "${lastTimestamp}"}) {
nodes {
extensionContribution {
identifier
}
content
createdAt
}
}
}
`,
},
})) as ExtensionLogResult;
if (result.body && result.body.data.extensionLogs.nodes.length === 0) {
// Nothing happening. Wait a bit before looping again.
await new Promise(resolve => setTimeout(resolve, loopDelayMs));
if (loopDelayMs < loopDelayMax) loopDelayMs += 500;
} else if (result.body) {
// Check faster next time.
loopDelayMs = loopDelayStart;
for (const logGroup of result.body.data.extensionLogs.nodes) {
for (const log of logGroup.content) {
outputLog(logGroup, log);
}
lastTimestamp = logGroup.createdAt;
}
}
}
}
}