@agoric/internal 0.4.0-u19.2 → 0.4.0-u20.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/package.json +19 -16
- package/src/config.d.ts +2 -4
- package/src/config.js +4 -2
- package/src/hex.d.ts +15 -0
- package/src/hex.d.ts.map +1 -0
- package/src/hex.js +105 -0
- package/src/index.d.ts +2 -3
- package/src/index.js +2 -4
- package/src/js-utils.d.ts +29 -4
- package/src/js-utils.d.ts.map +1 -1
- package/src/js-utils.js +144 -23
- package/src/metrics.d.ts +183 -0
- package/src/metrics.d.ts.map +1 -0
- package/src/metrics.js +476 -0
- package/src/module-utils.d.ts +2 -0
- package/src/module-utils.d.ts.map +1 -0
- package/src/module-utils.js +27 -0
- package/src/ses-utils.d.ts +7 -0
- package/src/ses-utils.d.ts.map +1 -1
- package/src/ses-utils.js +66 -2
- package/src/tmpDir.d.ts +2 -0
- package/src/tmpDir.d.ts.map +1 -0
- package/src/tmpDir.js +17 -0
- package/src/types.d.ts +12 -0
- package/src/types.d.ts.map +1 -1
- package/src/types.ts +21 -0
package/src/metrics.d.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export namespace HISTOGRAM_METRICS {
|
|
2
|
+
namespace swingset_crank_processing_time {
|
|
3
|
+
let description: "Processing time per crank (ms)";
|
|
4
|
+
let unit: "ms";
|
|
5
|
+
let boundaries: number[];
|
|
6
|
+
}
|
|
7
|
+
namespace swingset_block_processing_seconds {
|
|
8
|
+
let description_1: "Processing time per block";
|
|
9
|
+
export { description_1 as description };
|
|
10
|
+
let unit_1: "s";
|
|
11
|
+
export { unit_1 as unit };
|
|
12
|
+
export { HISTOGRAM_SECONDS_LATENCY_BOUNDARIES as boundaries };
|
|
13
|
+
}
|
|
14
|
+
namespace swingset_vat_startup {
|
|
15
|
+
let description_2: "Vat startup time (ms)";
|
|
16
|
+
export { description_2 as description };
|
|
17
|
+
let unit_2: "ms";
|
|
18
|
+
export { unit_2 as unit };
|
|
19
|
+
export { HISTOGRAM_MS_LATENCY_BOUNDARIES as boundaries };
|
|
20
|
+
}
|
|
21
|
+
namespace swingset_vat_delivery {
|
|
22
|
+
let description_3: "Vat delivery time (ms)";
|
|
23
|
+
export { description_3 as description };
|
|
24
|
+
let unit_3: "ms";
|
|
25
|
+
export { unit_3 as unit };
|
|
26
|
+
export { HISTOGRAM_MS_LATENCY_BOUNDARIES as boundaries };
|
|
27
|
+
}
|
|
28
|
+
namespace swingset_meter_usage {
|
|
29
|
+
let description_4: "Vat meter usage";
|
|
30
|
+
export { description_4 as description };
|
|
31
|
+
let unit_4: "ms";
|
|
32
|
+
export { unit_4 as unit };
|
|
33
|
+
export { HISTOGRAM_MS_LATENCY_BOUNDARIES as boundaries };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export namespace BLOCK_HISTOGRAM_METRICS {
|
|
37
|
+
namespace swingsetRunSeconds {
|
|
38
|
+
let unit_5: string;
|
|
39
|
+
export { unit_5 as unit };
|
|
40
|
+
export namespace advice {
|
|
41
|
+
let explicitBucketBoundaries: number[];
|
|
42
|
+
}
|
|
43
|
+
let description_5: "Per-block time spent executing SwingSet";
|
|
44
|
+
export { description_5 as description };
|
|
45
|
+
}
|
|
46
|
+
namespace swingsetChainSaveSeconds {
|
|
47
|
+
let unit_6: string;
|
|
48
|
+
export { unit_6 as unit };
|
|
49
|
+
export namespace advice_1 { }
|
|
50
|
+
export { advice_1 as advice };
|
|
51
|
+
let description_6: "Per-block time spent propagating SwingSet state into cosmos";
|
|
52
|
+
export { description_6 as description };
|
|
53
|
+
}
|
|
54
|
+
namespace swingsetCommitSeconds {
|
|
55
|
+
let unit_7: string;
|
|
56
|
+
export { unit_7 as unit };
|
|
57
|
+
export namespace advice_2 { }
|
|
58
|
+
export { advice_2 as advice };
|
|
59
|
+
let description_7: "Per-block time spent committing SwingSet state to host storage";
|
|
60
|
+
export { description_7 as description };
|
|
61
|
+
}
|
|
62
|
+
namespace cosmosCommitSeconds {
|
|
63
|
+
let unit_8: string;
|
|
64
|
+
export { unit_8 as unit };
|
|
65
|
+
export namespace advice_3 { }
|
|
66
|
+
export { advice_3 as advice };
|
|
67
|
+
let description_8: "Per-block time spent committing cosmos state";
|
|
68
|
+
export { description_8 as description };
|
|
69
|
+
}
|
|
70
|
+
namespace fullCommitSeconds {
|
|
71
|
+
let unit_9: string;
|
|
72
|
+
export { unit_9 as unit };
|
|
73
|
+
export namespace advice_4 { }
|
|
74
|
+
export { advice_4 as advice };
|
|
75
|
+
let description_9: "Per-block time spent committing state, inclusive of COMMIT_BLOCK processing plus time spent [outside of cosmic-swingset] before and after it";
|
|
76
|
+
export { description_9 as description };
|
|
77
|
+
}
|
|
78
|
+
namespace interBlockSeconds {
|
|
79
|
+
let unit_10: string;
|
|
80
|
+
export { unit_10 as unit };
|
|
81
|
+
export namespace advice_5 { }
|
|
82
|
+
export { advice_5 as advice };
|
|
83
|
+
let description_10: "Time spent idle between blocks";
|
|
84
|
+
export { description_10 as description };
|
|
85
|
+
}
|
|
86
|
+
namespace afterCommitHangoverSeconds {
|
|
87
|
+
let unit_11: string;
|
|
88
|
+
export { unit_11 as unit };
|
|
89
|
+
export namespace advice_6 { }
|
|
90
|
+
export { advice_6 as advice };
|
|
91
|
+
let description_11: "Per-block time spent waiting for previous-block afterCommit work";
|
|
92
|
+
export { description_11 as description };
|
|
93
|
+
}
|
|
94
|
+
namespace blockLagSeconds {
|
|
95
|
+
export namespace advice_7 {
|
|
96
|
+
let explicitBucketBoundaries_1: number[];
|
|
97
|
+
export { explicitBucketBoundaries_1 as explicitBucketBoundaries };
|
|
98
|
+
}
|
|
99
|
+
export { advice_7 as advice };
|
|
100
|
+
let unit_12: string;
|
|
101
|
+
export { unit_12 as unit };
|
|
102
|
+
let description_12: "The delay of each block from its expected begin time";
|
|
103
|
+
export { description_12 as description };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export type QueueMetricAspect = (typeof QueueMetricAspect)[keyof typeof QueueMetricAspect];
|
|
107
|
+
export namespace QueueMetricAspect {
|
|
108
|
+
let Length: "length";
|
|
109
|
+
let IncrementCount: "increments";
|
|
110
|
+
let DecrementCount: "decrements";
|
|
111
|
+
}
|
|
112
|
+
export function makeQueueMetricsMeta(namePrefix: string, descPrefix: string): Record<QueueMetricAspect, {
|
|
113
|
+
name: string;
|
|
114
|
+
options: MetricAttributes;
|
|
115
|
+
}>;
|
|
116
|
+
export function makeQueueMetrics<QueueName extends string>({ otelMeter, namePrefix, descPrefix, console, }: {
|
|
117
|
+
otelMeter: OTelMeter;
|
|
118
|
+
namePrefix: string;
|
|
119
|
+
descPrefix: string;
|
|
120
|
+
console?: Pick<Console, "warn"> | undefined;
|
|
121
|
+
}): QueueMetrics<QueueName>;
|
|
122
|
+
/**
|
|
123
|
+
* @typedef KernelMetricMeta
|
|
124
|
+
* @property {string} key
|
|
125
|
+
* @property {string} name
|
|
126
|
+
* @property {{ dimension: string; value: string }} [sub]
|
|
127
|
+
* @property {string} description
|
|
128
|
+
* @property {boolean} [consensus]
|
|
129
|
+
* @property {MetricType} metricType
|
|
130
|
+
*/
|
|
131
|
+
/** @type {Omit<KernelMetricMeta, 'metricType'>[]} */
|
|
132
|
+
export const KERNEL_STATS_SUM_METRICS: Omit<KernelMetricMeta, "metricType">[];
|
|
133
|
+
/** @type {Omit<KernelMetricMeta, 'metricType'>[]} */
|
|
134
|
+
export const KERNEL_STATS_UPDOWN_METRICS: Omit<KernelMetricMeta, "metricType">[];
|
|
135
|
+
/** @type {KernelMetricMeta[]} */
|
|
136
|
+
export const KERNEL_STATS_METRICS: KernelMetricMeta[];
|
|
137
|
+
export type QueueMetrics<QueueName extends string> = {
|
|
138
|
+
/**
|
|
139
|
+
* must be
|
|
140
|
+
* called before any other function
|
|
141
|
+
*/
|
|
142
|
+
initLengths: (lengths: Record<QueueName, number>) => void;
|
|
143
|
+
updateLengths: (lengths: Record<QueueName, number>) => void;
|
|
144
|
+
/**
|
|
145
|
+
* for a
|
|
146
|
+
* non-negative delta
|
|
147
|
+
*/
|
|
148
|
+
incLength: (queue: QueueName, delta?: number) => void;
|
|
149
|
+
/**
|
|
150
|
+
* for a
|
|
151
|
+
* non-negative delta
|
|
152
|
+
*/
|
|
153
|
+
decLength: (queue: QueueName, delta?: number) => void;
|
|
154
|
+
};
|
|
155
|
+
export type KernelMetricMeta = {
|
|
156
|
+
key: string;
|
|
157
|
+
name: string;
|
|
158
|
+
sub?: {
|
|
159
|
+
dimension: string;
|
|
160
|
+
value: string;
|
|
161
|
+
} | undefined;
|
|
162
|
+
description: string;
|
|
163
|
+
consensus?: boolean | undefined;
|
|
164
|
+
metricType: MetricType;
|
|
165
|
+
};
|
|
166
|
+
declare const HISTOGRAM_SECONDS_LATENCY_BOUNDARIES: number[];
|
|
167
|
+
/**
|
|
168
|
+
* @import {Meter as OTelMeter, MetricAttributes} from '@opentelemetry/api';
|
|
169
|
+
* @import {TotalMap} from '@agoric/internal';
|
|
170
|
+
*/
|
|
171
|
+
declare const HISTOGRAM_MS_LATENCY_BOUNDARIES: number[];
|
|
172
|
+
import type { MetricAttributes } from '@opentelemetry/api';
|
|
173
|
+
import type { Meter as OTelMeter } from '@opentelemetry/api';
|
|
174
|
+
/**
|
|
175
|
+
* MetricType
|
|
176
|
+
*/
|
|
177
|
+
type MetricType = (typeof MetricType)[keyof typeof MetricType];
|
|
178
|
+
declare namespace MetricType {
|
|
179
|
+
let Counter: "counter";
|
|
180
|
+
let Gauge: "gauge";
|
|
181
|
+
}
|
|
182
|
+
export {};
|
|
183
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["metrics.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4CAqH2C,MAAM,EAAE;;;;;;;;;;gCAQxC,CAAC,OAAO,iBAAiB,EAAE,MAAM,OAAO,iBAAiB,CAAC;;;;;;AAiB9D,iDAPI,MAAM,cACN,MAAM,GACJ,MAAM,CACd,iBAAiB,EACrB;IAAM,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAC5C,CAoBH;AA0BM,iCARe,SAAS,SAAlB,MAAQ,mDAElB;IAA0B,SAAS,EAA3B,SAAS;IACM,UAAU,EAAzB,MAAM;IACS,UAAU,EAAzB,MAAM;IACyB,OAAO;CAC9C,GAAU,YAAY,CAAC,SAAS,CAAC,CA8GnC;AAQD;;;;;;;;GAQG;AACH,qDAAqD;AACrD,uCADW,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAAE,CAkF/C;AAEF,qDAAqD;AACrD,0CADW,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,EAAE,CA4D/C;AAGF,iCAAiC;AACjC,mCADW,gBAAgB,EAAE,CAI1B;yBA3SmB,SAAS,SAAlB,MAAQ;;;;;iBAEP,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,IAAI;mBAE5C,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,IAAI;;;;;eAC5C,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI;;;;;eAE1C,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,IAAI;;;SAsI1C,MAAM;UACN,MAAM;;mBACO,MAAM;eAAS,MAAM;;iBAClC,MAAM;;gBAEN,UAAU;;AAnRxB,6DACuD;AApBvD;;;GAGG;AAEH,wDAaE;sCAjBqD,oBAAoB;wCAApB,oBAAoB;;;;kBAyRhE,CAAC,OAAO,UAAU,EAAE,MAAM,OAAO,UAAU,CAAC"}
|
package/src/metrics.js
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Metadata about exported metrics. Note that any embedded unit
|
|
3
|
+
* information should be provided as case-sensitive UCUM (e.g., `s` for
|
|
4
|
+
* seconds, `ms` for milliseconds, `KiBy` for binary kilobytes [each being
|
|
5
|
+
* 1024 bytes]).
|
|
6
|
+
*
|
|
7
|
+
* - https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/metrics.md#instrument-units
|
|
8
|
+
* - https://ucum.org/ucum
|
|
9
|
+
* - https://ucum.nlm.nih.gov/ucum-lhc/demo.html
|
|
10
|
+
* - https://en.wikipedia.org/wiki/Unified_Code_for_Units_of_Measure
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { q } from '@endo/errors';
|
|
14
|
+
import { isNat } from '@endo/nat';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @import {Meter as OTelMeter, MetricAttributes} from '@opentelemetry/api';
|
|
18
|
+
* @import {TotalMap} from '@agoric/internal';
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const HISTOGRAM_MS_LATENCY_BOUNDARIES = [
|
|
22
|
+
5,
|
|
23
|
+
10,
|
|
24
|
+
25,
|
|
25
|
+
50,
|
|
26
|
+
100,
|
|
27
|
+
250,
|
|
28
|
+
500,
|
|
29
|
+
1000,
|
|
30
|
+
2500,
|
|
31
|
+
5000,
|
|
32
|
+
10000,
|
|
33
|
+
Infinity,
|
|
34
|
+
];
|
|
35
|
+
const HISTOGRAM_SECONDS_LATENCY_BOUNDARIES =
|
|
36
|
+
HISTOGRAM_MS_LATENCY_BOUNDARIES.map(ms => ms / 1000);
|
|
37
|
+
|
|
38
|
+
// TODO: Validate these boundaries. We're not going to have 5ms blocks, but
|
|
39
|
+
// we probably care about the difference between 10 vs. 30 seconds.
|
|
40
|
+
export const HISTOGRAM_METRICS = /** @type {const} */ ({
|
|
41
|
+
swingset_crank_processing_time: {
|
|
42
|
+
description: 'Processing time per crank (ms)',
|
|
43
|
+
unit: 'ms',
|
|
44
|
+
boundaries: Array.of(1, 11, 21, 31, 41, 51, 61, 71, 81, 91, Infinity),
|
|
45
|
+
},
|
|
46
|
+
swingset_block_processing_seconds: {
|
|
47
|
+
description: 'Processing time per block',
|
|
48
|
+
unit: 's',
|
|
49
|
+
boundaries: HISTOGRAM_SECONDS_LATENCY_BOUNDARIES,
|
|
50
|
+
},
|
|
51
|
+
swingset_vat_startup: {
|
|
52
|
+
description: 'Vat startup time (ms)',
|
|
53
|
+
unit: 'ms',
|
|
54
|
+
boundaries: HISTOGRAM_MS_LATENCY_BOUNDARIES,
|
|
55
|
+
},
|
|
56
|
+
swingset_vat_delivery: {
|
|
57
|
+
description: 'Vat delivery time (ms)',
|
|
58
|
+
unit: 'ms',
|
|
59
|
+
boundaries: HISTOGRAM_MS_LATENCY_BOUNDARIES,
|
|
60
|
+
},
|
|
61
|
+
swingset_meter_usage: {
|
|
62
|
+
description: 'Vat meter usage',
|
|
63
|
+
unit: 'ms',
|
|
64
|
+
boundaries: HISTOGRAM_MS_LATENCY_BOUNDARIES,
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const blockHistogramMetricDesc = {
|
|
69
|
+
// Disabled because importing from @opentelemetry/api breaks kernel bundling.
|
|
70
|
+
// Thankfully, it's the default anyway:
|
|
71
|
+
// https://github.com/open-telemetry/opentelemetry-js/blob/f4dd2a1062f980cd344cfb172a515d00115df570/api/src/metrics/Metric.ts#L53-L57
|
|
72
|
+
// valueType: ValueType.DOUBLE,
|
|
73
|
+
unit: 's',
|
|
74
|
+
advice: {
|
|
75
|
+
explicitBucketBoundaries: [
|
|
76
|
+
0.1, 0.2, 0.3, 0.4, 0.5, 1, 2, 3, 4, 5, 6, 7, 10, 15, 30,
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
export const BLOCK_HISTOGRAM_METRICS = /** @type {const} */ ({
|
|
81
|
+
swingsetRunSeconds: {
|
|
82
|
+
description: 'Per-block time spent executing SwingSet',
|
|
83
|
+
...blockHistogramMetricDesc,
|
|
84
|
+
},
|
|
85
|
+
swingsetChainSaveSeconds: {
|
|
86
|
+
description: 'Per-block time spent propagating SwingSet state into cosmos',
|
|
87
|
+
...blockHistogramMetricDesc,
|
|
88
|
+
},
|
|
89
|
+
swingsetCommitSeconds: {
|
|
90
|
+
description:
|
|
91
|
+
'Per-block time spent committing SwingSet state to host storage',
|
|
92
|
+
...blockHistogramMetricDesc,
|
|
93
|
+
},
|
|
94
|
+
cosmosCommitSeconds: {
|
|
95
|
+
description: 'Per-block time spent committing cosmos state',
|
|
96
|
+
...blockHistogramMetricDesc,
|
|
97
|
+
},
|
|
98
|
+
fullCommitSeconds: {
|
|
99
|
+
description:
|
|
100
|
+
'Per-block time spent committing state, inclusive of COMMIT_BLOCK processing plus time spent [outside of cosmic-swingset] before and after it',
|
|
101
|
+
...blockHistogramMetricDesc,
|
|
102
|
+
},
|
|
103
|
+
interBlockSeconds: {
|
|
104
|
+
description: 'Time spent idle between blocks',
|
|
105
|
+
...blockHistogramMetricDesc,
|
|
106
|
+
},
|
|
107
|
+
afterCommitHangoverSeconds: {
|
|
108
|
+
description:
|
|
109
|
+
'Per-block time spent waiting for previous-block afterCommit work',
|
|
110
|
+
...blockHistogramMetricDesc,
|
|
111
|
+
},
|
|
112
|
+
blockLagSeconds: {
|
|
113
|
+
description: 'The delay of each block from its expected begin time',
|
|
114
|
+
...blockHistogramMetricDesc,
|
|
115
|
+
// Add buckets for excessively long delays.
|
|
116
|
+
advice: {
|
|
117
|
+
...blockHistogramMetricDesc.advice,
|
|
118
|
+
explicitBucketBoundaries: /** @type {number[]} */ ([
|
|
119
|
+
...blockHistogramMetricDesc.advice.explicitBucketBoundaries,
|
|
120
|
+
...[60, 120, 180, 240, 300, 600, 3600],
|
|
121
|
+
]),
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/** @enum {(typeof QueueMetricAspect)[keyof typeof QueueMetricAspect]} */
|
|
127
|
+
export const QueueMetricAspect = /** @type {const} */ ({
|
|
128
|
+
Length: 'length',
|
|
129
|
+
IncrementCount: 'increments',
|
|
130
|
+
DecrementCount: 'decrements',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Queue metrics come in {length,add,remove} triples sharing a common prefix.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} namePrefix
|
|
137
|
+
* @param {string} descPrefix
|
|
138
|
+
* @returns {Record<
|
|
139
|
+
* QueueMetricAspect,
|
|
140
|
+
* { name: string; options: MetricAttributes }
|
|
141
|
+
* >}
|
|
142
|
+
*/
|
|
143
|
+
export const makeQueueMetricsMeta = (namePrefix, descPrefix) => {
|
|
144
|
+
/** @type {[QueueMetricAspect, string, string][]} */
|
|
145
|
+
const metricsMeta = [
|
|
146
|
+
[QueueMetricAspect.Length, 'length', 'length'],
|
|
147
|
+
[QueueMetricAspect.IncrementCount, 'add', 'increments'],
|
|
148
|
+
[QueueMetricAspect.DecrementCount, 'remove', 'decrements'],
|
|
149
|
+
];
|
|
150
|
+
const entries = metricsMeta.map(([aspect, nameSuffix, descSuffix]) => {
|
|
151
|
+
const name = `${namePrefix}_${nameSuffix}`;
|
|
152
|
+
const description = `${descPrefix} ${descSuffix}`;
|
|
153
|
+
// Future OpenTelemetry SDKs should also support creating Instruments with
|
|
154
|
+
// attribute keys (such as the "queue" attribute for
|
|
155
|
+
// "cosmic_swingset_inbound_queue_{length,add,remove}" measurements):
|
|
156
|
+
// https://opentelemetry.io/docs/specs/otel/metrics/api/#instrument-advisory-parameter-attributes
|
|
157
|
+
// At that time, a new field will be added to this record.
|
|
158
|
+
return [aspect, { name, options: { description } }];
|
|
159
|
+
});
|
|
160
|
+
return Object.fromEntries(entries);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @template {string} QueueName
|
|
165
|
+
* @typedef QueueMetrics
|
|
166
|
+
* @property {(lengths: Record<QueueName, number>) => void} initLengths must be
|
|
167
|
+
* called before any other function
|
|
168
|
+
* @property {(lengths: Record<QueueName, number>) => void} updateLengths
|
|
169
|
+
* @property {(queue: QueueName, delta?: number) => void} incLength for a
|
|
170
|
+
* non-negative delta
|
|
171
|
+
* @property {(queue: QueueName, delta?: number) => void} decLength for a
|
|
172
|
+
* non-negative delta
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Create {length,add,remove} Instruments for a queue and return functions for
|
|
177
|
+
* consistently initializing and updating them.
|
|
178
|
+
*
|
|
179
|
+
* @template {string} QueueName
|
|
180
|
+
* @param {object} config
|
|
181
|
+
* @param {OTelMeter} config.otelMeter
|
|
182
|
+
* @param {string} config.namePrefix
|
|
183
|
+
* @param {string} config.descPrefix
|
|
184
|
+
* @param {Pick<Console, 'warn'>} [config.console]
|
|
185
|
+
* @returns {QueueMetrics<QueueName>}
|
|
186
|
+
*/
|
|
187
|
+
export const makeQueueMetrics = ({
|
|
188
|
+
otelMeter,
|
|
189
|
+
namePrefix,
|
|
190
|
+
descPrefix,
|
|
191
|
+
console,
|
|
192
|
+
}) => {
|
|
193
|
+
const {
|
|
194
|
+
[QueueMetricAspect.Length]: lengthMeta,
|
|
195
|
+
[QueueMetricAspect.IncrementCount]: upMeta,
|
|
196
|
+
[QueueMetricAspect.DecrementCount]: downMeta,
|
|
197
|
+
} = makeQueueMetricsMeta(namePrefix, descPrefix);
|
|
198
|
+
// TODO: When it's deemed safe to change reported metrics, make upCounter and
|
|
199
|
+
// downCounter synchronous (and drop `increments` and `decrements` maps).
|
|
200
|
+
// We can't do so until then because it will add a "_total" suffix to the
|
|
201
|
+
// Prometheus export metric name, diverging from `makeInboundQueueMetrics` in
|
|
202
|
+
// packages/cosmic-swingset/src/kernel-stats.js.
|
|
203
|
+
// https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/upgrade-to-2.x.md#-other-changes
|
|
204
|
+
const lengthCounter = otelMeter.createUpDownCounter(
|
|
205
|
+
lengthMeta.name,
|
|
206
|
+
lengthMeta.options,
|
|
207
|
+
);
|
|
208
|
+
// const upCounter = otelMeter.createCounter(upMeta.name, upMeta.options);
|
|
209
|
+
// const downCounter = otelMeter.createCounter(downMeta.name, downMeta.options);
|
|
210
|
+
const upCounter = otelMeter.createObservableCounter(
|
|
211
|
+
upMeta.name,
|
|
212
|
+
upMeta.options,
|
|
213
|
+
);
|
|
214
|
+
const downCounter = otelMeter.createObservableCounter(
|
|
215
|
+
downMeta.name,
|
|
216
|
+
downMeta.options,
|
|
217
|
+
);
|
|
218
|
+
const increments = /** @type {TotalMap<string, number>} */ (new Map());
|
|
219
|
+
const decrements = /** @type {TotalMap<string, number>} */ (new Map());
|
|
220
|
+
upCounter.addCallback(observer => {
|
|
221
|
+
for (const [queueName, value] of increments.entries()) {
|
|
222
|
+
observer.observe(value, { queue: queueName });
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
downCounter.addCallback(observer => {
|
|
226
|
+
for (const [queueName, value] of decrements.entries()) {
|
|
227
|
+
observer.observe(value, { queue: queueName });
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
let ready = false;
|
|
232
|
+
const lengths = /** @type {TotalMap<string, number>} */ (new Map());
|
|
233
|
+
const nudge = (queueName, delta, init = false) => {
|
|
234
|
+
if (!lengths.has(queueName)) {
|
|
235
|
+
if (!init) console?.warn('Unknown queue', queueName);
|
|
236
|
+
lengths.set(queueName, 0);
|
|
237
|
+
increments.set(queueName, 0);
|
|
238
|
+
decrements.set(queueName, 0);
|
|
239
|
+
}
|
|
240
|
+
const oldLength = lengths.get(queueName);
|
|
241
|
+
lengths.set(queueName, oldLength + delta);
|
|
242
|
+
const dimensions = { queue: queueName };
|
|
243
|
+
lengthCounter.add(delta, dimensions);
|
|
244
|
+
if (init) {
|
|
245
|
+
return;
|
|
246
|
+
} else if (delta > 0) {
|
|
247
|
+
// TODO per above: upCounter.add(delta, dimensions);
|
|
248
|
+
increments.set(queueName, (increments.get(queueName) || 0) + delta);
|
|
249
|
+
} else if (delta < 0) {
|
|
250
|
+
// TODO per above: downCounter.add(-delta, dimensions);
|
|
251
|
+
decrements.set(queueName, (decrements.get(queueName) || 0) - delta);
|
|
252
|
+
}
|
|
253
|
+
ready = true;
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
return harden({
|
|
257
|
+
initLengths: initialLengths => {
|
|
258
|
+
!ready ||
|
|
259
|
+
console?.warn(
|
|
260
|
+
`Unexpected repeat queue length initialization from ${q(lengths)} to ${q(initialLengths)}`,
|
|
261
|
+
);
|
|
262
|
+
for (const [queueName, newLength] of Object.entries(initialLengths)) {
|
|
263
|
+
if (!isNat(newLength)) {
|
|
264
|
+
console?.warn(`Invalid length for queue ${q(queueName)}:`, newLength);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
nudge(queueName, newLength, true);
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
updateLengths: newLengths => {
|
|
271
|
+
ready || console?.warn('Missing initial queue lengths');
|
|
272
|
+
for (const [queueName, newLength] of Object.entries(newLengths)) {
|
|
273
|
+
if (!isNat(newLength)) {
|
|
274
|
+
console?.warn(`Invalid length for queue ${q(queueName)}:`, newLength);
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
nudge(queueName, newLength - (lengths.get(queueName) || 0));
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
incLength: (queueName, delta = 1) => {
|
|
281
|
+
if (!isNat(delta)) {
|
|
282
|
+
console?.warn(`Invalid increment for queue ${q(queueName)}:`, delta);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
nudge(queueName, delta);
|
|
286
|
+
},
|
|
287
|
+
decLength: (queueName, delta = 1) => {
|
|
288
|
+
if (!isNat(delta)) {
|
|
289
|
+
console?.warn(`Invalid decrement for queue ${q(queueName)}:`, delta);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
nudge(queueName, -delta);
|
|
293
|
+
},
|
|
294
|
+
});
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// All the kernel metrics we are prepared for.
|
|
298
|
+
/** @enum {(typeof MetricType)[keyof typeof MetricType]} MetricType */
|
|
299
|
+
const MetricType = /** @type {const} */ ({
|
|
300
|
+
Counter: 'counter',
|
|
301
|
+
Gauge: 'gauge',
|
|
302
|
+
});
|
|
303
|
+
/**
|
|
304
|
+
* @typedef KernelMetricMeta
|
|
305
|
+
* @property {string} key
|
|
306
|
+
* @property {string} name
|
|
307
|
+
* @property {{ dimension: string; value: string }} [sub]
|
|
308
|
+
* @property {string} description
|
|
309
|
+
* @property {boolean} [consensus]
|
|
310
|
+
* @property {MetricType} metricType
|
|
311
|
+
*/
|
|
312
|
+
/** @type {Omit<KernelMetricMeta, 'metricType'>[]} */
|
|
313
|
+
export const KERNEL_STATS_SUM_METRICS = [
|
|
314
|
+
{
|
|
315
|
+
key: 'syscalls',
|
|
316
|
+
name: 'swingset_all_syscall_total',
|
|
317
|
+
description: 'Total number of SwingSet kernel calls',
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
key: 'syscallSend',
|
|
321
|
+
name: 'swingset_syscall_total',
|
|
322
|
+
sub: { dimension: 'syscall', value: 'send' },
|
|
323
|
+
description: 'Total number of SwingSet message send kernel calls',
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
key: 'syscallCallNow',
|
|
327
|
+
name: 'swingset_syscall_total',
|
|
328
|
+
sub: { dimension: 'syscall', value: 'callNow' },
|
|
329
|
+
description: 'Total number of SwingSet synchronous device kernel calls',
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
key: 'syscallSubscribe',
|
|
333
|
+
name: 'swingset_syscall_total',
|
|
334
|
+
sub: { dimension: 'syscall', value: 'subscribe' },
|
|
335
|
+
description: 'Total number of SwingSet promise subscription kernel calls',
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
key: 'syscallResolve',
|
|
339
|
+
name: 'swingset_syscall_total',
|
|
340
|
+
sub: { dimension: 'syscall', value: 'resolve' },
|
|
341
|
+
description: 'Total number of SwingSet promise resolution kernel calls',
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
key: 'syscallExit',
|
|
345
|
+
name: 'swingset_syscall_total',
|
|
346
|
+
sub: { dimension: 'syscall', value: 'exit' },
|
|
347
|
+
description: 'Total number of SwingSet vat exit kernel calls',
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
key: 'syscallVatstoreGet',
|
|
351
|
+
name: 'swingset_syscall_total',
|
|
352
|
+
sub: { dimension: 'syscall', value: 'vatstoreGet' },
|
|
353
|
+
description: 'Total number of SwingSet vatstore get kernel calls',
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
key: 'syscallVatstoreSet',
|
|
357
|
+
name: 'swingset_syscall_total',
|
|
358
|
+
sub: { dimension: 'syscall', value: 'vatstoreSet' },
|
|
359
|
+
description: 'Total number of SwingSet vatstore set kernel calls',
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
key: 'syscallVatstoreGetNextKey',
|
|
363
|
+
name: 'swingset_syscall_total',
|
|
364
|
+
sub: { dimension: 'syscall', value: 'vatstoreGetNext' },
|
|
365
|
+
description: 'Total number of SwingSet vatstore getNextKey kernel calls',
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
key: 'syscallVatstoreDelete',
|
|
369
|
+
name: 'swingset_syscall_total',
|
|
370
|
+
sub: { dimension: 'syscall', value: 'vatstoreDelete' },
|
|
371
|
+
description: 'Total number of SwingSet vatstore delete kernel calls',
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
key: 'syscallDropImports',
|
|
375
|
+
name: 'swingset_syscall_total',
|
|
376
|
+
sub: { dimension: 'syscall', value: 'dropImports' },
|
|
377
|
+
description: 'Total number of SwingSet drop imports kernel calls',
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
key: 'dispatches',
|
|
381
|
+
name: 'swingset_dispatch_total',
|
|
382
|
+
description: 'Total number of SwingSet vat calls',
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
key: 'dispatchDeliver',
|
|
386
|
+
name: 'swingset_dispatch_deliver_total',
|
|
387
|
+
description: 'Total number of SwingSet vat message deliveries',
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
key: 'dispatchNotify',
|
|
391
|
+
name: 'swingset_dispatch_notify_total',
|
|
392
|
+
description: 'Total number of SwingSet vat promise notifications',
|
|
393
|
+
},
|
|
394
|
+
];
|
|
395
|
+
|
|
396
|
+
/** @type {Omit<KernelMetricMeta, 'metricType'>[]} */
|
|
397
|
+
export const KERNEL_STATS_UPDOWN_METRICS = [
|
|
398
|
+
{
|
|
399
|
+
key: 'kernelObjects',
|
|
400
|
+
name: 'swingset_kernel_objects',
|
|
401
|
+
description: 'Active kernel objects',
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
key: 'kernelDevices',
|
|
405
|
+
name: 'swingset_kernel_devices',
|
|
406
|
+
description: 'Active kernel devices',
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
key: 'kernelPromises',
|
|
410
|
+
name: 'swingset_kernel_promises',
|
|
411
|
+
description: 'Active kernel promises',
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
key: 'kpUnresolved',
|
|
415
|
+
name: 'swingset_unresolved_kernel_promises',
|
|
416
|
+
description: 'Unresolved kernel promises',
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
key: 'kpFulfilled',
|
|
420
|
+
name: 'swingset_fulfilled_kernel_promises',
|
|
421
|
+
description: 'Fulfilled kernel promises',
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
key: 'kpRejected',
|
|
425
|
+
name: 'swingset_rejected_kernel_promises',
|
|
426
|
+
description: 'Rejected kernel promises',
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
key: 'runQueueLength',
|
|
430
|
+
name: 'swingset_run_queue_length',
|
|
431
|
+
consensus: true,
|
|
432
|
+
description: 'Length of the kernel run queue',
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
key: 'acceptanceQueueLength',
|
|
436
|
+
name: 'swingset_acceptance_queue_length',
|
|
437
|
+
consensus: true,
|
|
438
|
+
description: 'Length of the kernel acceptance queue',
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
key: 'promiseQueuesLength',
|
|
442
|
+
name: 'swingset_promise_queues_length',
|
|
443
|
+
consensus: true,
|
|
444
|
+
description: 'Combined length of all kernel promise queues',
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
key: 'clistEntries',
|
|
448
|
+
name: 'swingset_clist_entries',
|
|
449
|
+
description: 'Number of entries in the kernel c-list',
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
key: 'vats',
|
|
453
|
+
name: 'swingset_vats',
|
|
454
|
+
description: 'Number of active vats',
|
|
455
|
+
},
|
|
456
|
+
];
|
|
457
|
+
|
|
458
|
+
const { Counter, Gauge } = MetricType;
|
|
459
|
+
/** @type {KernelMetricMeta[]} */
|
|
460
|
+
export const KERNEL_STATS_METRICS = harden([
|
|
461
|
+
...KERNEL_STATS_SUM_METRICS.map(m => ({ ...m, metricType: Counter })),
|
|
462
|
+
...KERNEL_STATS_UPDOWN_METRICS.map(m => ({ ...m, metricType: Gauge })),
|
|
463
|
+
]);
|
|
464
|
+
|
|
465
|
+
// Ensure kernel stats key uniqueness.
|
|
466
|
+
const kernelStatsKeys = new Map();
|
|
467
|
+
for (const { key } of KERNEL_STATS_METRICS) {
|
|
468
|
+
kernelStatsKeys.set(key, (kernelStatsKeys.get(key) || 0) + 1);
|
|
469
|
+
}
|
|
470
|
+
const duplicateKernelStatsKeys = [...kernelStatsKeys.entries()].flatMap(
|
|
471
|
+
([key, value]) => (value > 1 ? [key] : []),
|
|
472
|
+
);
|
|
473
|
+
if (duplicateKernelStatsKeys.length > 0) {
|
|
474
|
+
const msg = `Duplicate kernel stats keys ${JSON.stringify(duplicateKernelStatsKeys)}`;
|
|
475
|
+
throw Error(msg);
|
|
476
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-utils.d.ts","sourceRoot":"","sources":["module-utils.js"],"names":[],"mappings":"AAaO,sCAHI,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAc3B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { search } from '@endo/compartment-mapper';
|
|
4
|
+
import { Fail } from '@endo/errors';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Given a file URL, return a deep import specifier that starts with the
|
|
8
|
+
* specifier for its containing module (e.g., the deep import specifier for this
|
|
9
|
+
* file is expected to be "@agoric/internal/src/module-utils.js").
|
|
10
|
+
*
|
|
11
|
+
* @param {string} fileUrl
|
|
12
|
+
* @returns {Promise<string>}
|
|
13
|
+
*/
|
|
14
|
+
export const getSpecifier = async fileUrl => {
|
|
15
|
+
// eslint-disable-next-line no-new
|
|
16
|
+
new URL(fileUrl); // validates fileUrl
|
|
17
|
+
const read = async location => {
|
|
18
|
+
const path = fileURLToPath(new URL(location, fileUrl));
|
|
19
|
+
return readFile(path);
|
|
20
|
+
};
|
|
21
|
+
const searchResult = await search(read, fileUrl);
|
|
22
|
+
const { packageDescriptorText, moduleSpecifier } = searchResult;
|
|
23
|
+
const { name } = JSON.parse(packageDescriptorText);
|
|
24
|
+
name || Fail`containing package must have a name`;
|
|
25
|
+
return `${name}/${moduleSpecifier.replace(/^\.\//, '')}`;
|
|
26
|
+
};
|
|
27
|
+
harden(getSpecifier);
|