@agoric/telemetry 0.6.3-dev-91a9ad7.0.91a9ad7 → 0.6.3-dev-c35956d.0.c35956d
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/package.json +4 -4
- package/src/block-slog.js +157 -0
- package/src/context-aware-slog.js +7 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/telemetry",
|
|
3
|
-
"version": "0.6.3-dev-
|
|
3
|
+
"version": "0.6.3-dev-c35956d.0.c35956d",
|
|
4
4
|
"description": "Agoric's telemetry implementation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": "https://github.com/Agoric/agoric-sdk",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"author": "Agoric",
|
|
23
23
|
"license": "Apache-2.0",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@agoric/internal": "0.3.3-dev-
|
|
26
|
-
"@agoric/store": "0.9.3-dev-
|
|
25
|
+
"@agoric/internal": "0.3.3-dev-c35956d.0.c35956d",
|
|
26
|
+
"@agoric/store": "0.9.3-dev-c35956d.0.c35956d",
|
|
27
27
|
"@endo/errors": "^1.2.13",
|
|
28
28
|
"@endo/init": "^1.1.12",
|
|
29
29
|
"@endo/marshal": "^1.8.0",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"typeCoverage": {
|
|
71
71
|
"atLeast": 89.28
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "c35956dcf414e6cc7f24db886cb647f36cb1eb90"
|
|
74
74
|
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
|
|
3
|
+
import { open } from 'node:fs/promises';
|
|
4
|
+
import { createGzip } from 'node:zlib';
|
|
5
|
+
import { SLOG_TYPES } from './context-aware-slog.js';
|
|
6
|
+
import { serializeSlogObj } from './serialize-slog-obj.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @import {Slog} from '@agoric/telemetry/src/context-aware-slog.js';
|
|
10
|
+
* @import {MakeSlogSenderOptions} from '@agoric/telemetry/src/index.js';
|
|
11
|
+
* @import {WriteStream} from 'node:fs';
|
|
12
|
+
* @import {FileHandle} from 'node:fs/promises';
|
|
13
|
+
* @import {Gzip} from 'node:zlib';
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {MakeSlogSenderOptions} options
|
|
18
|
+
*/
|
|
19
|
+
export const makeSlogSender = async options => {
|
|
20
|
+
const { CONTEXTUAL_BLOCK_SLOGS } = options.env || {};
|
|
21
|
+
if (!(options.stateDir || CONTEXTUAL_BLOCK_SLOGS))
|
|
22
|
+
return console.error(
|
|
23
|
+
'Ignoring invocation of slogger "block-slog" without the presence of "stateDir" or "CONTEXTUAL_BLOCK_SLOGS"',
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
let chainedPromises = Promise.resolve();
|
|
27
|
+
/**
|
|
28
|
+
* @type {FileHandle | null}
|
|
29
|
+
*/
|
|
30
|
+
let currentFileHandle = null;
|
|
31
|
+
/**
|
|
32
|
+
* @type {WriteStream | null}
|
|
33
|
+
*/
|
|
34
|
+
let currentFileStream = null;
|
|
35
|
+
/**
|
|
36
|
+
* @type {Gzip | null}
|
|
37
|
+
*/
|
|
38
|
+
let currentStream = null;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {Array<() => Promise<void>>} promises
|
|
42
|
+
*/
|
|
43
|
+
const chainPromises = (...promises) => {
|
|
44
|
+
for (const promise of promises)
|
|
45
|
+
chainedPromises = chainedPromises.then(promise);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const closeStream = () =>
|
|
49
|
+
currentStream
|
|
50
|
+
? chainPromises(
|
|
51
|
+
() =>
|
|
52
|
+
new Promise(resolve =>
|
|
53
|
+
// @ts-expect-error
|
|
54
|
+
currentStream.end(() => currentStream.once('finish', resolve)),
|
|
55
|
+
),
|
|
56
|
+
() =>
|
|
57
|
+
// @ts-expect-error
|
|
58
|
+
new Promise(resolve => currentFileStream.once('finish', resolve)),
|
|
59
|
+
async () => {
|
|
60
|
+
currentStream = null;
|
|
61
|
+
currentFileStream = null;
|
|
62
|
+
currentFileHandle = null;
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
: console.error('No stream to close');
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {string} fileName
|
|
69
|
+
*/
|
|
70
|
+
const createStream = async fileName => {
|
|
71
|
+
if (currentStream) throw Error('Stream already open');
|
|
72
|
+
|
|
73
|
+
const filePath = `${options.stateDir || CONTEXTUAL_BLOCK_SLOGS}/slogfile_${fileName}.gz`;
|
|
74
|
+
currentFileHandle = await open(filePath, 'w');
|
|
75
|
+
currentFileStream = currentFileHandle.createWriteStream();
|
|
76
|
+
currentStream = createGzip();
|
|
77
|
+
currentStream.pipe(currentFileStream);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @param {Slog} slog
|
|
82
|
+
*/
|
|
83
|
+
const slogSender = slog => {
|
|
84
|
+
const { blockHeight, type: slogType } = slog;
|
|
85
|
+
|
|
86
|
+
switch (slogType) {
|
|
87
|
+
case SLOG_TYPES.KERNEL.INIT.START: {
|
|
88
|
+
chainPromises(() => createStream(`init_${new Date().getTime()}`));
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case SLOG_TYPES.COSMIC_SWINGSET.BOOTSTRAP_BLOCK.START: {
|
|
92
|
+
chainPromises(() => createStream(`bootstrap_${new Date().getTime()}`));
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case SLOG_TYPES.COSMIC_SWINGSET.UPGRADE.START: {
|
|
96
|
+
chainPromises(() => createStream(`upgrade_${new Date().getTime()}`));
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case SLOG_TYPES.COSMIC_SWINGSET.BEGIN_BLOCK: {
|
|
100
|
+
chainPromises(() =>
|
|
101
|
+
createStream(`block_${blockHeight}_${new Date().getTime()}`),
|
|
102
|
+
);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
default: {
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
chainPromises(() => writeSlogToStream(slog));
|
|
111
|
+
|
|
112
|
+
switch (slogType) {
|
|
113
|
+
case SLOG_TYPES.KERNEL.INIT.FINISH:
|
|
114
|
+
case SLOG_TYPES.COSMIC_SWINGSET.BOOTSTRAP_BLOCK.FINISH:
|
|
115
|
+
case SLOG_TYPES.COSMIC_SWINGSET.UPGRADE.FINISH:
|
|
116
|
+
case SLOG_TYPES.COSMIC_SWINGSET.AFTER_COMMIT_STATS: {
|
|
117
|
+
closeStream();
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
default: {
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @param {Slog} slog
|
|
128
|
+
* @returns {Promise<void>}
|
|
129
|
+
*/
|
|
130
|
+
const writeSlogToStream = slog =>
|
|
131
|
+
new Promise(resolve => {
|
|
132
|
+
if (!currentStream) {
|
|
133
|
+
console.error(`No stream available for slog type "${slog.type}"`);
|
|
134
|
+
resolve();
|
|
135
|
+
} else {
|
|
136
|
+
// eslint-disable-next-line prefer-template
|
|
137
|
+
const message = serializeSlogObj(slog) + '\n';
|
|
138
|
+
|
|
139
|
+
if (!currentStream.write(message)) currentStream.once('drain', resolve);
|
|
140
|
+
else resolve();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
return Object.assign(slogSender, {
|
|
145
|
+
forceFlush: () =>
|
|
146
|
+
chainedPromises.then(
|
|
147
|
+
() =>
|
|
148
|
+
/** @type {Promise<void>} */ (
|
|
149
|
+
new Promise(resolve => currentStream?.flush(resolve))
|
|
150
|
+
),
|
|
151
|
+
),
|
|
152
|
+
shutdown: async () => {
|
|
153
|
+
closeStream();
|
|
154
|
+
await chainedPromises;
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
};
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
* }} Slog
|
|
50
50
|
*/
|
|
51
51
|
|
|
52
|
-
const SLOG_TYPES = {
|
|
52
|
+
export const SLOG_TYPES = {
|
|
53
53
|
CLIST: 'clist',
|
|
54
54
|
CONSOLE: 'console',
|
|
55
55
|
COSMIC_SWINGSET: {
|
|
@@ -60,8 +60,8 @@ const SLOG_TYPES = {
|
|
|
60
60
|
START: 'cosmic-swingset-bootstrap-block-start',
|
|
61
61
|
},
|
|
62
62
|
COMMIT: {
|
|
63
|
-
FINISH: 'cosmic-swingset-commit-finish',
|
|
64
|
-
START: 'cosmic-swingset-commit-start',
|
|
63
|
+
FINISH: 'cosmic-swingset-commit-block-finish',
|
|
64
|
+
START: 'cosmic-swingset-commit-block-start',
|
|
65
65
|
},
|
|
66
66
|
END_BLOCK: {
|
|
67
67
|
FINISH: 'cosmic-swingset-end-block-finish',
|
|
@@ -72,6 +72,10 @@ const SLOG_TYPES = {
|
|
|
72
72
|
FINISH: 'cosmic-swingset-run-finish',
|
|
73
73
|
START: 'cosmic-swingset-run-start',
|
|
74
74
|
},
|
|
75
|
+
UPGRADE: {
|
|
76
|
+
FINISH: 'cosmic-swingset-upgrade-finish',
|
|
77
|
+
START: 'cosmic-swingset-upgrade-start',
|
|
78
|
+
},
|
|
75
79
|
},
|
|
76
80
|
COSMIC_SWINGSET_TRIGGERS: {
|
|
77
81
|
BRIDGE_INBOUND: 'cosmic-swingset-bridge-inbound',
|