@aztec/telemetry-client 0.0.0-test.0 → 0.0.1-commit.03f7ef2

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.
Files changed (83) hide show
  1. package/dest/attributes.d.ts +32 -9
  2. package/dest/attributes.d.ts.map +1 -1
  3. package/dest/attributes.js +21 -8
  4. package/dest/bench.d.ts +4 -1
  5. package/dest/bench.d.ts.map +1 -1
  6. package/dest/bench.js +7 -0
  7. package/dest/config.d.ts +7 -2
  8. package/dest/config.d.ts.map +1 -1
  9. package/dest/config.js +29 -1
  10. package/dest/index.d.ts +2 -1
  11. package/dest/index.d.ts.map +1 -1
  12. package/dest/index.js +1 -0
  13. package/dest/l1_metrics.d.ts +17 -0
  14. package/dest/l1_metrics.d.ts.map +1 -0
  15. package/dest/l1_metrics.js +70 -0
  16. package/dest/lmdb_metrics.d.ts +4 -2
  17. package/dest/lmdb_metrics.d.ts.map +1 -1
  18. package/dest/lmdb_metrics.js +8 -0
  19. package/dest/metrics.d.ts +115 -13
  20. package/dest/metrics.d.ts.map +1 -1
  21. package/dest/metrics.js +116 -13
  22. package/dest/nodejs_metrics_monitor.d.ts +21 -0
  23. package/dest/nodejs_metrics_monitor.d.ts.map +1 -0
  24. package/dest/{event_loop_monitor.js → nodejs_metrics_monitor.js} +55 -12
  25. package/dest/noop.d.ts +4 -2
  26. package/dest/noop.d.ts.map +1 -1
  27. package/dest/noop.js +2 -0
  28. package/dest/otel.d.ts +9 -5
  29. package/dest/otel.d.ts.map +1 -1
  30. package/dest/otel.js +93 -19
  31. package/dest/otel_filter_metric_exporter.d.ts +12 -4
  32. package/dest/otel_filter_metric_exporter.d.ts.map +1 -1
  33. package/dest/otel_filter_metric_exporter.js +38 -4
  34. package/dest/otel_logger_provider.d.ts +1 -1
  35. package/dest/otel_propagation.d.ts +1 -1
  36. package/dest/otel_resource.d.ts +1 -1
  37. package/dest/otel_resource.d.ts.map +1 -1
  38. package/dest/otel_resource.js +31 -2
  39. package/dest/prom_otel_adapter.d.ts +58 -9
  40. package/dest/prom_otel_adapter.d.ts.map +1 -1
  41. package/dest/prom_otel_adapter.js +143 -43
  42. package/dest/start.d.ts +2 -2
  43. package/dest/start.d.ts.map +1 -1
  44. package/dest/start.js +7 -6
  45. package/dest/telemetry.d.ts +29 -12
  46. package/dest/telemetry.d.ts.map +1 -1
  47. package/dest/telemetry.js +1 -1
  48. package/dest/vendor/attributes.d.ts +1 -1
  49. package/dest/vendor/otel-pino-stream.d.ts +1 -2
  50. package/dest/vendor/otel-pino-stream.d.ts.map +1 -1
  51. package/dest/vendor/otel-pino-stream.js +2 -2
  52. package/dest/with_tracer.d.ts +1 -1
  53. package/dest/with_tracer.d.ts.map +1 -1
  54. package/dest/wrappers/fetch.d.ts +2 -2
  55. package/dest/wrappers/fetch.d.ts.map +1 -1
  56. package/dest/wrappers/fetch.js +7 -5
  57. package/dest/wrappers/index.d.ts +1 -1
  58. package/dest/wrappers/json_rpc_server.d.ts +2 -2
  59. package/dest/wrappers/json_rpc_server.d.ts.map +1 -1
  60. package/dest/wrappers/l2_block_stream.d.ts +4 -3
  61. package/dest/wrappers/l2_block_stream.d.ts.map +1 -1
  62. package/package.json +21 -15
  63. package/src/attributes.ts +40 -11
  64. package/src/bench.ts +15 -5
  65. package/src/config.ts +54 -2
  66. package/src/index.ts +1 -0
  67. package/src/l1_metrics.ts +80 -0
  68. package/src/lmdb_metrics.ts +24 -3
  69. package/src/metrics.ts +140 -12
  70. package/src/{event_loop_monitor.ts → nodejs_metrics_monitor.ts} +59 -10
  71. package/src/noop.ts +4 -1
  72. package/src/otel.ts +80 -21
  73. package/src/otel_filter_metric_exporter.ts +47 -5
  74. package/src/otel_resource.ts +40 -2
  75. package/src/prom_otel_adapter.ts +191 -59
  76. package/src/start.ts +7 -6
  77. package/src/telemetry.ts +50 -12
  78. package/src/vendor/otel-pino-stream.ts +1 -4
  79. package/src/wrappers/fetch.ts +24 -31
  80. package/src/wrappers/json_rpc_server.ts +1 -1
  81. package/src/wrappers/l2_block_stream.ts +3 -2
  82. package/dest/event_loop_monitor.d.ts +0 -18
  83. package/dest/event_loop_monitor.d.ts.map +0 -1
@@ -1,16 +1,54 @@
1
1
  import {
2
+ type DetectorSync,
2
3
  type IResource,
4
+ Resource,
3
5
  detectResourcesSync,
4
6
  envDetectorSync,
5
7
  osDetectorSync,
6
- processDetectorSync,
7
8
  serviceInstanceIdDetectorSync,
8
9
  } from '@opentelemetry/resources';
10
+ import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
11
+
12
+ import { AZTEC_NODE_ROLE, AZTEC_REGISTRY_ADDRESS, AZTEC_ROLLUP_ADDRESS, AZTEC_ROLLUP_VERSION } from './attributes.js';
9
13
 
10
14
  export function getOtelResource(): IResource {
11
15
  const resource = detectResourcesSync({
12
- detectors: [osDetectorSync, envDetectorSync, processDetectorSync, serviceInstanceIdDetectorSync],
16
+ detectors: [
17
+ aztecNetworkDetectorSync,
18
+ osDetectorSync,
19
+ envDetectorSync,
20
+ // this detector is disabled because:
21
+ // 1. our software runs in a docker container, a lot of the attributes detected would be identical across different machines (e.g. all run node v22, executing the same script, running PID 1, etc)
22
+ // 2. it catures process.argv which could contain sensitive values in plain text (e.g. validator private keys)
23
+ // processDetectorSync,
24
+ serviceInstanceIdDetectorSync,
25
+ ],
13
26
  });
14
27
 
15
28
  return resource;
16
29
  }
30
+
31
+ const aztecNetworkDetectorSync: DetectorSync = {
32
+ detect(): IResource {
33
+ let role: string | undefined;
34
+ if (process.argv.includes('--sequencer')) {
35
+ role = 'sequencer';
36
+ } else if (process.argv.includes('--prover-node')) {
37
+ role = 'prover-node';
38
+ } else if (process.argv.includes('--node')) {
39
+ role = 'node';
40
+ } else if (process.argv.includes('--p2p-bootstrap')) {
41
+ role = 'bootnode';
42
+ }
43
+ const aztecAttributes = {
44
+ // this gets overwritten by OTEL_RESOURCE_ATTRIBUTES (if set)
45
+ [SEMRESATTRS_SERVICE_NAME]: role ? `aztec-${role}` : undefined,
46
+ [AZTEC_NODE_ROLE]: role,
47
+ [AZTEC_ROLLUP_VERSION]: process.env.ROLLUP_VERSION ?? 'canonical',
48
+ [AZTEC_ROLLUP_ADDRESS]: process.env.ROLLUP_CONTRACT_ADDRESS,
49
+ [AZTEC_REGISTRY_ADDRESS]: process.env.REGISTRY_CONTRACT_ADDRESS,
50
+ };
51
+
52
+ return new Resource(aztecAttributes);
53
+ },
54
+ };
@@ -1,8 +1,9 @@
1
1
  import { type Logger, createLogger } from '@aztec/foundation/log';
2
+ import { Timer } from '@aztec/foundation/timer';
2
3
 
3
4
  import { Registry } from 'prom-client';
4
5
 
5
- import type { Meter, MetricsType, ObservableGauge, TelemetryClient } from './telemetry.js';
6
+ import type { Histogram, Meter, MetricsType, ObservableGauge, TelemetryClient } from './telemetry.js';
6
7
 
7
8
  /**
8
9
  * Types matching the gossipsub and libp2p services
@@ -125,7 +126,7 @@ export class OtelGauge<Labels extends LabelsGeneric = NoLabels> implements IGaug
125
126
  }
126
127
 
127
128
  for (const [labelStr, value] of this.labeledValues.entries()) {
128
- const labels = this.parseLabelsSafely(labelStr);
129
+ const labels = parseLabelsSafely(labelStr, this.logger);
129
130
  if (labels) {
130
131
  result.observe(value, labels);
131
132
  }
@@ -146,7 +147,7 @@ export class OtelGauge<Labels extends LabelsGeneric = NoLabels> implements IGaug
146
147
  }
147
148
 
148
149
  if (labelsOrValue) {
149
- this.validateLabels(labelsOrValue);
150
+ validateLabels(labelsOrValue, this.labelNames, 'Gauge');
150
151
  const labelKey = JSON.stringify(labelsOrValue);
151
152
  const currentValue = this.labeledValues.get(labelKey) ?? 0;
152
153
  this.labeledValues.set(labelKey, currentValue + (value ?? 1));
@@ -169,7 +170,7 @@ export class OtelGauge<Labels extends LabelsGeneric = NoLabels> implements IGaug
169
170
  return;
170
171
  }
171
172
 
172
- this.validateLabels(labelsOrValue);
173
+ validateLabels(labelsOrValue, this.labelNames, 'Gauge');
173
174
  const labelKey = JSON.stringify(labelsOrValue);
174
175
  this.labeledValues.set(labelKey, value!);
175
176
  }
@@ -180,7 +181,7 @@ export class OtelGauge<Labels extends LabelsGeneric = NoLabels> implements IGaug
180
181
  */
181
182
  dec(labels?: Labels): void {
182
183
  if (labels) {
183
- this.validateLabels(labels);
184
+ validateLabels(labels, this.labelNames, 'Gauge');
184
185
  const labelKey = JSON.stringify(labels);
185
186
  const currentValue = this.labeledValues.get(labelKey) ?? 0;
186
187
  this.labeledValues.set(labelKey, currentValue - 1);
@@ -197,84 +198,215 @@ export class OtelGauge<Labels extends LabelsGeneric = NoLabels> implements IGaug
197
198
  this.currentValue = 0;
198
199
  this.labeledValues.clear();
199
200
  }
201
+ }
202
+
203
+ /**
204
+ * Implementation of a Histogram collector
205
+ */
206
+ export class OtelHistogram<Labels extends LabelsGeneric = NoLabels> implements IHistogram<Labels> {
207
+ private histogram: Histogram;
208
+
209
+ constructor(
210
+ private logger: Logger,
211
+ meter: Meter,
212
+ name: string,
213
+ help: string,
214
+ buckets: number[] = [],
215
+ private labelNames: Array<keyof Labels> = [],
216
+ ) {
217
+ this.histogram = meter.createHistogram(name as MetricsType, {
218
+ description: help,
219
+ advice: buckets.length ? { explicitBucketBoundaries: buckets } : undefined,
220
+ });
221
+ }
200
222
 
201
223
  /**
202
- * Validates that provided labels match the expected schema
203
- * @param labels - Labels object to validate
204
- * @throws Error if invalid labels are provided
224
+ * Starts a timer and returns a function that when called will record the time elapsed
225
+ * @param labels - Optional labels for the observation
205
226
  */
206
- private validateLabels(labels: Labels): void {
207
- if (this.labelNames.length === 0) {
208
- throw new Error('Gauge was initialized without labels support');
227
+ startTimer(labels?: Labels): () => void {
228
+ if (labels) {
229
+ validateLabels(labels, this.labelNames, 'Histogram');
209
230
  }
210
231
 
211
- for (const key of Object.keys(labels)) {
212
- if (!this.labelNames.includes(key as keyof Labels)) {
213
- throw new Error(`Invalid label key: ${key}`);
232
+ const timer = new Timer();
233
+ return () => {
234
+ // Use timer.s() here to get the duration in seconds since this is only currently used by gossipsub_heartbeat_duration_seconds
235
+ const duration = timer.s();
236
+ if (labels) {
237
+ this.observe(labels, duration);
238
+ } else {
239
+ this.observe(duration);
214
240
  }
215
- }
241
+ };
216
242
  }
217
243
 
218
244
  /**
219
- * Safely parses label string back to object
220
- * @param labelStr - Stringified labels object
221
- * @returns Labels object or null if parsing fails
245
+ * Observes a value
246
+ * @param value - Value to observe
247
+ */
248
+ observe(value: number): void;
249
+ /**
250
+ * Observes a value with labels
251
+ * @param labels - Labels object
252
+ * @param value - Value to observe
222
253
  */
223
- private parseLabelsSafely(labelStr: string): Labels | null {
224
- try {
225
- return JSON.parse(labelStr) as Labels;
226
- } catch {
227
- this.logger.error(`Failed to parse label string: ${labelStr}`);
228
- return null;
254
+ observe(labels: Labels, value: number): void;
255
+ observe(labelsOrValue: Labels | number, value?: number): void {
256
+ if (typeof labelsOrValue === 'number') {
257
+ this.histogram.record(labelsOrValue);
258
+ } else {
259
+ validateLabels(labelsOrValue, this.labelNames, 'Histogram');
260
+ this.histogram.record(value!, labelsOrValue);
229
261
  }
230
262
  }
263
+
264
+ reset(): void {
265
+ // OpenTelemetry histograms cannot be reset, but we implement the interface
266
+ this.logger.silent('OpenTelemetry histograms cannot be fully reset');
267
+ }
231
268
  }
232
269
 
233
270
  /**
234
- * Noop implementation of a Historgram collec
271
+ * Implementation of an AvgMinMax collector
235
272
  */
236
- class NoopOtelHistogram<Labels extends LabelsGeneric = NoLabels> implements IHistogram<Labels> {
273
+ export class OtelAvgMinMax<Labels extends LabelsGeneric = NoLabels> implements IAvgMinMax<Labels> {
274
+ private gauges: {
275
+ avg: ObservableGauge;
276
+ min: ObservableGauge;
277
+ max: ObservableGauge;
278
+ };
279
+
280
+ private currentValues: number[] = [];
281
+ private labeledValues: Map<string, number[]> = new Map();
282
+
237
283
  constructor(
238
284
  private logger: Logger,
239
- _meter: Meter,
240
- _name: string, // MetricsType must be registered in the aztec labels registry
241
- _help: string,
242
- _buckets: number[] = [],
243
- _labelNames: Array<keyof Labels> = [],
244
- ) {}
245
-
246
- // Overload signatures
247
- observe(_value: number): void;
248
- observe(_labels: Labels, _value: number): void;
249
- observe(_valueOrLabels: number | Labels, _value?: number): void {}
250
-
251
- startTimer(_labels?: Labels): (_labels?: Labels) => number {
252
- return () => 0;
285
+ meter: Meter,
286
+ name: string,
287
+ help: string,
288
+ private labelNames: Array<keyof Labels> = [],
289
+ ) {
290
+ // Create three separate gauges for avg, min, and max
291
+ this.gauges = {
292
+ avg: meter.createObservableGauge(`${name}_avg` as MetricsType, {
293
+ description: `${help} (average)`,
294
+ }),
295
+ min: meter.createObservableGauge(`${name}_min` as MetricsType, {
296
+ description: `${help} (minimum)`,
297
+ }),
298
+ max: meter.createObservableGauge(`${name}_max` as MetricsType, {
299
+ description: `${help} (maximum)`,
300
+ }),
301
+ };
302
+
303
+ // Register callbacks for each gauge
304
+ this.gauges.avg.addCallback(this.observeAvg.bind(this));
305
+ this.gauges.min.addCallback(this.observeMin.bind(this));
306
+ this.gauges.max.addCallback(this.observeMax.bind(this));
253
307
  }
254
308
 
309
+ /**
310
+ * Sets the values for calculating avg, min, max
311
+ * @param values - Array of values
312
+ */
313
+ set(values: number[]): void;
314
+ /**
315
+ * Sets the values for calculating avg, min, max with labels
316
+ * @param labels - Labels object
317
+ * @param values - Array of values
318
+ */
319
+ set(labels: Labels, values: number[]): void;
320
+ set(labelsOrValues: number[] | Labels, values?: number[]): void {
321
+ if (Array.isArray(labelsOrValues)) {
322
+ this.currentValues = labelsOrValues;
323
+ return;
324
+ } else {
325
+ validateLabels(labelsOrValues, this.labelNames, 'AvgMinMax');
326
+ const labelKey = JSON.stringify(labelsOrValues);
327
+ this.labeledValues.set(labelKey, values || []);
328
+ }
329
+ }
330
+
331
+ /**
332
+ * Resets all stored values
333
+ */
255
334
  reset(): void {
256
- // OpenTelemetry histograms cannot be reset, but we implement the interface
257
- this.logger.warn('OpenTelemetry histograms cannot be reset');
335
+ this.currentValues = [];
336
+ this.labeledValues.clear();
337
+ }
338
+
339
+ /**
340
+ * General function to observe an aggregation
341
+ * @param result - Observer result
342
+ * @param aggregateFn - Function that calculates the aggregation
343
+ */
344
+ private observeAggregation(result: any, aggregateFn: (arr: number[]) => number): void {
345
+ // Observe unlabeled values
346
+ if (this.currentValues.length > 0) {
347
+ result.observe(aggregateFn(this.currentValues));
348
+ }
349
+
350
+ // Observe labeled values
351
+ for (const [labelStr, values] of this.labeledValues.entries()) {
352
+ if (values.length > 0) {
353
+ const labels = parseLabelsSafely(labelStr, this.logger);
354
+ if (labels) {
355
+ result.observe(aggregateFn(values), labels);
356
+ }
357
+ }
358
+ }
359
+ }
360
+
361
+ private observeAvg(result: any): void {
362
+ this.observeAggregation(result, arr => arr.reduce((sum, val) => sum + val, 0) / arr.length);
363
+ }
364
+
365
+ private observeMin(result: any): void {
366
+ this.observeAggregation(result, arr => Math.min.apply(null, arr));
367
+ }
368
+
369
+ private observeMax(result: any): void {
370
+ this.observeAggregation(result, arr => Math.max.apply(null, arr));
258
371
  }
259
372
  }
260
373
 
261
374
  /**
262
- * Noop implementation of an AvgMinMax collector
375
+ * Validates that provided labels match the expected schema
376
+ * @param labels - Labels object to validate
377
+ * @param labelNames - Array of allowed label names
378
+ * @param metricType - Type of metric for error message ('Gauge', 'Histogram', 'AvgMinMax')
379
+ * @throws Error if invalid labels are provided
263
380
  */
264
- class NoopOtelAvgMinMax<Labels extends LabelsGeneric = NoLabels> implements IAvgMinMax<Labels> {
265
- constructor(
266
- private _logger: Logger,
267
- _meter: Meter,
268
- _name: string, // MetricsType must be registered in the aztec labels registry
269
- _help: string,
270
- _labelNames: Array<keyof Labels> = [],
271
- ) {}
272
-
273
- set(_values: number[]): void;
274
- set(_labels: Labels, _values: number[]): void;
275
- set(_valueOrLabels: number[] | Labels, _values?: number[]): void {}
276
-
277
- reset(): void {}
381
+ function validateLabels<Labels extends LabelsGeneric>(
382
+ labels: Labels,
383
+ labelNames: Array<keyof Labels>,
384
+ metricType: string,
385
+ ): void {
386
+ if (labelNames.length === 0) {
387
+ throw new Error(`${metricType} was initialized without labels support`);
388
+ }
389
+
390
+ for (const key of Object.keys(labels)) {
391
+ if (!labelNames.includes(key as keyof Labels)) {
392
+ throw new Error(`Invalid label key: ${key}`);
393
+ }
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Safely parses label string back to object
399
+ * @param labelStr - Stringified labels object
400
+ * @param logger - Logger instance for error reporting
401
+ * @returns Labels object or null if parsing fails
402
+ */
403
+ function parseLabelsSafely<Labels extends LabelsGeneric>(labelStr: string, logger: Logger): Labels | null {
404
+ try {
405
+ return JSON.parse(labelStr) as Labels;
406
+ } catch {
407
+ logger.error(`Failed to parse label string: ${labelStr}`);
408
+ return null;
409
+ }
278
410
  }
279
411
 
280
412
  /**
@@ -304,7 +436,7 @@ export class OtelMetricsAdapter extends Registry implements MetricsRegister {
304
436
  }
305
437
 
306
438
  histogram<Labels extends LabelsGeneric = NoLabels>(configuration: HistogramConfig<Labels>): IHistogram<Labels> {
307
- return new NoopOtelHistogram<Labels>(
439
+ return new OtelHistogram<Labels>(
308
440
  this.logger,
309
441
  this.meter,
310
442
  configuration.name as MetricsType,
@@ -315,7 +447,7 @@ export class OtelMetricsAdapter extends Registry implements MetricsRegister {
315
447
  }
316
448
 
317
449
  avgMinMax<Labels extends LabelsGeneric = NoLabels>(configuration: AvgMinMaxConfig<Labels>): IAvgMinMax<Labels> {
318
- return new NoopOtelAvgMinMax<Labels>(
450
+ return new OtelAvgMinMax<Labels>(
319
451
  this.logger,
320
452
  this.meter,
321
453
  configuration.name as MetricsType,
package/src/start.ts CHANGED
@@ -2,29 +2,30 @@ import { createLogger } from '@aztec/foundation/log';
2
2
 
3
3
  import type { TelemetryClientConfig } from './config.js';
4
4
  import { NoopTelemetryClient } from './noop.js';
5
- import { OpenTelemetryClient } from './otel.js';
6
5
  import type { TelemetryClient } from './telemetry.js';
7
6
 
8
7
  export * from './config.js';
9
8
 
10
- let initialised = false;
9
+ let initialized = false;
11
10
  let telemetry: TelemetryClient = new NoopTelemetryClient();
12
11
 
13
- export function initTelemetryClient(config: TelemetryClientConfig): TelemetryClient {
12
+ export async function initTelemetryClient(config: TelemetryClientConfig): Promise<TelemetryClient> {
14
13
  const log = createLogger('telemetry:client');
15
- if (initialised) {
14
+ if (initialized) {
16
15
  log.warn('Telemetry client has already been initialized once');
17
16
  return telemetry;
18
17
  }
19
18
 
20
- if (config.metricsCollectorUrl) {
19
+ if (config.metricsCollectorUrl || config.publicMetricsCollectorUrl) {
21
20
  log.info(`Using OpenTelemetry client with custom collector`);
21
+ // Lazy load OpenTelemetry to avoid loading heavy deps at startup
22
+ const { OpenTelemetryClient } = await import('./otel.js');
22
23
  telemetry = OpenTelemetryClient.createAndStart(config, log);
23
24
  } else {
24
25
  log.info('Using NoopTelemetryClient');
25
26
  }
26
27
 
27
- initialised = true;
28
+ initialized = true;
28
29
  return telemetry;
29
30
  }
30
31
 
package/src/telemetry.ts CHANGED
@@ -24,21 +24,49 @@ export { type Span, SpanStatusCode, ValueType } from '@opentelemetry/api';
24
24
 
25
25
  type ValuesOf<T> = T extends Record<string, infer U> ? U : never;
26
26
 
27
+ type AttributeNames = ValuesOf<typeof Attributes>;
28
+
29
+ /**
30
+ * This is a set of attributes that could lead to high cardinality in the metrics.
31
+ * If you find yourself wanting to capture this data in a metric consider if it makes sense to capture
32
+ * as the metric value instead of an attribute or consider logging instead.
33
+ *
34
+ * Think twice before removing an attribute from this list.
35
+ */
36
+ type BannedMetricAttributeNames = (typeof Attributes)[
37
+ | 'BLOCK_NUMBER'
38
+ | 'BLOCK_ARCHIVE'
39
+ | 'SLOT_NUMBER'
40
+ | 'BLOCK_PARENT'
41
+ | 'BLOCK_CANDIDATE_TXS_COUNT'
42
+ | 'BLOCK_TXS_COUNT'
43
+ | 'BLOCK_SIZE'
44
+ | 'EPOCH_SIZE'
45
+ | 'EPOCH_NUMBER'
46
+ | 'TX_HASH'
47
+ | 'PROVING_JOB_ID'
48
+ | 'P2P_ID'
49
+ | 'P2P_REQ_RESP_BATCH_REQUESTS_COUNT'
50
+ | 'TARGET_ADDRESS'
51
+ | 'MANA_USED'
52
+ | 'TOTAL_INSTRUCTIONS'];
53
+
27
54
  /** Global registry of attributes */
28
- type AttributesType = Partial<Record<ValuesOf<typeof Attributes>, AttributeValue>>;
29
- export type { AttributesType };
55
+ export type AttributesType = Partial<Record<AttributeNames, AttributeValue>>;
56
+
57
+ /** Subset of attributes allowed to be added to metrics */
58
+ export type MetricAttributesType = Partial<Record<Exclude<AttributeNames, BannedMetricAttributeNames>, AttributeValue>>;
30
59
 
31
60
  /** Global registry of metrics */
32
- type MetricsType = (typeof Metrics)[keyof typeof Metrics];
33
- export type { MetricsType };
61
+ export type MetricsType = (typeof Metrics)[keyof typeof Metrics];
34
62
 
35
- export type Gauge = OtelGauge<AttributesType>;
36
- export type Histogram = OtelHistogram<AttributesType>;
37
- export type UpDownCounter = OtelUpDownCounter<AttributesType>;
38
- export type ObservableGauge = OtelObservableGauge<AttributesType>;
39
- export type ObservableUpDownCounter = OtelObservableUpDownCounter<AttributesType>;
40
- export type ObservableResult = OtelObservableResult<AttributesType>;
41
- export type BatchObservableResult = OtelBatchObservableResult<AttributesType>;
63
+ export type Gauge = OtelGauge<MetricAttributesType>;
64
+ export type Histogram = OtelHistogram<MetricAttributesType>;
65
+ export type UpDownCounter = OtelUpDownCounter<MetricAttributesType>;
66
+ export type ObservableGauge = OtelObservableGauge<MetricAttributesType>;
67
+ export type ObservableUpDownCounter = OtelObservableUpDownCounter<MetricAttributesType>;
68
+ export type ObservableResult = OtelObservableResult<MetricAttributesType>;
69
+ export type BatchObservableResult = OtelBatchObservableResult<MetricAttributesType>;
42
70
 
43
71
  export type { Tracer };
44
72
 
@@ -122,6 +150,16 @@ export interface TelemetryClient {
122
150
  * Flushes the telemetry client.
123
151
  */
124
152
  flush(): Promise<void>;
153
+
154
+ /**
155
+ * Updates what telemetry is exported to the public collector
156
+ */
157
+ setExportedPublicTelemetry(prefixes: string[]): void;
158
+
159
+ /**
160
+ * Updates the roles that would share telemetry (if enabled)
161
+ */
162
+ setPublicTelemetryCollectFrom(roles: string[]): void;
125
163
  }
126
164
 
127
165
  /** Objects that adhere to this interface can use @trackSpan */
@@ -165,7 +203,7 @@ export function trackSpan<T extends Traceable, F extends (...args: any[]) => any
165
203
  // run originalMethod wrapped in an active span
166
204
  // "active" means the span will be alive for the duration of the function execution
167
205
  // 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-v18.x/docs/api/async_context.html
206
+ // behind the scenes this uses AsyncLocalStorage https://nodejs.org/dist/latest-v22.x/docs/api/async_context.html
169
207
  return this.tracer.startActiveSpan(name, async (span: Span) => {
170
208
  span.setAttributes(currentAttrs ?? {});
171
209
 
@@ -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-abtract-transport` does:
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;
@@ -15,38 +15,31 @@ import { ATTR_JSONRPC_METHOD, ATTR_JSONRPC_REQUEST_ID } from '../vendor/attribut
15
15
  * @returns A fetch function.
16
16
  */
17
17
  export function makeTracedFetch(retries: number[], defaultNoRetry: boolean, fetch = defaultFetch, log?: Logger) {
18
- return (
19
- host: string,
20
- rpcMethod: string,
21
- body: any,
22
- useApiEndpoints: boolean,
23
- extraHeaders: Record<string, string> = {},
24
- noRetry?: boolean,
25
- ) => {
18
+ return (host: string, body: unknown, extraHeaders: Record<string, string> = {}, noRetry?: boolean) => {
26
19
  const telemetry = getTelemetryClient();
27
- return telemetry
28
- .getTracer('fetch')
29
- .startActiveSpan(`JsonRpcClient.${rpcMethod}`, { kind: SpanKind.CLIENT }, async span => {
30
- try {
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();
20
+ return telemetry.getTracer('fetch').startActiveSpan(`JsonRpcClient`, { kind: SpanKind.CLIENT }, async span => {
21
+ try {
22
+ if (body && typeof body === 'object' && 'id' in body && typeof body.id === 'number') {
23
+ span.setAttribute(ATTR_JSONRPC_REQUEST_ID, body.id);
49
24
  }
50
- });
25
+ if (body && typeof body === 'object' && 'method' in body && typeof body.method === 'string') {
26
+ span.setAttribute(ATTR_JSONRPC_METHOD, body.method);
27
+ }
28
+ const headers = { ...extraHeaders };
29
+ propagation.inject(context.active(), headers);
30
+ return await retry(
31
+ () => fetch(host, body, headers, noRetry ?? defaultNoRetry),
32
+ `JsonRpcClient request to ${host}`,
33
+ makeBackoff(retries),
34
+ log,
35
+ false,
36
+ );
37
+ } catch (err: any) {
38
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err?.message ?? String(err) });
39
+ throw err;
40
+ } finally {
41
+ span.end();
42
+ }
43
+ });
51
44
  };
52
45
  }
@@ -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: Partial<SafeJsonRpcServerOptions> = {},
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' | 'getBlockHeader' | 'getL2Tips'>,
14
+ l2BlockSource: Pick<L2BlockSource, 'getPublishedBlocks' | 'getBlockHeader' | 'getL2Tips'>,
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?: number;
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"}