@aztec/telemetry-client 0.0.0-test.1 → 0.0.1-commit.017a351
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/dest/attributes.d.ts +45 -10
- package/dest/attributes.d.ts.map +1 -1
- package/dest/attributes.js +28 -9
- package/dest/bench.d.ts +6 -1
- package/dest/bench.d.ts.map +1 -1
- package/dest/bench.js +31 -14
- package/dest/config.d.ts +9 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +44 -8
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/l1_metrics.d.ts +17 -0
- package/dest/l1_metrics.d.ts.map +1 -0
- package/dest/l1_metrics.js +54 -0
- package/dest/lmdb_metrics.d.ts +5 -3
- package/dest/lmdb_metrics.d.ts.map +1 -1
- package/dest/lmdb_metrics.js +7 -15
- package/dest/metric-utils.d.ts +24 -0
- package/dest/metric-utils.d.ts.map +1 -0
- package/dest/metric-utils.js +59 -0
- package/dest/metrics.d.ts +312 -122
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +1595 -120
- package/dest/monitored_batch_span_processor.d.ts +29 -0
- package/dest/monitored_batch_span_processor.d.ts.map +1 -0
- package/dest/monitored_batch_span_processor.js +70 -0
- package/dest/nodejs_metrics_monitor.d.ts +19 -0
- package/dest/nodejs_metrics_monitor.d.ts.map +1 -0
- package/dest/nodejs_metrics_monitor.js +115 -0
- package/dest/noop.d.ts +9 -4
- package/dest/noop.d.ts.map +1 -1
- package/dest/noop.js +34 -1
- package/dest/otel.d.ts +13 -7
- package/dest/otel.d.ts.map +1 -1
- package/dest/otel.js +204 -24
- package/dest/otel_filter_metric_exporter.d.ts +12 -4
- package/dest/otel_filter_metric_exporter.d.ts.map +1 -1
- package/dest/otel_filter_metric_exporter.js +38 -4
- package/dest/otel_logger_provider.d.ts +1 -1
- package/dest/otel_propagation.d.ts +3 -1
- package/dest/otel_propagation.d.ts.map +1 -1
- package/dest/otel_propagation.js +49 -1
- package/dest/otel_resource.d.ts +1 -1
- package/dest/otel_resource.d.ts.map +1 -1
- package/dest/otel_resource.js +43 -2
- package/dest/prom_otel_adapter.d.ts +61 -12
- package/dest/prom_otel_adapter.d.ts.map +1 -1
- package/dest/prom_otel_adapter.js +157 -48
- package/dest/start.d.ts +3 -2
- package/dest/start.d.ts.map +1 -1
- package/dest/start.js +8 -7
- package/dest/telemetry.d.ts +63 -34
- package/dest/telemetry.d.ts.map +1 -1
- package/dest/telemetry.js +47 -24
- package/dest/vendor/attributes.d.ts +1 -1
- package/dest/vendor/otel-pino-stream.d.ts +1 -2
- package/dest/vendor/otel-pino-stream.d.ts.map +1 -1
- package/dest/vendor/otel-pino-stream.js +2 -2
- package/dest/with_tracer.d.ts +1 -1
- package/dest/with_tracer.d.ts.map +1 -1
- package/dest/wrappers/fetch.d.ts +3 -3
- package/dest/wrappers/fetch.d.ts.map +1 -1
- package/dest/wrappers/fetch.js +9 -6
- package/dest/wrappers/index.d.ts +1 -1
- package/dest/wrappers/json_rpc_server.d.ts +2 -2
- package/dest/wrappers/json_rpc_server.d.ts.map +1 -1
- package/dest/wrappers/l2_block_stream.d.ts +4 -3
- package/dest/wrappers/l2_block_stream.d.ts.map +1 -1
- package/dest/wrappers/l2_block_stream.js +385 -11
- package/package.json +21 -15
- package/src/attributes.ts +59 -12
- package/src/bench.ts +37 -15
- package/src/config.ts +76 -9
- package/src/index.ts +1 -0
- package/src/l1_metrics.ts +65 -0
- package/src/lmdb_metrics.ts +24 -24
- package/src/metric-utils.ts +75 -0
- package/src/metrics.ts +1679 -145
- package/src/monitored_batch_span_processor.ts +93 -0
- package/src/nodejs_metrics_monitor.ts +135 -0
- package/src/noop.ts +65 -4
- package/src/otel.ts +193 -28
- package/src/otel_filter_metric_exporter.ts +47 -5
- package/src/otel_propagation.ts +42 -1
- package/src/otel_resource.ts +57 -2
- package/src/prom_otel_adapter.ts +195 -70
- package/src/start.ts +17 -8
- package/src/telemetry.ts +152 -76
- package/src/vendor/otel-pino-stream.ts +1 -4
- package/src/wrappers/fetch.ts +32 -33
- package/src/wrappers/json_rpc_server.ts +1 -1
- package/src/wrappers/l2_block_stream.ts +3 -2
- package/dest/event_loop_monitor.d.ts +0 -18
- package/dest/event_loop_monitor.d.ts.map +0 -1
- package/dest/event_loop_monitor.js +0 -93
- package/src/event_loop_monitor.ts +0 -119
package/src/telemetry.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AttributeValue,
|
|
3
3
|
type BatchObservableCallback,
|
|
4
|
+
type Context,
|
|
4
5
|
type MetricOptions,
|
|
5
6
|
type Observable,
|
|
6
7
|
type BatchObservableResult as OtelBatchObservableResult,
|
|
@@ -14,31 +15,61 @@ import {
|
|
|
14
15
|
SpanStatusCode,
|
|
15
16
|
type Tracer,
|
|
16
17
|
} from '@opentelemetry/api';
|
|
17
|
-
import { isPromise } from 'node:util/types';
|
|
18
18
|
|
|
19
19
|
import type * as Attributes from './attributes.js';
|
|
20
|
-
import type
|
|
20
|
+
import type { MetricDefinition } from './metrics.js';
|
|
21
21
|
import { getTelemetryClient } from './start.js';
|
|
22
22
|
|
|
23
|
-
export {
|
|
23
|
+
export { toMetricOptions, createUpDownCounterWithDefault } from './metric-utils.js';
|
|
24
|
+
|
|
25
|
+
export { type Span, SpanStatusCode, ValueType, type Context } from '@opentelemetry/api';
|
|
24
26
|
|
|
25
27
|
type ValuesOf<T> = T extends Record<string, infer U> ? U : never;
|
|
26
28
|
|
|
29
|
+
type AttributeNames = ValuesOf<typeof Attributes>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* This is a set of attributes that could lead to high cardinality in the metrics.
|
|
33
|
+
* If you find yourself wanting to capture this data in a metric consider if it makes sense to capture
|
|
34
|
+
* as the metric value instead of an attribute or consider logging instead.
|
|
35
|
+
*
|
|
36
|
+
* Think twice before removing an attribute from this list.
|
|
37
|
+
*/
|
|
38
|
+
type BannedMetricAttributeNames = (typeof Attributes)[
|
|
39
|
+
| 'BLOCK_NUMBER'
|
|
40
|
+
| 'BLOCK_ARCHIVE'
|
|
41
|
+
| 'SLOT_NUMBER'
|
|
42
|
+
| 'BLOCK_PARENT'
|
|
43
|
+
| 'BLOCK_CANDIDATE_TXS_COUNT'
|
|
44
|
+
| 'BLOCK_TXS_COUNT'
|
|
45
|
+
| 'BLOCK_SIZE'
|
|
46
|
+
| 'EPOCH_SIZE'
|
|
47
|
+
| 'EPOCH_NUMBER'
|
|
48
|
+
| 'TX_HASH'
|
|
49
|
+
| 'PROVING_JOB_ID'
|
|
50
|
+
| 'P2P_ID'
|
|
51
|
+
| 'TARGET_ADDRESS'
|
|
52
|
+
| 'MANA_USED'
|
|
53
|
+
| 'TOTAL_INSTRUCTIONS'];
|
|
54
|
+
|
|
27
55
|
/** Global registry of attributes */
|
|
28
|
-
type AttributesType = Partial<Record<
|
|
29
|
-
export type { AttributesType };
|
|
56
|
+
export type AttributesType = Partial<Record<AttributeNames, AttributeValue>>;
|
|
30
57
|
|
|
31
|
-
|
|
32
|
-
type MetricsType = (typeof Metrics)[keyof typeof Metrics];
|
|
33
|
-
export type { MetricsType };
|
|
58
|
+
export type AllowedAttributeNames = Exclude<AttributeNames, BannedMetricAttributeNames>;
|
|
34
59
|
|
|
35
|
-
|
|
36
|
-
export type
|
|
37
|
-
|
|
38
|
-
export
|
|
39
|
-
export type
|
|
40
|
-
|
|
41
|
-
export type
|
|
60
|
+
/** Subset of attributes allowed to be added to metrics */
|
|
61
|
+
export type MetricAttributesType = Partial<Record<AllowedAttributeNames, AttributeValue>>;
|
|
62
|
+
|
|
63
|
+
/** Re-export MetricDefinition for convenience */
|
|
64
|
+
export type { MetricDefinition } from './metrics.js';
|
|
65
|
+
|
|
66
|
+
export type Gauge = OtelGauge<MetricAttributesType>;
|
|
67
|
+
export type Histogram = OtelHistogram<MetricAttributesType>;
|
|
68
|
+
export type UpDownCounter = OtelUpDownCounter<MetricAttributesType>;
|
|
69
|
+
export type ObservableGauge = OtelObservableGauge<MetricAttributesType>;
|
|
70
|
+
export type ObservableUpDownCounter = OtelObservableUpDownCounter<MetricAttributesType>;
|
|
71
|
+
export type ObservableResult = OtelObservableResult<MetricAttributesType>;
|
|
72
|
+
export type BatchObservableResult = OtelBatchObservableResult<MetricAttributesType>;
|
|
42
73
|
|
|
43
74
|
export type { Tracer };
|
|
44
75
|
|
|
@@ -49,17 +80,15 @@ export type { Tracer };
|
|
|
49
80
|
export interface Meter {
|
|
50
81
|
/**
|
|
51
82
|
* Creates a new gauge instrument. A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
|
|
52
|
-
* @param
|
|
53
|
-
* @param options - The options for the gauge
|
|
83
|
+
* @param metric - The metric definition
|
|
54
84
|
*/
|
|
55
|
-
createGauge(
|
|
85
|
+
createGauge(metric: MetricDefinition): Gauge;
|
|
56
86
|
|
|
57
87
|
/**
|
|
58
|
-
* Creates a new gauge instrument. A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
|
|
59
|
-
* @param
|
|
60
|
-
* @param options - The options for the gauge
|
|
88
|
+
* Creates a new observable gauge instrument. A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
|
|
89
|
+
* @param metric - The metric definition
|
|
61
90
|
*/
|
|
62
|
-
createObservableGauge(
|
|
91
|
+
createObservableGauge(metric: MetricDefinition): ObservableGauge;
|
|
63
92
|
|
|
64
93
|
addBatchObservableCallback(
|
|
65
94
|
callback: BatchObservableCallback<AttributesType>,
|
|
@@ -73,24 +102,22 @@ export interface Meter {
|
|
|
73
102
|
|
|
74
103
|
/**
|
|
75
104
|
* Creates a new histogram instrument. A histogram is a metric that samples observations (usually things like request durations or response sizes) and counts them in configurable buckets.
|
|
76
|
-
* @param
|
|
77
|
-
* @param
|
|
105
|
+
* @param metric - The metric definition
|
|
106
|
+
* @param extraOptions - Optional extra options (e.g., advice for bucket boundaries)
|
|
78
107
|
*/
|
|
79
|
-
createHistogram(
|
|
108
|
+
createHistogram(metric: MetricDefinition, extraOptions?: Partial<MetricOptions>): Histogram;
|
|
80
109
|
|
|
81
110
|
/**
|
|
82
111
|
* Creates a new counter instrument. A counter can go up or down with a delta from the previous value.
|
|
83
|
-
* @param
|
|
84
|
-
* @param options - The options for the counter
|
|
112
|
+
* @param metric - The metric definition
|
|
85
113
|
*/
|
|
86
|
-
createUpDownCounter(
|
|
114
|
+
createUpDownCounter(metric: MetricDefinition): UpDownCounter;
|
|
87
115
|
|
|
88
116
|
/**
|
|
89
|
-
* Creates a new
|
|
90
|
-
* @param
|
|
91
|
-
* @param options - The options for the gauge
|
|
117
|
+
* Creates a new observable up/down counter instrument.
|
|
118
|
+
* @param metric - The metric definition
|
|
92
119
|
*/
|
|
93
|
-
createObservableUpDownCounter(
|
|
120
|
+
createObservableUpDownCounter(metric: MetricDefinition): ObservableUpDownCounter;
|
|
94
121
|
}
|
|
95
122
|
|
|
96
123
|
/**
|
|
@@ -122,6 +149,27 @@ export interface TelemetryClient {
|
|
|
122
149
|
* Flushes the telemetry client.
|
|
123
150
|
*/
|
|
124
151
|
flush(): Promise<void>;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Updates what telemetry is exported to the public collector
|
|
155
|
+
*/
|
|
156
|
+
setExportedPublicTelemetry(prefixes: string[]): void;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Updates the roles that would share telemetry (if enabled)
|
|
160
|
+
*/
|
|
161
|
+
setPublicTelemetryCollectFrom(roles: string[]): void;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get current trace context as an opaque string for propagation.
|
|
165
|
+
* Returns the W3C traceparent header value if a trace is active, undefined otherwise.
|
|
166
|
+
*/
|
|
167
|
+
getTraceContext(): string | undefined;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Recreates a context propagated by a remote system
|
|
171
|
+
*/
|
|
172
|
+
extractPropagatedContext(traceContext: string): Context | undefined;
|
|
125
173
|
}
|
|
126
174
|
|
|
127
175
|
/** Objects that adhere to this interface can use @trackSpan */
|
|
@@ -165,25 +213,37 @@ export function trackSpan<T extends Traceable, F extends (...args: any[]) => any
|
|
|
165
213
|
// run originalMethod wrapped in an active span
|
|
166
214
|
// "active" means the span will be alive for the duration of the function execution
|
|
167
215
|
// and if any other spans are started during the execution of originalMethod, they will be children of this span
|
|
168
|
-
// behind the scenes this uses AsyncLocalStorage https://nodejs.org/dist/latest-
|
|
169
|
-
return this.tracer.startActiveSpan(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
216
|
+
// behind the scenes this uses AsyncLocalStorage https://nodejs.org/dist/latest-v22.x/docs/api/async_context.html
|
|
217
|
+
return this.tracer.startActiveSpan(
|
|
218
|
+
name,
|
|
219
|
+
{
|
|
220
|
+
attributes: currentAttrs,
|
|
221
|
+
},
|
|
222
|
+
async (span: Span) => {
|
|
223
|
+
try {
|
|
224
|
+
const res = await originalMethod.call(this, ...args);
|
|
225
|
+
const extraAttrs = extraAttributes?.call(this, res);
|
|
226
|
+
span.setAttributes(extraAttrs ?? {});
|
|
227
|
+
span.setStatus({
|
|
228
|
+
code: SpanStatusCode.OK,
|
|
229
|
+
});
|
|
230
|
+
return res;
|
|
231
|
+
} catch (err) {
|
|
232
|
+
span.setStatus({
|
|
233
|
+
code: SpanStatusCode.ERROR,
|
|
234
|
+
message: String(err),
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
if (typeof err === 'string' || (err && err instanceof Error)) {
|
|
238
|
+
span.recordException(err);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
throw err;
|
|
242
|
+
} finally {
|
|
243
|
+
span.end();
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
);
|
|
187
247
|
} as F;
|
|
188
248
|
};
|
|
189
249
|
}
|
|
@@ -227,41 +287,57 @@ export function wrapCallbackInSpan<F extends (...args: any[]) => any>(
|
|
|
227
287
|
export function runInSpan<A extends any[], R>(
|
|
228
288
|
tracer: Tracer | string,
|
|
229
289
|
spanName: string,
|
|
230
|
-
callback: (span: Span, ...args: A) => R
|
|
231
|
-
): (...args: A) => R {
|
|
232
|
-
return (...args: A): R => {
|
|
290
|
+
callback: (span: Span, ...args: A) => Promise<R>,
|
|
291
|
+
): (...args: A) => Promise<R> {
|
|
292
|
+
return (...args: A): Promise<R> => {
|
|
233
293
|
const actualTracer = typeof tracer === 'string' ? getTelemetryClient().getTracer(tracer) : tracer;
|
|
234
|
-
return actualTracer.startActiveSpan(spanName, (span: Span): R => {
|
|
235
|
-
let deferSpanEnd = false;
|
|
294
|
+
return actualTracer.startActiveSpan(spanName, async (span: Span): Promise<R> => {
|
|
236
295
|
try {
|
|
237
|
-
const res = callback(span, ...args);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
code: SpanStatusCode.ERROR,
|
|
244
|
-
message: String(err),
|
|
245
|
-
});
|
|
246
|
-
throw err;
|
|
247
|
-
})
|
|
248
|
-
.finally(() => {
|
|
249
|
-
span.end();
|
|
250
|
-
}) as R;
|
|
251
|
-
} else {
|
|
252
|
-
return res;
|
|
253
|
-
}
|
|
296
|
+
const res = await callback(span, ...args);
|
|
297
|
+
span.setStatus({
|
|
298
|
+
code: SpanStatusCode.OK,
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
return res;
|
|
254
302
|
} catch (err) {
|
|
255
303
|
span.setStatus({
|
|
256
304
|
code: SpanStatusCode.ERROR,
|
|
257
305
|
message: String(err),
|
|
258
306
|
});
|
|
307
|
+
if (typeof err === 'string' || (err && err instanceof Error)) {
|
|
308
|
+
span.recordException(err);
|
|
309
|
+
}
|
|
259
310
|
throw err;
|
|
260
311
|
} finally {
|
|
261
|
-
|
|
262
|
-
span.end();
|
|
263
|
-
}
|
|
312
|
+
span.end();
|
|
264
313
|
}
|
|
265
314
|
});
|
|
266
315
|
};
|
|
267
316
|
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Execute a callback within a span immediately (for one-off traced calls).
|
|
320
|
+
* Unlike runInSpan which returns a reusable function, this executes right away.
|
|
321
|
+
*/
|
|
322
|
+
export function execInSpan<R>(
|
|
323
|
+
tracer: Tracer | string,
|
|
324
|
+
spanName: string,
|
|
325
|
+
callback: (span: Span) => Promise<R>,
|
|
326
|
+
): Promise<R> {
|
|
327
|
+
const actualTracer = typeof tracer === 'string' ? getTelemetryClient().getTracer(tracer) : tracer;
|
|
328
|
+
return actualTracer.startActiveSpan(spanName, async (span: Span): Promise<R> => {
|
|
329
|
+
try {
|
|
330
|
+
const res = await callback(span);
|
|
331
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
332
|
+
return res;
|
|
333
|
+
} catch (err) {
|
|
334
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
335
|
+
if (typeof err === 'string' || (err && err instanceof Error)) {
|
|
336
|
+
span.recordException(err);
|
|
337
|
+
}
|
|
338
|
+
throw err;
|
|
339
|
+
} finally {
|
|
340
|
+
span.end();
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
@@ -23,9 +23,6 @@ import { Writable } from 'stream';
|
|
|
23
23
|
import { registerOtelLoggerProvider } from '../otel_logger_provider.js';
|
|
24
24
|
import { getOtelResource } from '../otel_resource.js';
|
|
25
25
|
|
|
26
|
-
/* eslint-disable @typescript-eslint/ban-types */
|
|
27
|
-
/* eslint-disable camelcase */
|
|
28
|
-
|
|
29
26
|
// This block is a copy (modulo code style and TypeScript types) of the Pino
|
|
30
27
|
// code that defines log level value and names. This file is part of
|
|
31
28
|
// *instrumenting* Pino, so we want to avoid a dependency on the library.
|
|
@@ -173,7 +170,7 @@ export class OTelPinoStream extends Writable {
|
|
|
173
170
|
return;
|
|
174
171
|
}
|
|
175
172
|
|
|
176
|
-
// Parse, and handle edge cases similar to how `pino-
|
|
173
|
+
// Parse, and handle edge cases similar to how `pino-abstract-transport` does:
|
|
177
174
|
// https://github.com/pinojs/pino-abstract-transport/blob/v1.2.0/index.js#L28-L45
|
|
178
175
|
// - Emitting an 'unknown' event on parse error mimicks pino-abstract-transport.
|
|
179
176
|
let recObj;
|
package/src/wrappers/fetch.ts
CHANGED
|
@@ -9,44 +9,43 @@ import { ATTR_JSONRPC_METHOD, ATTR_JSONRPC_REQUEST_ID } from '../vendor/attribut
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Makes a fetch function that retries based on the given attempts and propagates trace information.
|
|
12
|
-
* @param retries - Sequence of intervals (in seconds) to retry.
|
|
12
|
+
* @param retries - Sequence of intervals (in seconds) to retry, or a factory function returning an iterator for custom/indefinite backoff.
|
|
13
13
|
* @param noRetry - Whether to stop retries on server errors.
|
|
14
14
|
* @param log - Optional logger for logging attempts.
|
|
15
15
|
* @returns A fetch function.
|
|
16
16
|
*/
|
|
17
|
-
export function makeTracedFetch(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
noRetry?: boolean,
|
|
25
|
-
) => {
|
|
17
|
+
export function makeTracedFetch(
|
|
18
|
+
retries: number[] | (() => Generator<number>),
|
|
19
|
+
defaultNoRetry: boolean,
|
|
20
|
+
fetch = defaultFetch,
|
|
21
|
+
log?: Logger,
|
|
22
|
+
) {
|
|
23
|
+
return (host: string, body: unknown, extraHeaders: Record<string, string> = {}, noRetry?: boolean) => {
|
|
26
24
|
const telemetry = getTelemetryClient();
|
|
27
|
-
return telemetry
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (body && typeof body.id === 'number') {
|
|
32
|
-
span.setAttribute(ATTR_JSONRPC_REQUEST_ID, body.id);
|
|
33
|
-
}
|
|
34
|
-
span.setAttribute(ATTR_JSONRPC_METHOD, rpcMethod);
|
|
35
|
-
const headers = { ...extraHeaders };
|
|
36
|
-
propagation.inject(context.active(), headers);
|
|
37
|
-
return await retry(
|
|
38
|
-
() => fetch(host, rpcMethod, body, useApiEndpoints, headers, noRetry ?? defaultNoRetry),
|
|
39
|
-
`JsonRpcClient request ${rpcMethod} to ${host}`,
|
|
40
|
-
makeBackoff(retries),
|
|
41
|
-
log,
|
|
42
|
-
false,
|
|
43
|
-
);
|
|
44
|
-
} catch (err: any) {
|
|
45
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message: err?.message ?? String(err) });
|
|
46
|
-
throw err;
|
|
47
|
-
} finally {
|
|
48
|
-
span.end();
|
|
25
|
+
return telemetry.getTracer('fetch').startActiveSpan(`JsonRpcClient`, { kind: SpanKind.CLIENT }, async span => {
|
|
26
|
+
try {
|
|
27
|
+
if (body && typeof body === 'object' && 'id' in body && typeof body.id === 'number') {
|
|
28
|
+
span.setAttribute(ATTR_JSONRPC_REQUEST_ID, body.id);
|
|
49
29
|
}
|
|
50
|
-
|
|
30
|
+
if (body && typeof body === 'object' && 'method' in body && typeof body.method === 'string') {
|
|
31
|
+
span.setAttribute(ATTR_JSONRPC_METHOD, body.method);
|
|
32
|
+
}
|
|
33
|
+
const headers = { ...extraHeaders };
|
|
34
|
+
propagation.inject(context.active(), headers);
|
|
35
|
+
const backoff = typeof retries === 'function' ? retries() : makeBackoff(retries);
|
|
36
|
+
return await retry(
|
|
37
|
+
() => fetch(host, body, headers, noRetry ?? defaultNoRetry),
|
|
38
|
+
`JsonRpcClient request to ${host}`,
|
|
39
|
+
backoff,
|
|
40
|
+
log,
|
|
41
|
+
false,
|
|
42
|
+
);
|
|
43
|
+
} catch (err: any) {
|
|
44
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err?.message ?? String(err) });
|
|
45
|
+
throw err;
|
|
46
|
+
} finally {
|
|
47
|
+
span.end();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
51
50
|
};
|
|
52
51
|
}
|
|
@@ -6,7 +6,7 @@ import { getOtelJsonRpcPropagationMiddleware } from '../otel_propagation.js';
|
|
|
6
6
|
export function createTracedJsonRpcServer<T extends object = any>(
|
|
7
7
|
handler: T,
|
|
8
8
|
schema: ApiSchemaFor<T>,
|
|
9
|
-
options:
|
|
9
|
+
options: SafeJsonRpcServerOptions = {},
|
|
10
10
|
) {
|
|
11
11
|
return createSafeJsonRpcServer(handler, schema, {
|
|
12
12
|
...options,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
3
|
import {
|
|
3
4
|
type L2BlockSource,
|
|
@@ -10,7 +11,7 @@ import { type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client'
|
|
|
10
11
|
/** Extends an L2BlockStream with a tracer to create a new trace per iteration. */
|
|
11
12
|
export class TraceableL2BlockStream extends L2BlockStream implements Traceable {
|
|
12
13
|
constructor(
|
|
13
|
-
l2BlockSource: Pick<L2BlockSource, 'getBlocks' | '
|
|
14
|
+
l2BlockSource: Pick<L2BlockSource, 'getBlocks' | 'getBlockData' | 'getL2Tips' | 'getCheckpoints'>,
|
|
14
15
|
localData: L2BlockStreamLocalDataProvider,
|
|
15
16
|
handler: L2BlockStreamEventHandler,
|
|
16
17
|
public readonly tracer: Tracer,
|
|
@@ -20,7 +21,7 @@ export class TraceableL2BlockStream extends L2BlockStream implements Traceable {
|
|
|
20
21
|
proven?: boolean;
|
|
21
22
|
pollIntervalMS?: number;
|
|
22
23
|
batchSize?: number;
|
|
23
|
-
startingBlock?:
|
|
24
|
+
startingBlock?: BlockNumber;
|
|
24
25
|
} = {},
|
|
25
26
|
) {
|
|
26
27
|
super(l2BlockSource, localData, handler, log, opts);
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { type Meter } from './telemetry.js';
|
|
2
|
-
/**
|
|
3
|
-
* Detector for custom Aztec attributes
|
|
4
|
-
*/
|
|
5
|
-
export declare class EventLoopMonitor {
|
|
6
|
-
private meter;
|
|
7
|
-
private eventLoopDelayGauges;
|
|
8
|
-
private eventLoopUilization;
|
|
9
|
-
private eventLoopTime;
|
|
10
|
-
private started;
|
|
11
|
-
private lastELU;
|
|
12
|
-
private eventLoopDelay;
|
|
13
|
-
constructor(meter: Meter);
|
|
14
|
-
start(): void;
|
|
15
|
-
stop(): void;
|
|
16
|
-
private measure;
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=event_loop_monitor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"event_loop_monitor.d.ts","sourceRoot":"","sources":["../src/event_loop_monitor.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,KAAK,EAIX,MAAM,gBAAgB,CAAC;AAExB;;GAEG;AACH,qBAAa,gBAAgB;IAmBf,OAAO,CAAC,KAAK;IAlBzB,OAAO,CAAC,oBAAoB,CAQ1B;IAEF,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,aAAa,CAAgB;IAErC,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,cAAc,CAAoB;gBAEtB,KAAK,EAAE,KAAK;IAgChC,KAAK,IAAI,IAAI;IAab,IAAI,IAAI,IAAI;IAaZ,OAAO,CAAC,OAAO,CAyBb;CACH"}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { monitorEventLoopDelay, performance } from 'node:perf_hooks';
|
|
2
|
-
import * as Attributes from './attributes.js';
|
|
3
|
-
import * as Metrics from './metrics.js';
|
|
4
|
-
import { ValueType } from './telemetry.js';
|
|
5
|
-
/**
|
|
6
|
-
* Detector for custom Aztec attributes
|
|
7
|
-
*/ export class EventLoopMonitor {
|
|
8
|
-
meter;
|
|
9
|
-
eventLoopDelayGauges;
|
|
10
|
-
eventLoopUilization;
|
|
11
|
-
eventLoopTime;
|
|
12
|
-
started;
|
|
13
|
-
lastELU;
|
|
14
|
-
eventLoopDelay;
|
|
15
|
-
constructor(meter){
|
|
16
|
-
this.meter = meter;
|
|
17
|
-
this.started = false;
|
|
18
|
-
this.measure = (obs)=>{
|
|
19
|
-
const newELU = performance.eventLoopUtilization();
|
|
20
|
-
const delta = performance.eventLoopUtilization(newELU, this.lastELU);
|
|
21
|
-
this.lastELU = newELU;
|
|
22
|
-
// `utilization` [0,1] represents how much the event loop is busy vs waiting for new events to come in
|
|
23
|
-
// This should be corelated with CPU usage to gauge the performance characteristics of services
|
|
24
|
-
// 100% utilization leads to high latency because the event loop is _always_ busy, there's no breathing room for events to be processed quickly.
|
|
25
|
-
// Docs and examples:
|
|
26
|
-
// - https://nodesource.com/blog/event-loop-utilization-nodejs
|
|
27
|
-
// - https://youtu.be/WetXnEPraYM
|
|
28
|
-
obs.observe(this.eventLoopUilization, delta.utilization);
|
|
29
|
-
this.eventLoopTime.add(Math.floor(delta.idle), {
|
|
30
|
-
[Attributes.NODEJS_EVENT_LOOP_STATE]: 'idle'
|
|
31
|
-
});
|
|
32
|
-
this.eventLoopTime.add(Math.floor(delta.active), {
|
|
33
|
-
[Attributes.NODEJS_EVENT_LOOP_STATE]: 'active'
|
|
34
|
-
});
|
|
35
|
-
obs.observe(this.eventLoopDelayGauges.min, Math.floor(this.eventLoopDelay.min));
|
|
36
|
-
obs.observe(this.eventLoopDelayGauges.mean, Math.floor(this.eventLoopDelay.mean));
|
|
37
|
-
obs.observe(this.eventLoopDelayGauges.max, Math.floor(this.eventLoopDelay.max));
|
|
38
|
-
obs.observe(this.eventLoopDelayGauges.stddev, Math.floor(this.eventLoopDelay.stddev));
|
|
39
|
-
obs.observe(this.eventLoopDelayGauges.p50, Math.floor(this.eventLoopDelay.percentile(50)));
|
|
40
|
-
obs.observe(this.eventLoopDelayGauges.p90, Math.floor(this.eventLoopDelay.percentile(90)));
|
|
41
|
-
obs.observe(this.eventLoopDelayGauges.p99, Math.floor(this.eventLoopDelay.percentile(99)));
|
|
42
|
-
this.eventLoopDelay.reset();
|
|
43
|
-
};
|
|
44
|
-
const nsObsGauge = (name, description)=>meter.createObservableGauge(name, {
|
|
45
|
-
unit: 'ns',
|
|
46
|
-
valueType: ValueType.INT,
|
|
47
|
-
description
|
|
48
|
-
});
|
|
49
|
-
this.eventLoopDelayGauges = {
|
|
50
|
-
min: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_MIN, 'Minimum delay of the event loop'),
|
|
51
|
-
mean: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_MEAN, 'Mean delay of the event loop'),
|
|
52
|
-
max: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_MAX, 'Max delay of the event loop'),
|
|
53
|
-
stddev: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_STDDEV, 'Stddev delay of the event loop'),
|
|
54
|
-
p50: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_P50, 'P50 delay of the event loop'),
|
|
55
|
-
p90: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_P90, 'P90 delay of the event loop'),
|
|
56
|
-
p99: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_P99, 'P99 delay of the event loop')
|
|
57
|
-
};
|
|
58
|
-
this.eventLoopUilization = meter.createObservableGauge(Metrics.NODEJS_EVENT_LOOP_UTILIZATION, {
|
|
59
|
-
valueType: ValueType.DOUBLE,
|
|
60
|
-
description: 'How busy is the event loop'
|
|
61
|
-
});
|
|
62
|
-
this.eventLoopTime = meter.createUpDownCounter(Metrics.NODEJS_EVENT_LOOP_TIME, {
|
|
63
|
-
unit: 'ms',
|
|
64
|
-
valueType: ValueType.INT,
|
|
65
|
-
description: 'How much time the event loop has spent in a given state'
|
|
66
|
-
});
|
|
67
|
-
this.eventLoopDelay = monitorEventLoopDelay();
|
|
68
|
-
}
|
|
69
|
-
start() {
|
|
70
|
-
if (this.started) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
this.lastELU = performance.eventLoopUtilization();
|
|
74
|
-
this.eventLoopDelay.enable();
|
|
75
|
-
this.meter.addBatchObservableCallback(this.measure, [
|
|
76
|
-
this.eventLoopUilization,
|
|
77
|
-
...Object.values(this.eventLoopDelayGauges)
|
|
78
|
-
]);
|
|
79
|
-
}
|
|
80
|
-
stop() {
|
|
81
|
-
if (!this.started) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.meter.removeBatchObservableCallback(this.measure, [
|
|
85
|
-
this.eventLoopUilization,
|
|
86
|
-
...Object.values(this.eventLoopDelayGauges)
|
|
87
|
-
]);
|
|
88
|
-
this.eventLoopDelay.disable();
|
|
89
|
-
this.eventLoopDelay.reset();
|
|
90
|
-
this.lastELU = undefined;
|
|
91
|
-
}
|
|
92
|
-
measure;
|
|
93
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { type EventLoopUtilization, type IntervalHistogram, monitorEventLoopDelay, performance } from 'node:perf_hooks';
|
|
2
|
-
|
|
3
|
-
import * as Attributes from './attributes.js';
|
|
4
|
-
import * as Metrics from './metrics.js';
|
|
5
|
-
import {
|
|
6
|
-
type BatchObservableResult,
|
|
7
|
-
type Meter,
|
|
8
|
-
type ObservableGauge,
|
|
9
|
-
type UpDownCounter,
|
|
10
|
-
ValueType,
|
|
11
|
-
} from './telemetry.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Detector for custom Aztec attributes
|
|
15
|
-
*/
|
|
16
|
-
export class EventLoopMonitor {
|
|
17
|
-
private eventLoopDelayGauges: {
|
|
18
|
-
min: ObservableGauge;
|
|
19
|
-
max: ObservableGauge;
|
|
20
|
-
mean: ObservableGauge;
|
|
21
|
-
stddev: ObservableGauge;
|
|
22
|
-
p50: ObservableGauge;
|
|
23
|
-
p90: ObservableGauge;
|
|
24
|
-
p99: ObservableGauge;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
private eventLoopUilization: ObservableGauge;
|
|
28
|
-
private eventLoopTime: UpDownCounter;
|
|
29
|
-
|
|
30
|
-
private started = false;
|
|
31
|
-
|
|
32
|
-
private lastELU: EventLoopUtilization | undefined;
|
|
33
|
-
private eventLoopDelay: IntervalHistogram;
|
|
34
|
-
|
|
35
|
-
constructor(private meter: Meter) {
|
|
36
|
-
const nsObsGauge = (name: (typeof Metrics)[keyof typeof Metrics], description: string) =>
|
|
37
|
-
meter.createObservableGauge(name, {
|
|
38
|
-
unit: 'ns',
|
|
39
|
-
valueType: ValueType.INT,
|
|
40
|
-
description,
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
this.eventLoopDelayGauges = {
|
|
44
|
-
min: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_MIN, 'Minimum delay of the event loop'),
|
|
45
|
-
mean: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_MEAN, 'Mean delay of the event loop'),
|
|
46
|
-
max: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_MAX, 'Max delay of the event loop'),
|
|
47
|
-
stddev: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_STDDEV, 'Stddev delay of the event loop'),
|
|
48
|
-
p50: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_P50, 'P50 delay of the event loop'),
|
|
49
|
-
p90: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_P90, 'P90 delay of the event loop'),
|
|
50
|
-
p99: nsObsGauge(Metrics.NODEJS_EVENT_LOOP_DELAY_P99, 'P99 delay of the event loop'),
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
this.eventLoopUilization = meter.createObservableGauge(Metrics.NODEJS_EVENT_LOOP_UTILIZATION, {
|
|
54
|
-
valueType: ValueType.DOUBLE,
|
|
55
|
-
description: 'How busy is the event loop',
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
this.eventLoopTime = meter.createUpDownCounter(Metrics.NODEJS_EVENT_LOOP_TIME, {
|
|
59
|
-
unit: 'ms',
|
|
60
|
-
valueType: ValueType.INT,
|
|
61
|
-
description: 'How much time the event loop has spent in a given state',
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
this.eventLoopDelay = monitorEventLoopDelay();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
start(): void {
|
|
68
|
-
if (this.started) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
this.lastELU = performance.eventLoopUtilization();
|
|
73
|
-
this.eventLoopDelay.enable();
|
|
74
|
-
this.meter.addBatchObservableCallback(this.measure, [
|
|
75
|
-
this.eventLoopUilization,
|
|
76
|
-
...Object.values(this.eventLoopDelayGauges),
|
|
77
|
-
]);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
stop(): void {
|
|
81
|
-
if (!this.started) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.meter.removeBatchObservableCallback(this.measure, [
|
|
85
|
-
this.eventLoopUilization,
|
|
86
|
-
...Object.values(this.eventLoopDelayGauges),
|
|
87
|
-
]);
|
|
88
|
-
this.eventLoopDelay.disable();
|
|
89
|
-
this.eventLoopDelay.reset();
|
|
90
|
-
this.lastELU = undefined;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
private measure = (obs: BatchObservableResult): void => {
|
|
94
|
-
const newELU = performance.eventLoopUtilization();
|
|
95
|
-
const delta = performance.eventLoopUtilization(newELU, this.lastELU);
|
|
96
|
-
this.lastELU = newELU;
|
|
97
|
-
|
|
98
|
-
// `utilization` [0,1] represents how much the event loop is busy vs waiting for new events to come in
|
|
99
|
-
// This should be corelated with CPU usage to gauge the performance characteristics of services
|
|
100
|
-
// 100% utilization leads to high latency because the event loop is _always_ busy, there's no breathing room for events to be processed quickly.
|
|
101
|
-
// Docs and examples:
|
|
102
|
-
// - https://nodesource.com/blog/event-loop-utilization-nodejs
|
|
103
|
-
// - https://youtu.be/WetXnEPraYM
|
|
104
|
-
obs.observe(this.eventLoopUilization, delta.utilization);
|
|
105
|
-
|
|
106
|
-
this.eventLoopTime.add(Math.floor(delta.idle), { [Attributes.NODEJS_EVENT_LOOP_STATE]: 'idle' });
|
|
107
|
-
this.eventLoopTime.add(Math.floor(delta.active), { [Attributes.NODEJS_EVENT_LOOP_STATE]: 'active' });
|
|
108
|
-
|
|
109
|
-
obs.observe(this.eventLoopDelayGauges.min, Math.floor(this.eventLoopDelay.min));
|
|
110
|
-
obs.observe(this.eventLoopDelayGauges.mean, Math.floor(this.eventLoopDelay.mean));
|
|
111
|
-
obs.observe(this.eventLoopDelayGauges.max, Math.floor(this.eventLoopDelay.max));
|
|
112
|
-
obs.observe(this.eventLoopDelayGauges.stddev, Math.floor(this.eventLoopDelay.stddev));
|
|
113
|
-
obs.observe(this.eventLoopDelayGauges.p50, Math.floor(this.eventLoopDelay.percentile(50)));
|
|
114
|
-
obs.observe(this.eventLoopDelayGauges.p90, Math.floor(this.eventLoopDelay.percentile(90)));
|
|
115
|
-
obs.observe(this.eventLoopDelayGauges.p99, Math.floor(this.eventLoopDelay.percentile(99)));
|
|
116
|
-
|
|
117
|
-
this.eventLoopDelay.reset();
|
|
118
|
-
};
|
|
119
|
-
}
|