@agoric/telemetry 0.6.3-other-dev-1f26562.0 → 0.6.3-other-dev-3eb1a1d.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.
@@ -1,24 +1,13 @@
1
+ // @ts-check
2
+ /* eslint-env node */
1
3
  /// <reference types="ses" />
2
4
 
3
- // https://github.com/Agoric/agoric-sdk/issues/3742#issuecomment-1028451575
4
- // I'd mmap() a 100MB file, reserve a few bytes for offsets, then use the rest
5
- // as a circular buffer to hold length-prefixed records. The agd process would
6
- // keep writing new events into the RAM window and updating the start/end
7
- // pointers, with some sequencing to make sure the record gets written before
8
- // the pointer is updated. Then, no mattter how abruptly the process is
9
- // terminated, as long as the host computer itself is still running, the on-disk
10
- // file would contain the most recent state, and anybody who reads the file will
11
- // get the most recent state. The host kernel (linux) is under no obligation to
12
- // flush it to disk any particular time, but knows when reads happen, so there's
13
- // no coherency problem, and the speed is unaffected by disk write speeds.
14
-
15
- import BufferFromFile from 'bufferfromfile';
16
- import { promises as fsPromises } from 'fs';
17
- import path from 'path';
5
+ import fs from 'node:fs';
6
+ import fsp from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { Fail } from '@endo/errors';
18
9
  import { serializeSlogObj } from './serialize-slog-obj.js';
19
10
 
20
- const { Fail } = assert;
21
-
22
11
  export const DEFAULT_CBUF_SIZE = 100 * 1024 * 1024;
23
12
  export const DEFAULT_CBUF_FILE = 'flight-recorder.bin';
24
13
  export const SLOG_MAGIC = 0x41472d534c4f4721n; // 'AG-SLOG!'
@@ -31,12 +20,16 @@ const I_ARENA_START = 4 * BigUint64Array.BYTES_PER_ELEMENT;
31
20
 
32
21
  const RECORD_HEADER_SIZE = BigUint64Array.BYTES_PER_ELEMENT;
33
22
 
23
+ /**
24
+ * Initializes a circular buffer with the given size, creating the buffer file if it doesn't exist or is not large enough.
25
+ *
26
+ * @param {string} bufferFile - the file path for the circular buffer
27
+ * @param {number} circularBufferSize - the size of the circular buffer
28
+ * @returns {Promise<bigint>} the size of the initialized circular buffer
29
+ */
34
30
  const initializeCircularBuffer = async (bufferFile, circularBufferSize) => {
35
- if (!circularBufferSize) {
36
- return undefined;
37
- }
38
31
  // If the file doesn't exist, or is not large enough, create it.
39
- const stbuf = await fsPromises.stat(bufferFile).catch(e => {
32
+ const stbuf = await fsp.stat(bufferFile).catch(e => {
40
33
  if (e.code === 'ENOENT') {
41
34
  return undefined;
42
35
  }
@@ -57,8 +50,8 @@ const initializeCircularBuffer = async (bufferFile, circularBufferSize) => {
57
50
  header.setBigUint64(I_CIRC_START, 0n);
58
51
  header.setBigUint64(I_CIRC_END, 0n);
59
52
 
60
- await fsPromises.mkdir(path.dirname(bufferFile), { recursive: true });
61
- await fsPromises.writeFile(bufferFile, headerBuf);
53
+ await fsp.mkdir(path.dirname(bufferFile), { recursive: true });
54
+ await fsp.writeFile(bufferFile, headerBuf);
62
55
 
63
56
  if (stbuf && stbuf.size >= circularBufferSize) {
64
57
  // File is big enough.
@@ -66,50 +59,20 @@ const initializeCircularBuffer = async (bufferFile, circularBufferSize) => {
66
59
  }
67
60
 
68
61
  // Increase the file size.
69
- await fsPromises.truncate(bufferFile, circularBufferSize);
62
+ await fsp.truncate(bufferFile, circularBufferSize);
70
63
  return arenaSize;
71
64
  };
72
65
 
73
- export const makeMemoryMappedCircularBuffer = async ({
74
- circularBufferSize = DEFAULT_CBUF_SIZE,
75
- stateDir = '/tmp',
76
- circularBufferFilename,
77
- }) => {
78
- const filename = circularBufferFilename || `${stateDir}/${DEFAULT_CBUF_FILE}`;
79
- // console.log({ circularBufferFilename, filename });
66
+ /** @typedef {Awaited<ReturnType<typeof makeSimpleCircularBuffer>>} CircularBuffer */
80
67
 
81
- const newArenaSize = await initializeCircularBuffer(
82
- filename,
83
- circularBufferSize,
84
- );
85
-
86
- /**
87
- * @type {Uint8Array}
88
- * BufferFromFile mmap()s the file into the process address space.
89
- */
90
- const fileBuf = BufferFromFile(filename).Uint8Array();
91
- const header = new DataView(fileBuf.buffer, 0, I_ARENA_START);
92
-
93
- // Detect the arena size from the header, if not initialized.
94
- const hdrArenaSize = header.getBigUint64(I_ARENA_SIZE);
95
- const arenaSize = newArenaSize || hdrArenaSize;
96
-
97
- const hdrMagic = header.getBigUint64(I_MAGIC);
98
- SLOG_MAGIC === hdrMagic ||
99
- Fail`${filename} is not a slog buffer; wanted magic ${SLOG_MAGIC}, got ${hdrMagic}`;
100
- arenaSize === hdrArenaSize ||
101
- Fail`${filename} arena size mismatch; wanted ${arenaSize}, got ${hdrArenaSize}`;
102
- const arena = new Uint8Array(
103
- fileBuf.buffer,
104
- header.byteLength,
105
- Number(arenaSize),
106
- );
107
-
108
- /**
109
- * @param {Uint8Array} outbuf
110
- * @param {number} [offset] offset relative to the current trailing edge (circStart) of the data
111
- * @returns {IteratorResult<Uint8Array, void>}
112
- */
68
+ /**
69
+ *
70
+ * @param {bigint} arenaSize
71
+ * @param {DataView} header
72
+ * @param {(outbuf: Uint8Array, readStart: number, firstReadLength: number) => void} readRecord
73
+ * @param {(record: Uint8Array, firstWriteLength: number, circEnd: bigint) => Promise<void>} writeRecord
74
+ */
75
+ function finishCircularBuffer(arenaSize, header, readRecord, writeRecord) {
113
76
  const readCircBuf = (outbuf, offset = 0) => {
114
77
  offset + outbuf.byteLength <= arenaSize ||
115
78
  Fail`Reading past end of circular buffer`;
@@ -132,19 +95,13 @@ export const makeMemoryMappedCircularBuffer = async ({
132
95
  // The data is contiguous, like ---AAABBB---
133
96
  return { done: true, value: undefined };
134
97
  }
135
- outbuf.set(arena.subarray(readStart, readStart + firstReadLength));
136
- if (firstReadLength < outbuf.byteLength) {
137
- outbuf.set(
138
- arena.subarray(0, outbuf.byteLength - firstReadLength),
139
- firstReadLength,
140
- );
141
- }
98
+ readRecord(outbuf, readStart, firstReadLength);
142
99
  return { done: false, value: outbuf };
143
100
  };
144
101
 
145
- /** @param {Uint8Array} data */
146
- const writeCircBuf = data => {
147
- if (RECORD_HEADER_SIZE + data.byteLength > arena.byteLength) {
102
+ /** @type {(data: Uint8Array) => Promise<void>} */
103
+ const writeCircBuf = async data => {
104
+ if (RECORD_HEADER_SIZE + data.byteLength > arenaSize) {
148
105
  // The data is too big to fit in the arena, so skip it.
149
106
  const tooBigRecord = JSON.stringify({
150
107
  type: 'slog-record-too-big',
@@ -153,14 +110,17 @@ export const makeMemoryMappedCircularBuffer = async ({
153
110
  data = new TextEncoder().encode(tooBigRecord);
154
111
  }
155
112
 
156
- if (RECORD_HEADER_SIZE + data.byteLength > arena.byteLength) {
113
+ if (RECORD_HEADER_SIZE + data.byteLength > arenaSize) {
157
114
  // Silently drop, it just doesn't fit.
158
115
  return;
159
116
  }
160
117
 
118
+ // Allocate for the data and a header
161
119
  const record = new Uint8Array(RECORD_HEADER_SIZE + data.byteLength);
120
+ // Set the data, after the header
162
121
  record.set(data, RECORD_HEADER_SIZE);
163
122
 
123
+ // Set the size in the header
164
124
  const lengthPrefix = new DataView(record.buffer);
165
125
  lengthPrefix.setBigUint64(0, BigInt(data.byteLength));
166
126
 
@@ -206,31 +166,135 @@ export const makeMemoryMappedCircularBuffer = async ({
206
166
  );
207
167
  }
208
168
 
209
- arena.set(record.subarray(0, firstWriteLength), Number(circEnd));
210
- if (firstWriteLength < record.byteLength) {
211
- // Write to the beginning of the arena.
212
- arena.set(record.subarray(firstWriteLength, record.byteLength), 0);
213
- }
214
169
  header.setBigUint64(
215
170
  I_CIRC_END,
216
171
  (circEnd + BigInt(record.byteLength)) % arenaSize,
217
172
  );
173
+
174
+ return writeRecord(record, firstWriteLength, circEnd);
218
175
  };
219
176
 
220
- const writeJSON = (obj, jsonObj = serializeSlogObj(obj)) => {
221
- // Prepend a newline so that the file can be more easily manipulated.
222
- const data = new TextEncoder().encode(`\n${jsonObj}`);
223
- // console.log('have obj', obj, data);
224
- writeCircBuf(data);
177
+ return { readCircBuf, writeCircBuf };
178
+ }
179
+
180
+ /**
181
+ * @param {{
182
+ * circularBufferSize?: number,
183
+ * stateDir?: string,
184
+ * circularBufferFilename?: string
185
+ * }} opts
186
+ */
187
+ export const makeSimpleCircularBuffer = async ({
188
+ circularBufferSize = DEFAULT_CBUF_SIZE,
189
+ stateDir = '/tmp',
190
+ circularBufferFilename,
191
+ }) => {
192
+ const filename = circularBufferFilename || `${stateDir}/${DEFAULT_CBUF_FILE}`;
193
+
194
+ const newArenaSize = await initializeCircularBuffer(
195
+ filename,
196
+ circularBufferSize,
197
+ );
198
+
199
+ const file = await fsp.open(filename, 'r+');
200
+
201
+ const headerBuffer = Buffer.alloc(I_ARENA_START);
202
+
203
+ await file.read({
204
+ buffer: headerBuffer,
205
+ length: I_ARENA_START,
206
+ position: 0,
207
+ });
208
+ const header = new DataView(headerBuffer.buffer);
209
+
210
+ // Detect the arena size from the header, if not initialized.
211
+ const hdrArenaSize = header.getBigUint64(I_ARENA_SIZE);
212
+ const arenaSize = newArenaSize || hdrArenaSize;
213
+
214
+ const hdrMagic = header.getBigUint64(I_MAGIC);
215
+ SLOG_MAGIC === hdrMagic ||
216
+ Fail`${filename} is not a slog buffer; wanted magic ${SLOG_MAGIC}, got ${hdrMagic}`;
217
+ arenaSize === hdrArenaSize ||
218
+ Fail`${filename} arena size mismatch; wanted ${arenaSize}, got ${hdrArenaSize}`;
219
+
220
+ /** @type {(outbuf: Uint8Array, readStart: number, firstReadLength: number) => void} */
221
+ const readRecord = (outbuf, readStart, firstReadLength) => {
222
+ const bytesRead = fs.readSync(file.fd, outbuf, {
223
+ length: firstReadLength,
224
+ position: Number(readStart) + I_ARENA_START,
225
+ });
226
+ assert.equal(bytesRead, firstReadLength, 'Too few bytes read');
227
+
228
+ if (bytesRead < outbuf.byteLength) {
229
+ fs.readSync(file.fd, outbuf, {
230
+ offset: firstReadLength,
231
+ length: outbuf.byteLength - firstReadLength,
232
+ position: I_ARENA_START,
233
+ });
234
+ }
235
+ };
236
+
237
+ /**
238
+ * Writes to the file, offset by the header size. Also updates the file header.
239
+ *
240
+ * @param {Uint8Array} record
241
+ * @param {number} firstWriteLength
242
+ * @param {bigint} circEnd
243
+ */
244
+ const writeRecord = async (record, firstWriteLength, circEnd) => {
245
+ await file.write(
246
+ record,
247
+ // TS saying options bag not available
248
+ 0,
249
+ firstWriteLength,
250
+ I_ARENA_START + Number(circEnd),
251
+ );
252
+ if (firstWriteLength < record.byteLength) {
253
+ // Write to the beginning of the arena.
254
+ await file.write(
255
+ record,
256
+ firstWriteLength,
257
+ record.byteLength - firstWriteLength,
258
+ I_ARENA_START,
259
+ );
260
+ }
261
+
262
+ // Write out the updated file header.
263
+ // This is somewhat independent of writing the record itself, but it needs
264
+ // updating each time a record is written.
265
+ await file.write(headerBuffer, undefined, undefined, 0);
225
266
  };
226
267
 
227
- return { readCircBuf, writeCircBuf, writeJSON };
268
+ return finishCircularBuffer(arenaSize, header, readRecord, writeRecord);
228
269
  };
229
270
 
230
- export const makeSlogSender = async opts => {
231
- const { writeJSON } = await makeMemoryMappedCircularBuffer(opts);
271
+ /**
272
+ *
273
+ * @param {Pick<Awaited<ReturnType<typeof makeSimpleCircularBuffer>>, 'writeCircBuf'>} circBuf
274
+ */
275
+ export const makeSlogSenderFromBuffer = ({ writeCircBuf }) => {
276
+ /** @type {Promise<void>} */
277
+ let toWrite = Promise.resolve();
278
+ const writeJSON = (obj, serialized = serializeSlogObj(obj)) => {
279
+ // Prepend a newline so that the file can be more easily manipulated.
280
+ const data = new TextEncoder().encode(`\n${serialized}`);
281
+ // console.log('have obj', obj, data);
282
+ toWrite = toWrite.then(() => writeCircBuf(data));
283
+ };
232
284
  return Object.assign(writeJSON, {
233
- forceFlush: async () => {},
285
+ forceFlush: async () => {
286
+ await toWrite;
287
+ },
234
288
  usesJsonObject: true,
235
289
  });
236
290
  };
291
+
292
+ /**
293
+ * Loaded dynamically by makeSlogSender()
294
+ *
295
+ * @type {import('./index.js').MakeSlogSender}
296
+ */
297
+ export const makeSlogSender = async opts => {
298
+ const { writeCircBuf } = await makeSimpleCircularBuffer(opts);
299
+ return makeSlogSenderFromBuffer({ writeCircBuf });
300
+ };
@@ -1,11 +1,11 @@
1
1
  #! /usr/bin/env node
2
- /* global process */
2
+ /* eslint-env node */
3
3
  // frcat - print out the contents of a flight recorder
4
4
  // NOTE: this only works on inactive recorder files where the writer has terminated
5
5
 
6
6
  import '@endo/init';
7
7
 
8
- import { makeMemoryMappedCircularBuffer } from './flight-recorder.js';
8
+ import { makeSimpleCircularBuffer } from './flight-recorder.js';
9
9
 
10
10
  const main = async () => {
11
11
  const files = process.argv.slice(2);
@@ -14,8 +14,7 @@ const main = async () => {
14
14
  }
15
15
 
16
16
  for await (const file of files) {
17
- // eslint-disable-next-line @jessie.js/no-nested-await
18
- const { readCircBuf } = await makeMemoryMappedCircularBuffer({
17
+ const { readCircBuf } = await makeSimpleCircularBuffer({
19
18
  circularBufferFilename: file,
20
19
  circularBufferSize: 0,
21
20
  });
@@ -50,13 +49,18 @@ const main = async () => {
50
49
  }
51
50
 
52
51
  // If the buffer is full, wait for stdout to drain.
53
- // eslint-disable-next-line no-await-in-loop, @jessie.js/no-nested-await
54
52
  await new Promise(resolve => process.stdout.once('drain', resolve));
55
53
  }
56
54
  }
57
55
  };
58
56
 
59
- main().catch(err => {
60
- console.error(err);
61
- process.exitCode = 1;
62
- });
57
+ process.exitCode = 1;
58
+ main().then(
59
+ () => {
60
+ process.exitCode = 0;
61
+ },
62
+ err => {
63
+ console.error('Failed with', err);
64
+ process.exit(process.exitCode || 1);
65
+ },
66
+ );
package/src/index.js CHANGED
@@ -13,6 +13,9 @@ export * from './make-slog-sender.js';
13
13
  * shutdown?: () => Promise<void>;
14
14
  * }} SlogSender
15
15
  */
16
+ /**
17
+ * @typedef {(opts: import('./index.js').MakeSlogSenderOptions) => SlogSender | undefined} MakeSlogSender
18
+ */
16
19
  /**
17
20
  * @typedef {MakeSlogSenderCommonOptions & Record<string, unknown>} MakeSlogSenderOptions
18
21
  * @typedef {object} MakeSlogSenderCommonOptions
@@ -34,9 +37,9 @@ export const tryFlushSlogSender = async (
34
37
  await Promise.resolve(slogSender?.forceFlush?.()).catch(err => {
35
38
  log?.('Failed to flush slog sender', err);
36
39
  if (err.errors) {
37
- err.errors.forEach(error => {
40
+ for (const error of err.errors) {
38
41
  log?.('nested error:', error);
39
- });
42
+ }
40
43
  }
41
44
  if (env.SLOGSENDER_FAIL_ON_ERROR) {
42
45
  throw err;
@@ -58,21 +61,20 @@ export const getResourceAttributes = ({
58
61
  SDK_REVISION;
59
62
  }
60
63
  if (!resourceAttributes[SemanticResourceAttributes.SERVICE_INSTANCE_ID]) {
61
- resourceAttributes[
62
- SemanticResourceAttributes.SERVICE_INSTANCE_ID
63
- ] = `${Math.random()}`;
64
+ resourceAttributes[SemanticResourceAttributes.SERVICE_INSTANCE_ID] =
65
+ `${Math.random()}`;
64
66
  }
65
67
  if (serviceName) {
66
68
  resourceAttributes[SemanticResourceAttributes.SERVICE_NAME] = serviceName;
67
69
  }
68
70
  if (OTEL_RESOURCE_ATTRIBUTES) {
69
71
  // Allow overriding resource attributes.
70
- OTEL_RESOURCE_ATTRIBUTES.split(',').forEach(kv => {
72
+ for (const kv of OTEL_RESOURCE_ATTRIBUTES.split(',')) {
71
73
  const match = kv.match(/^([^=]*)=(.*)$/);
72
74
  if (match) {
73
75
  resourceAttributes[match[1]] = match[2];
74
76
  }
75
- });
77
+ }
76
78
  }
77
79
  return resourceAttributes;
78
80
  };
@@ -1,5 +1,5 @@
1
1
  #! /usr/bin/env node
2
- /* global setTimeout */
2
+ /* eslint-env node */
3
3
  import '@endo/init';
4
4
 
5
5
  import fs from 'fs';
@@ -11,7 +11,8 @@ import { makeSlogSender } from './make-slog-sender.js';
11
11
 
12
12
  const LINE_COUNT_TO_FLUSH = 10000;
13
13
  const ELAPSED_MS_TO_FLUSH = 3000;
14
- const MAX_LINE_COUNT_PER_PERIOD = 1000;
14
+ const MAX_LINE_COUNT_PER_PERIOD = 10000;
15
+ const MAX_BLOCKS_PER_PERIOD = 10;
15
16
  const PROCESSING_PERIOD = 1000;
16
17
 
17
18
  async function run() {
@@ -29,7 +30,7 @@ async function run() {
29
30
  return;
30
31
  }
31
32
 
32
- const [slogFile] = args;
33
+ const slogFile = args[0] === '-' ? undefined : args[0];
33
34
  const slogSender = await makeSlogSender({
34
35
  serviceName,
35
36
  stateDir: '.',
@@ -56,14 +57,21 @@ async function run() {
56
57
  const lines = readline.createInterface({ input: slogF });
57
58
  const slogFileName = slogFile || '*stdin*';
58
59
 
59
- const progressFileName = `${slogFileName}.ingest-progress`;
60
- if (!fs.existsSync(progressFileName)) {
61
- const progress = { virtualTimeOffset: 0, lastSlogTime: 0 };
62
- fs.writeFileSync(progressFileName, JSON.stringify(progress));
60
+ const progressFileName = slogFile && `${slogFileName}.ingest-progress`;
61
+ const progress = { virtualTimeOffset: 0, lastSlogTime: 0 };
62
+ if (progressFileName) {
63
+ if (!fs.existsSync(progressFileName)) {
64
+ fs.writeFileSync(progressFileName, JSON.stringify(progress));
65
+ } else {
66
+ Object.assign(
67
+ progress,
68
+ JSON.parse(fs.readFileSync(progressFileName).toString()),
69
+ );
70
+ }
63
71
  }
64
- const progress = JSON.parse(fs.readFileSync(progressFileName).toString());
65
72
 
66
73
  let linesProcessedThisPeriod = 0;
74
+ let blocksInThisPeriod = 0;
67
75
  let startOfLastPeriod = 0;
68
76
 
69
77
  let lastTime = Date.now();
@@ -74,11 +82,13 @@ async function run() {
74
82
  if (!flush) {
75
83
  return;
76
84
  }
77
- await slogSender.forceFlush();
78
- fs.writeFileSync(progressFileName, JSON.stringify(progress));
85
+ await slogSender.forceFlush?.();
86
+ if (progressFileName) {
87
+ fs.writeFileSync(progressFileName, JSON.stringify(progress));
88
+ }
79
89
  };
80
90
 
81
- console.log(`parsing`, slogFileName);
91
+ console.warn(`parsing`, slogFileName);
82
92
 
83
93
  let update = false;
84
94
  const maybeUpdateStats = async now => {
@@ -106,9 +116,14 @@ async function run() {
106
116
  continue;
107
117
  }
108
118
 
119
+ const isAfterCommit = obj.type === 'cosmic-swingset-after-commit-stats';
120
+
109
121
  // Maybe wait for the next period to process a bunch of lines.
110
122
  let maybeWait;
111
- if (linesProcessedThisPeriod >= MAX_LINE_COUNT_PER_PERIOD) {
123
+ if (
124
+ linesProcessedThisPeriod >= MAX_LINE_COUNT_PER_PERIOD ||
125
+ blocksInThisPeriod >= MAX_BLOCKS_PER_PERIOD
126
+ ) {
112
127
  const delayMS = PROCESSING_PERIOD - (now - startOfLastPeriod);
113
128
  maybeWait = new Promise(resolve => setTimeout(resolve, delayMS));
114
129
  }
@@ -118,8 +133,8 @@ async function run() {
118
133
  if (now - startOfLastPeriod >= PROCESSING_PERIOD) {
119
134
  startOfLastPeriod = now;
120
135
  linesProcessedThisPeriod = 0;
136
+ blocksInThisPeriod = 0;
121
137
  }
122
- linesProcessedThisPeriod += 1;
123
138
 
124
139
  if (progress.virtualTimeOffset) {
125
140
  const virtualTime = obj.time + progress.virtualTimeOffset;
@@ -133,14 +148,30 @@ async function run() {
133
148
  // Use the original.
134
149
  slogSender(obj);
135
150
  }
151
+
152
+ linesProcessedThisPeriod += 1;
153
+ if (isAfterCommit) {
154
+ blocksInThisPeriod += 1;
155
+ lastTime = Date.now();
156
+ await stats(true);
157
+ }
136
158
  }
137
159
 
138
160
  await stats(true);
139
- console.log(
161
+ console.warn(
140
162
  `done parsing`,
141
163
  slogFileName,
142
164
  `(${lineCount} lines, ${byteCount} bytes)`,
143
165
  );
144
166
  }
145
167
 
146
- run().catch(err => console.log('err', err));
168
+ process.exitCode = 1;
169
+ run().then(
170
+ () => {
171
+ process.exitCode = 0;
172
+ },
173
+ err => {
174
+ console.error('Failed with', err);
175
+ process.exit(process.exitCode || 1);
176
+ },
177
+ );
@@ -9,7 +9,7 @@ export const SLOGFILE_SENDER_MODULE = '@agoric/telemetry/src/slog-file.js';
9
9
 
10
10
  export const DEFAULT_SLOGSENDER_AGENT = 'self';
11
11
 
12
- /** @typedef {import('./index.js').SlogSender} SlogSender */
12
+ /** @import {SlogSender} from './index.js' */
13
13
 
14
14
  /**
15
15
  * @template T
@@ -19,7 +19,7 @@ export const DEFAULT_SLOGSENDER_AGENT = 'self';
19
19
  const filterTruthy = arr => /** @type {any[]} */ (arr.filter(Boolean));
20
20
 
21
21
  /**
22
- * @param {import('./index.js').MakeSlogSenderOptions} opts
22
+ * @type {import('./index.js').MakeSlogSender}
23
23
  */
24
24
  export const makeSlogSender = async (opts = {}) => {
25
25
  const { env = {}, stateDir: stateDirOption, ...otherOpts } = opts;
@@ -88,7 +88,7 @@ export const makeSlogSender = async (opts = {}) => {
88
88
  slogSenderModules.map(async moduleIdentifier =>
89
89
  import(moduleIdentifier)
90
90
  .then(
91
- /** @param {{makeSlogSender: (opts: {}) => Promise<SlogSender | undefined>}} module */ ({
91
+ /** @param {{makeSlogSender: import('./index.js').MakeSlogSender}} module */ ({
92
92
  makeSlogSender: maker,
93
93
  }) => {
94
94
  if (typeof maker !== 'function') {
@@ -1,6 +1,9 @@
1
- import { NonNullish } from '@agoric/assert';
1
+ import { NonNullish } from '@agoric/internal';
2
2
  import { makeSlogSender as makeSlogSenderFromEnv } from './make-slog-sender.js';
3
3
 
4
+ /**
5
+ * @param {import('./index.js').MakeSlogSenderOptions} opts
6
+ */
4
7
  export const makeSlogSender = async opts => {
5
8
  const { SLOGFILE: _1, SLOGSENDER: _2, ...otherEnv } = opts.env || {};
6
9