@aztec/telemetry-client 0.0.0-test.0 → 0.0.1-commit.21caa21

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 (82) hide show
  1. package/dest/attributes.d.ts +24 -9
  2. package/dest/attributes.d.ts.map +1 -1
  3. package/dest/attributes.js +17 -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 +98 -13
  20. package/dest/metrics.d.ts.map +1 -1
  21. package/dest/metrics.js +98 -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 +1 -1
  43. package/dest/start.js +4 -4
  44. package/dest/telemetry.d.ts +29 -12
  45. package/dest/telemetry.d.ts.map +1 -1
  46. package/dest/telemetry.js +1 -1
  47. package/dest/vendor/attributes.d.ts +1 -1
  48. package/dest/vendor/otel-pino-stream.d.ts +1 -2
  49. package/dest/vendor/otel-pino-stream.d.ts.map +1 -1
  50. package/dest/vendor/otel-pino-stream.js +2 -2
  51. package/dest/with_tracer.d.ts +1 -1
  52. package/dest/with_tracer.d.ts.map +1 -1
  53. package/dest/wrappers/fetch.d.ts +2 -2
  54. package/dest/wrappers/fetch.d.ts.map +1 -1
  55. package/dest/wrappers/fetch.js +7 -5
  56. package/dest/wrappers/index.d.ts +1 -1
  57. package/dest/wrappers/json_rpc_server.d.ts +2 -2
  58. package/dest/wrappers/json_rpc_server.d.ts.map +1 -1
  59. package/dest/wrappers/l2_block_stream.d.ts +2 -2
  60. package/dest/wrappers/l2_block_stream.d.ts.map +1 -1
  61. package/package.json +19 -15
  62. package/src/attributes.ts +29 -11
  63. package/src/bench.ts +15 -5
  64. package/src/config.ts +54 -2
  65. package/src/index.ts +1 -0
  66. package/src/l1_metrics.ts +80 -0
  67. package/src/lmdb_metrics.ts +24 -3
  68. package/src/metrics.ts +118 -12
  69. package/src/{event_loop_monitor.ts → nodejs_metrics_monitor.ts} +59 -10
  70. package/src/noop.ts +4 -1
  71. package/src/otel.ts +80 -21
  72. package/src/otel_filter_metric_exporter.ts +47 -5
  73. package/src/otel_resource.ts +40 -2
  74. package/src/prom_otel_adapter.ts +191 -59
  75. package/src/start.ts +4 -4
  76. package/src/telemetry.ts +50 -12
  77. package/src/vendor/otel-pino-stream.ts +1 -4
  78. package/src/wrappers/fetch.ts +24 -31
  79. package/src/wrappers/json_rpc_server.ts +1 -1
  80. package/src/wrappers/l2_block_stream.ts +1 -1
  81. package/dest/event_loop_monitor.d.ts +0 -18
  82. package/dest/event_loop_monitor.d.ts.map +0 -1
@@ -1,3 +1,4 @@
1
+ import type { Observable } from '@opentelemetry/api';
1
2
  import { type EventLoopUtilization, type IntervalHistogram, monitorEventLoopDelay, performance } from 'node:perf_hooks';
2
3
 
3
4
  import * as Attributes from './attributes.js';
@@ -13,7 +14,7 @@ import {
13
14
  /**
14
15
  * Detector for custom Aztec attributes
15
16
  */
16
- export class EventLoopMonitor {
17
+ export class NodejsMetricsMonitor {
17
18
  private eventLoopDelayGauges: {
18
19
  min: ObservableGauge;
19
20
  max: ObservableGauge;
@@ -24,6 +25,10 @@ export class EventLoopMonitor {
24
25
  p99: ObservableGauge;
25
26
  };
26
27
 
28
+ // skip `rss` because that's already tracked by @opentelemetry/host-metrics
29
+ // description of each field here https://nodejs.org/api/process.html#processmemoryusage
30
+ private memoryGauges: Record<Exclude<keyof NodeJS.MemoryUsage, 'rss'>, ObservableGauge>;
31
+
27
32
  private eventLoopUilization: ObservableGauge;
28
33
  private eventLoopTime: UpDownCounter;
29
34
 
@@ -62,6 +67,25 @@ export class EventLoopMonitor {
62
67
  });
63
68
 
64
69
  this.eventLoopDelay = monitorEventLoopDelay();
70
+
71
+ this.memoryGauges = {
72
+ heapUsed: meter.createObservableGauge(Metrics.NODEJS_MEMORY_HEAP_USAGE, {
73
+ unit: 'By',
74
+ description: 'Memory used by the V8 heap',
75
+ }),
76
+ heapTotal: meter.createObservableGauge(Metrics.NODEJS_MEMORY_HEAP_TOTAL, {
77
+ unit: 'By',
78
+ description: 'The max size the V8 heap can grow to',
79
+ }),
80
+ arrayBuffers: meter.createObservableGauge(Metrics.NODEJS_MEMORY_BUFFER_USAGE, {
81
+ unit: 'By',
82
+ description: 'Memory allocated for buffers (includes native memory used)',
83
+ }),
84
+ external: meter.createObservableGauge(Metrics.NODEJS_MEMORY_NATIVE_USAGE, {
85
+ unit: 'By',
86
+ description: 'Memory allocated for native C++ objects',
87
+ }),
88
+ };
65
89
  }
66
90
 
67
91
  start(): void {
@@ -74,6 +98,7 @@ export class EventLoopMonitor {
74
98
  this.meter.addBatchObservableCallback(this.measure, [
75
99
  this.eventLoopUilization,
76
100
  ...Object.values(this.eventLoopDelayGauges),
101
+ ...Object.values(this.memoryGauges),
77
102
  ]);
78
103
  }
79
104
 
@@ -84,6 +109,7 @@ export class EventLoopMonitor {
84
109
  this.meter.removeBatchObservableCallback(this.measure, [
85
110
  this.eventLoopUilization,
86
111
  ...Object.values(this.eventLoopDelayGauges),
112
+ ...Object.values(this.memoryGauges),
87
113
  ]);
88
114
  this.eventLoopDelay.disable();
89
115
  this.eventLoopDelay.reset();
@@ -91,6 +117,20 @@ export class EventLoopMonitor {
91
117
  }
92
118
 
93
119
  private measure = (obs: BatchObservableResult): void => {
120
+ this.measureMemoryUsage(obs);
121
+ this.measureEventLoopDelay(obs);
122
+ };
123
+
124
+ private measureMemoryUsage = (observer: BatchObservableResult) => {
125
+ const mem = process.memoryUsage();
126
+
127
+ observer.observe(this.memoryGauges.heapUsed, mem.heapUsed);
128
+ observer.observe(this.memoryGauges.heapTotal, mem.heapTotal);
129
+ observer.observe(this.memoryGauges.arrayBuffers, mem.arrayBuffers);
130
+ observer.observe(this.memoryGauges.external, mem.external);
131
+ };
132
+
133
+ private measureEventLoopDelay = (obs: BatchObservableResult): void => {
94
134
  const newELU = performance.eventLoopUtilization();
95
135
  const delta = performance.eventLoopUtilization(newELU, this.lastELU);
96
136
  this.lastELU = newELU;
@@ -103,17 +143,26 @@ export class EventLoopMonitor {
103
143
  // - https://youtu.be/WetXnEPraYM
104
144
  obs.observe(this.eventLoopUilization, delta.utilization);
105
145
 
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' });
146
+ this.eventLoopTime.add(Math.trunc(delta.idle), { [Attributes.NODEJS_EVENT_LOOP_STATE]: 'idle' });
147
+ this.eventLoopTime.add(Math.trunc(delta.active), { [Attributes.NODEJS_EVENT_LOOP_STATE]: 'active' });
108
148
 
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)));
149
+ safeObserveInt(obs, this.eventLoopDelayGauges.min, this.eventLoopDelay.min);
150
+ safeObserveInt(obs, this.eventLoopDelayGauges.mean, this.eventLoopDelay.mean);
151
+ safeObserveInt(obs, this.eventLoopDelayGauges.max, this.eventLoopDelay.max);
152
+ safeObserveInt(obs, this.eventLoopDelayGauges.stddev, this.eventLoopDelay.stddev);
153
+ safeObserveInt(obs, this.eventLoopDelayGauges.p50, this.eventLoopDelay.percentile(50));
154
+ safeObserveInt(obs, this.eventLoopDelayGauges.p90, this.eventLoopDelay.percentile(90));
155
+ safeObserveInt(obs, this.eventLoopDelayGauges.p99, this.eventLoopDelay.percentile(99));
116
156
 
117
157
  this.eventLoopDelay.reset();
118
158
  };
119
159
  }
160
+
161
+ function safeObserveInt(observer: BatchObservableResult, metric: Observable, value: number, attrs?: object) {
162
+ // discard NaN, Infinity, -Infinity
163
+ if (!Number.isFinite(value)) {
164
+ return;
165
+ }
166
+
167
+ observer.observe(metric, Math.trunc(value), attrs);
168
+ }
package/src/noop.ts CHANGED
@@ -3,6 +3,9 @@ import { type Meter, type Span, type SpanContext, type Tracer, createNoopMeter }
3
3
  import type { TelemetryClient } from './telemetry.js';
4
4
 
5
5
  export class NoopTelemetryClient implements TelemetryClient {
6
+ setExportedPublicTelemetry(_prefixes: string[]): void {}
7
+ setPublicTelemetryCollectFrom(_roles: string[]): void {}
8
+
6
9
  getMeter(): Meter {
7
10
  return createNoopMeter();
8
11
  }
@@ -32,7 +35,7 @@ export class NoopTracer implements Tracer {
32
35
  return new NoopSpan();
33
36
  }
34
37
 
35
- startActiveSpan<F extends (...args: any[]) => any>(_name: string, ...args: (unknown | F)[]): ReturnType<F> {
38
+ startActiveSpan<F extends (...args: any[]) => any>(_name: string, ...args: unknown[]): ReturnType<F> {
36
39
  // there are three different signatures for startActiveSpan, grab the function, we don't care about the rest
37
40
  const fn = args.find(arg => typeof arg === 'function') as F;
38
41
  return fn(new NoopSpan());
package/src/otel.ts CHANGED
@@ -28,8 +28,8 @@ import { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace
28
28
  import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
29
29
 
30
30
  import type { TelemetryClientConfig } from './config.js';
31
- import { EventLoopMonitor } from './event_loop_monitor.js';
32
- import { OtelFilterMetricExporter } from './otel_filter_metric_exporter.js';
31
+ import { NodejsMetricsMonitor } from './nodejs_metrics_monitor.js';
32
+ import { OtelFilterMetricExporter, PublicOtelFilterMetricExporter } from './otel_filter_metric_exporter.js';
33
33
  import { registerOtelLoggerProvider } from './otel_logger_provider.js';
34
34
  import { getOtelResource } from './otel_resource.js';
35
35
  import type { TelemetryClient } from './telemetry.js';
@@ -38,7 +38,7 @@ export type OpenTelemetryClientFactory = (resource: IResource, log: Logger) => O
38
38
 
39
39
  export class OpenTelemetryClient implements TelemetryClient {
40
40
  hostMetrics: HostMetrics | undefined;
41
- eventLoopMonitor: EventLoopMonitor | undefined;
41
+ nodejsMetricsMonitor: NodejsMetricsMonitor | undefined;
42
42
  private meters: Map<string, Meter> = new Map<string, Meter>();
43
43
  private tracers: Map<string, Tracer> = new Map<string, Tracer>();
44
44
 
@@ -47,9 +47,18 @@ export class OpenTelemetryClient implements TelemetryClient {
47
47
  private meterProvider: MeterProvider,
48
48
  private traceProvider: TracerProvider,
49
49
  private loggerProvider: LoggerProvider | undefined,
50
+ private publicMetricExporter: PublicOtelFilterMetricExporter | undefined,
50
51
  private log: Logger,
51
52
  ) {}
52
53
 
54
+ setExportedPublicTelemetry(metrics: string[]): void {
55
+ this.publicMetricExporter?.setMetricPrefixes(metrics);
56
+ }
57
+
58
+ setPublicTelemetryCollectFrom(roles: string[]): void {
59
+ this.publicMetricExporter?.setAllowedRoles(roles);
60
+ }
61
+
53
62
  getMeter(name: string): Meter {
54
63
  let meter = this.meters.get(name);
55
64
  if (!meter) {
@@ -91,12 +100,12 @@ export class OpenTelemetryClient implements TelemetryClient {
91
100
  meterProvider: this.meterProvider,
92
101
  });
93
102
 
94
- this.eventLoopMonitor = new EventLoopMonitor(
103
+ this.nodejsMetricsMonitor = new NodejsMetricsMonitor(
95
104
  this.meterProvider.getMeter(this.resource.attributes[ATTR_SERVICE_NAME] as string),
96
105
  );
97
106
 
98
107
  this.hostMetrics.start();
99
- this.eventLoopMonitor.start();
108
+ this.nodejsMetricsMonitor.start();
100
109
  }
101
110
 
102
111
  public isEnabled() {
@@ -112,7 +121,7 @@ export class OpenTelemetryClient implements TelemetryClient {
112
121
  }
113
122
 
114
123
  public async stop() {
115
- this.eventLoopMonitor?.stop();
124
+ this.nodejsMetricsMonitor?.stop();
116
125
 
117
126
  const flushAndShutdown = async (provider?: { forceFlush: () => Promise<void>; shutdown: () => Promise<void> }) => {
118
127
  if (!provider) {
@@ -131,16 +140,31 @@ export class OpenTelemetryClient implements TelemetryClient {
131
140
 
132
141
  public static createMeterProvider(
133
142
  resource: IResource,
134
- options: Partial<PeriodicExportingMetricReaderOptions>,
143
+ exporters: Array<PeriodicExportingMetricReaderOptions>,
135
144
  ): MeterProvider {
136
145
  return new MeterProvider({
137
146
  resource,
138
- readers: options.exporter
139
- ? [new PeriodicExportingMetricReader(options as PeriodicExportingMetricReaderOptions)]
140
- : [],
147
+ readers: exporters.map(options => new PeriodicExportingMetricReader(options)),
141
148
 
142
149
  views: [
143
150
  // Every histogram matching the selector (type + unit) gets these custom buckets assigned
151
+ new View({
152
+ instrumentType: InstrumentType.HISTOGRAM,
153
+ instrumentUnit: 'Mmana',
154
+ aggregation: new ExplicitBucketHistogramAggregation(
155
+ [0.1, 0.5, 1, 2, 4, 8, 10, 25, 50, 100, 500, 1000, 5000, 10000],
156
+ true,
157
+ ),
158
+ }),
159
+ new View({
160
+ instrumentType: InstrumentType.HISTOGRAM,
161
+ instrumentUnit: 'tx',
162
+ aggregation: new ExplicitBucketHistogramAggregation(
163
+ // TPS
164
+ [0.1 * 36, 0.2 * 36, 0.5 * 36, 1 * 36, 2 * 36, 5 * 36, 10 * 36, 15 * 36].map(Math.ceil),
165
+ true,
166
+ ),
167
+ }),
144
168
  new View({
145
169
  instrumentType: InstrumentType.HISTOGRAM,
146
170
  instrumentUnit: 's',
@@ -257,20 +281,55 @@ export class OpenTelemetryClient implements TelemetryClient {
257
281
 
258
282
  tracerProvider.register();
259
283
 
260
- const meterProvider = OpenTelemetryClient.createMeterProvider(resource, {
261
- exporter: config.metricsCollectorUrl
262
- ? new OtelFilterMetricExporter(
263
- new OTLPMetricExporter({ url: config.metricsCollectorUrl.href }),
264
- config.otelExcludeMetrics ?? [],
265
- )
266
- : undefined,
267
- exportTimeoutMillis: config.otelExportTimeoutMs,
268
- exportIntervalMillis: config.otelCollectIntervalMs,
269
- });
284
+ const exporters: PeriodicExportingMetricReaderOptions[] = [];
285
+ if (config.metricsCollectorUrl) {
286
+ // Default to a blacklist that is empty (allow all metrics)
287
+ let filter: string[] = [];
288
+ let mode: 'allow' | 'deny' = 'deny';
289
+ if (config.otelExcludeMetrics.length > 0) {
290
+ // Implement a blacklist as specified in config
291
+ log.info(`Excluding metrics from export: ${config.otelExcludeMetrics}`);
292
+ filter = config.otelExcludeMetrics;
293
+ mode = 'deny';
294
+ } else if (config.otelIncludeMetrics.length > 0) {
295
+ // Implement a whitelist as specified in config
296
+ log.info(`Including only specified metrics for export: ${config.otelIncludeMetrics}`);
297
+ filter = config.otelIncludeMetrics;
298
+ mode = 'allow';
299
+ }
300
+ exporters.push({
301
+ exporter: new OtelFilterMetricExporter(
302
+ new OTLPMetricExporter({ url: config.metricsCollectorUrl.href }),
303
+ filter,
304
+ mode,
305
+ ),
306
+ exportTimeoutMillis: config.otelExportTimeoutMs,
307
+ exportIntervalMillis: config.otelCollectIntervalMs,
308
+ });
309
+ }
310
+
311
+ let publicExporter: PublicOtelFilterMetricExporter | undefined;
312
+ if (config.publicMetricsCollectorUrl && !config.publicMetricsOptOut) {
313
+ log.info(`Exporting public metrics: ${config.publicIncludeMetrics}`, {
314
+ publicMetrics: config.publicIncludeMetrics,
315
+ collectorUrl: config.publicMetricsCollectorUrl,
316
+ });
317
+ publicExporter = new PublicOtelFilterMetricExporter(
318
+ config.publicMetricsCollectFrom,
319
+ new OTLPMetricExporter({ url: config.publicMetricsCollectorUrl.href }),
320
+ config.publicIncludeMetrics,
321
+ );
322
+ exporters.push({
323
+ exporter: publicExporter,
324
+ exportTimeoutMillis: config.otelExportTimeoutMs,
325
+ exportIntervalMillis: config.otelCollectIntervalMs,
326
+ });
327
+ }
270
328
 
329
+ const meterProvider = OpenTelemetryClient.createMeterProvider(resource, exporters);
271
330
  const loggerProvider = registerOtelLoggerProvider(resource, config.logsCollectorUrl);
272
331
 
273
- return new OpenTelemetryClient(resource, meterProvider, tracerProvider, loggerProvider, log);
332
+ return new OpenTelemetryClient(resource, meterProvider, tracerProvider, loggerProvider, publicExporter, log);
274
333
  };
275
334
  }
276
335
 
@@ -1,8 +1,14 @@
1
- import type { ExportResult } from '@opentelemetry/core';
1
+ import { type ExportResult, ExportResultCode } from '@opentelemetry/core';
2
2
  import type { MetricData, PushMetricExporter, ResourceMetrics } from '@opentelemetry/sdk-metrics';
3
3
 
4
+ import { AZTEC_NODE_ROLE } from './attributes.js';
5
+
4
6
  export class OtelFilterMetricExporter implements PushMetricExporter {
5
- constructor(private readonly exporter: PushMetricExporter, private readonly excludeMetricPrefixes: string[]) {
7
+ constructor(
8
+ private readonly exporter: PushMetricExporter,
9
+ private metricPrefix: string[],
10
+ private readonly filter: 'allow' | 'deny' = 'deny',
11
+ ) {
6
12
  if (exporter.selectAggregation) {
7
13
  (this as PushMetricExporter).selectAggregation = exporter.selectAggregation.bind(exporter);
8
14
  }
@@ -23,9 +29,17 @@ export class OtelFilterMetricExporter implements PushMetricExporter {
23
29
  }
24
30
 
25
31
  private filterMetrics(metrics: MetricData[]): MetricData[] {
26
- return metrics.filter(
27
- metric => !this.excludeMetricPrefixes.some(prefix => metric.descriptor.name.startsWith(prefix)),
28
- );
32
+ return metrics.filter(metric => {
33
+ const matched = this.metricPrefix.some(prefix => metric.descriptor.name.startsWith(prefix));
34
+
35
+ if (this.filter === 'deny') {
36
+ return !matched;
37
+ }
38
+
39
+ if (this.filter === 'allow') {
40
+ return matched;
41
+ }
42
+ });
29
43
  }
30
44
 
31
45
  public forceFlush(): Promise<void> {
@@ -35,4 +49,32 @@ export class OtelFilterMetricExporter implements PushMetricExporter {
35
49
  public shutdown(): Promise<void> {
36
50
  return this.exporter.shutdown();
37
51
  }
52
+
53
+ public setMetricPrefixes(metrics: string[]) {
54
+ this.metricPrefix = metrics;
55
+ }
56
+ }
57
+
58
+ export class PublicOtelFilterMetricExporter extends OtelFilterMetricExporter {
59
+ constructor(
60
+ private allowedRoles: string[],
61
+ exporter: PushMetricExporter,
62
+ metricPrefix: string[],
63
+ ) {
64
+ super(exporter, metricPrefix, 'allow');
65
+ }
66
+
67
+ public override export(metrics: ResourceMetrics, resultCallback: (result: ExportResult) => void): void {
68
+ const role = String(metrics.resource.attributes[AZTEC_NODE_ROLE] ?? '');
69
+ if (!role || !this.allowedRoles.includes(role)) {
70
+ // noop
71
+ return resultCallback({ code: ExportResultCode.SUCCESS });
72
+ }
73
+
74
+ super.export(metrics, resultCallback);
75
+ }
76
+
77
+ public setAllowedRoles(roles: string[]) {
78
+ this.allowedRoles = roles;
79
+ }
38
80
  }
@@ -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
+ };