@aztec/telemetry-client 0.0.0-test.1 → 0.0.1-commit.5476d83
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 +24 -9
- package/dest/attributes.d.ts.map +1 -1
- package/dest/attributes.js +17 -8
- package/dest/bench.d.ts +4 -1
- package/dest/bench.d.ts.map +1 -1
- package/dest/bench.js +7 -0
- package/dest/config.d.ts +7 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +29 -1
- 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 +70 -0
- package/dest/lmdb_metrics.d.ts +4 -2
- package/dest/lmdb_metrics.d.ts.map +1 -1
- package/dest/lmdb_metrics.js +8 -0
- package/dest/metrics.d.ts +98 -13
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +98 -13
- package/dest/nodejs_metrics_monitor.d.ts +21 -0
- package/dest/nodejs_metrics_monitor.d.ts.map +1 -0
- package/dest/{event_loop_monitor.js → nodejs_metrics_monitor.js} +55 -12
- package/dest/noop.d.ts +4 -2
- package/dest/noop.d.ts.map +1 -1
- package/dest/noop.js +2 -0
- package/dest/otel.d.ts +9 -5
- package/dest/otel.d.ts.map +1 -1
- package/dest/otel.js +93 -19
- 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 +1 -1
- package/dest/otel_resource.d.ts +1 -1
- package/dest/otel_resource.d.ts.map +1 -1
- package/dest/otel_resource.js +31 -2
- package/dest/prom_otel_adapter.d.ts +58 -9
- package/dest/prom_otel_adapter.d.ts.map +1 -1
- package/dest/prom_otel_adapter.js +143 -43
- package/dest/start.d.ts +1 -1
- package/dest/start.js +4 -4
- package/dest/telemetry.d.ts +29 -12
- package/dest/telemetry.d.ts.map +1 -1
- package/dest/telemetry.js +1 -1
- 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 +2 -2
- package/dest/wrappers/fetch.d.ts.map +1 -1
- package/dest/wrappers/fetch.js +7 -5
- 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 +2 -2
- package/dest/wrappers/l2_block_stream.d.ts.map +1 -1
- package/package.json +19 -15
- package/src/attributes.ts +29 -11
- package/src/bench.ts +15 -5
- package/src/config.ts +54 -2
- package/src/index.ts +1 -0
- package/src/l1_metrics.ts +80 -0
- package/src/lmdb_metrics.ts +24 -3
- package/src/metrics.ts +118 -12
- package/src/{event_loop_monitor.ts → nodejs_metrics_monitor.ts} +59 -10
- package/src/noop.ts +4 -1
- package/src/otel.ts +80 -21
- package/src/otel_filter_metric_exporter.ts +47 -5
- package/src/otel_resource.ts +40 -2
- package/src/prom_otel_adapter.ts +191 -59
- package/src/start.ts +4 -4
- package/src/telemetry.ts +50 -12
- package/src/vendor/otel-pino-stream.ts +1 -4
- package/src/wrappers/fetch.ts +24 -31
- package/src/wrappers/json_rpc_server.ts +1 -1
- package/src/wrappers/l2_block_stream.ts +1 -1
- package/dest/event_loop_monitor.d.ts +0 -18
- 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
|
|
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.
|
|
107
|
-
this.eventLoopTime.add(Math.
|
|
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
|
|
110
|
-
obs
|
|
111
|
-
obs
|
|
112
|
-
obs
|
|
113
|
-
obs
|
|
114
|
-
obs
|
|
115
|
-
obs
|
|
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:
|
|
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 {
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
143
|
+
exporters: Array<PeriodicExportingMetricReaderOptions>,
|
|
135
144
|
): MeterProvider {
|
|
136
145
|
return new MeterProvider({
|
|
137
146
|
resource,
|
|
138
|
-
readers: options
|
|
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
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
}
|
package/src/otel_resource.ts
CHANGED
|
@@ -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: [
|
|
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
|
+
};
|