@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.
Files changed (97) hide show
  1. package/dest/attributes.d.ts +45 -10
  2. package/dest/attributes.d.ts.map +1 -1
  3. package/dest/attributes.js +28 -9
  4. package/dest/bench.d.ts +6 -1
  5. package/dest/bench.d.ts.map +1 -1
  6. package/dest/bench.js +31 -14
  7. package/dest/config.d.ts +9 -2
  8. package/dest/config.d.ts.map +1 -1
  9. package/dest/config.js +44 -8
  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 +54 -0
  16. package/dest/lmdb_metrics.d.ts +5 -3
  17. package/dest/lmdb_metrics.d.ts.map +1 -1
  18. package/dest/lmdb_metrics.js +7 -15
  19. package/dest/metric-utils.d.ts +24 -0
  20. package/dest/metric-utils.d.ts.map +1 -0
  21. package/dest/metric-utils.js +59 -0
  22. package/dest/metrics.d.ts +312 -122
  23. package/dest/metrics.d.ts.map +1 -1
  24. package/dest/metrics.js +1595 -120
  25. package/dest/monitored_batch_span_processor.d.ts +29 -0
  26. package/dest/monitored_batch_span_processor.d.ts.map +1 -0
  27. package/dest/monitored_batch_span_processor.js +70 -0
  28. package/dest/nodejs_metrics_monitor.d.ts +19 -0
  29. package/dest/nodejs_metrics_monitor.d.ts.map +1 -0
  30. package/dest/nodejs_metrics_monitor.js +115 -0
  31. package/dest/noop.d.ts +9 -4
  32. package/dest/noop.d.ts.map +1 -1
  33. package/dest/noop.js +34 -1
  34. package/dest/otel.d.ts +13 -7
  35. package/dest/otel.d.ts.map +1 -1
  36. package/dest/otel.js +204 -24
  37. package/dest/otel_filter_metric_exporter.d.ts +12 -4
  38. package/dest/otel_filter_metric_exporter.d.ts.map +1 -1
  39. package/dest/otel_filter_metric_exporter.js +38 -4
  40. package/dest/otel_logger_provider.d.ts +1 -1
  41. package/dest/otel_propagation.d.ts +3 -1
  42. package/dest/otel_propagation.d.ts.map +1 -1
  43. package/dest/otel_propagation.js +49 -1
  44. package/dest/otel_resource.d.ts +1 -1
  45. package/dest/otel_resource.d.ts.map +1 -1
  46. package/dest/otel_resource.js +43 -2
  47. package/dest/prom_otel_adapter.d.ts +61 -12
  48. package/dest/prom_otel_adapter.d.ts.map +1 -1
  49. package/dest/prom_otel_adapter.js +157 -48
  50. package/dest/start.d.ts +3 -2
  51. package/dest/start.d.ts.map +1 -1
  52. package/dest/start.js +8 -7
  53. package/dest/telemetry.d.ts +63 -34
  54. package/dest/telemetry.d.ts.map +1 -1
  55. package/dest/telemetry.js +47 -24
  56. package/dest/vendor/attributes.d.ts +1 -1
  57. package/dest/vendor/otel-pino-stream.d.ts +1 -2
  58. package/dest/vendor/otel-pino-stream.d.ts.map +1 -1
  59. package/dest/vendor/otel-pino-stream.js +2 -2
  60. package/dest/with_tracer.d.ts +1 -1
  61. package/dest/with_tracer.d.ts.map +1 -1
  62. package/dest/wrappers/fetch.d.ts +3 -3
  63. package/dest/wrappers/fetch.d.ts.map +1 -1
  64. package/dest/wrappers/fetch.js +9 -6
  65. package/dest/wrappers/index.d.ts +1 -1
  66. package/dest/wrappers/json_rpc_server.d.ts +2 -2
  67. package/dest/wrappers/json_rpc_server.d.ts.map +1 -1
  68. package/dest/wrappers/l2_block_stream.d.ts +4 -3
  69. package/dest/wrappers/l2_block_stream.d.ts.map +1 -1
  70. package/dest/wrappers/l2_block_stream.js +385 -11
  71. package/package.json +21 -15
  72. package/src/attributes.ts +59 -12
  73. package/src/bench.ts +37 -15
  74. package/src/config.ts +76 -9
  75. package/src/index.ts +1 -0
  76. package/src/l1_metrics.ts +65 -0
  77. package/src/lmdb_metrics.ts +24 -24
  78. package/src/metric-utils.ts +75 -0
  79. package/src/metrics.ts +1679 -145
  80. package/src/monitored_batch_span_processor.ts +93 -0
  81. package/src/nodejs_metrics_monitor.ts +135 -0
  82. package/src/noop.ts +65 -4
  83. package/src/otel.ts +193 -28
  84. package/src/otel_filter_metric_exporter.ts +47 -5
  85. package/src/otel_propagation.ts +42 -1
  86. package/src/otel_resource.ts +57 -2
  87. package/src/prom_otel_adapter.ts +195 -70
  88. package/src/start.ts +17 -8
  89. package/src/telemetry.ts +152 -76
  90. package/src/vendor/otel-pino-stream.ts +1 -4
  91. package/src/wrappers/fetch.ts +32 -33
  92. package/src/wrappers/json_rpc_server.ts +1 -1
  93. package/src/wrappers/l2_block_stream.ts +3 -2
  94. package/dest/event_loop_monitor.d.ts +0 -18
  95. package/dest/event_loop_monitor.d.ts.map +0 -1
  96. package/dest/event_loop_monitor.js +0 -93
  97. package/src/event_loop_monitor.ts +0 -119
package/package.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/telemetry-client",
3
+ "version": "0.0.1-commit.017a351",
3
4
  "inherits": [
4
5
  "../package.common.json"
5
6
  ],
@@ -7,18 +8,18 @@
7
8
  "exports": {
8
9
  ".": "./dest/index.js",
9
10
  "./bench": "./dest/bench.js",
11
+ "./config": "./dest/config.js",
12
+ "./start": "./dest/start.js",
10
13
  "./otel-pino-stream": "./dest/vendor/otel-pino-stream.js"
11
14
  },
12
15
  "scripts": {
13
- "build": "yarn clean && tsc -b",
14
- "build:dev": "tsc -b --watch",
16
+ "build": "yarn clean && ../scripts/tsc.sh",
17
+ "build:dev": "../scripts/tsc.sh --watch",
15
18
  "clean": "rm -rf ./dest .tsbuildinfo",
16
- "formatting": "run -T prettier --check ./src && run -T eslint ./src",
17
- "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
18
19
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
19
20
  },
20
21
  "engines": {
21
- "node": ">=18"
22
+ "node": ">=20.10"
22
23
  },
23
24
  "files": [
24
25
  "dest",
@@ -26,15 +27,15 @@
26
27
  "!*.test.*"
27
28
  ],
28
29
  "dependencies": {
29
- "@aztec/foundation": "0.0.0-test.1",
30
- "@aztec/stdlib": "0.0.0-test.1",
30
+ "@aztec/foundation": "0.0.1-commit.017a351",
31
+ "@aztec/stdlib": "0.0.1-commit.017a351",
31
32
  "@opentelemetry/api": "^1.9.0",
32
33
  "@opentelemetry/api-logs": "^0.55.0",
33
34
  "@opentelemetry/core": "^1.28.0",
34
35
  "@opentelemetry/exporter-logs-otlp-http": "^0.55.0",
35
36
  "@opentelemetry/exporter-metrics-otlp-http": "^0.55.0",
36
37
  "@opentelemetry/exporter-trace-otlp-http": "^0.55.0",
37
- "@opentelemetry/host-metrics": "^0.35.4",
38
+ "@opentelemetry/host-metrics": "^0.36.2",
38
39
  "@opentelemetry/otlp-exporter-base": "^0.55.0",
39
40
  "@opentelemetry/resource-detector-gcp": "^0.32.0",
40
41
  "@opentelemetry/resources": "^1.28.0",
@@ -42,15 +43,17 @@
42
43
  "@opentelemetry/sdk-metrics": "^1.28.0",
43
44
  "@opentelemetry/sdk-trace-node": "^1.28.0",
44
45
  "@opentelemetry/semantic-conventions": "^1.28.0",
45
- "prom-client": "^15.1.3"
46
+ "prom-client": "^15.1.3",
47
+ "viem": "npm:@aztec/viem@2.38.2"
46
48
  },
47
49
  "devDependencies": {
48
- "@jest/globals": "^29.5.0",
49
- "@types/jest": "^29.5.0",
50
+ "@jest/globals": "^30.0.0",
51
+ "@types/jest": "^30.0.0",
50
52
  "@types/koa": "^2.15.0",
51
- "jest": "^29.5.0",
53
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
54
+ "jest": "^30.0.0",
52
55
  "ts-node": "^10.9.1",
53
- "typescript": "^5.0.4"
56
+ "typescript": "^5.3.3"
54
57
  },
55
58
  "jest": {
56
59
  "extensionsToTreatAsEsm": [
@@ -83,7 +86,10 @@
83
86
  "testTimeout": 120000,
84
87
  "setupFiles": [
85
88
  "../../foundation/src/jest/setup.mjs"
89
+ ],
90
+ "testEnvironment": "../../foundation/src/jest/env.mjs",
91
+ "setupFilesAfterEnv": [
92
+ "../../foundation/src/jest/setupAfterEnv.mjs"
86
93
  ]
87
- },
88
- "version": "0.0.0-test.1"
94
+ }
89
95
  }
package/src/attributes.ts CHANGED
@@ -14,36 +14,41 @@
14
14
  * @see {@link https://opentelemetry.io/docs/specs/semconv/general/attribute-naming/}
15
15
  */
16
16
 
17
+ /** The host of an HTTP request */
18
+ export const HTTP_REQUEST_HOST = 'http.header.request.host';
19
+ export const HTTP_RESPONSE_STATUS_CODE = 'http.response.status_code';
20
+
17
21
  /** The Aztec network identifier */
18
22
  export const NETWORK_NAME = 'aztec.network_name';
19
23
 
24
+ export const AZTEC_NODE_ROLE = 'aztec.node_role';
25
+ export const AZTEC_ROLLUP_VERSION = 'aztec.rollup_version';
26
+ export const AZTEC_ROLLUP_ADDRESS = 'aztec.rollup_address';
27
+ export const AZTEC_REGISTRY_ADDRESS = 'aztec.registry_address';
28
+
20
29
  /**
21
30
  * The name of the protocol circuit being run (e.g. public-kernel-setup or base-rollup)
22
31
  * @see {@link @aztec/stdlib/stats:CircuitName}
23
32
  */
24
33
  export const PROTOCOL_CIRCUIT_NAME = 'aztec.circuit.protocol_circuit_name';
25
34
 
26
- /**
27
- * The type of protocol circuit being run: server or client
28
- */
29
- export const PROTOCOL_CIRCUIT_TYPE = 'aztec.circuit.protocol_circuit_type';
30
-
31
35
  /**
32
36
  * For an app circuit, the contract:function being run (e.g. Token:transfer)
33
37
  */
34
38
  export const APP_CIRCUIT_NAME = 'aztec.circuit.app_circuit_name';
35
39
 
36
- /**
37
- * The type of app circuit being run: server or client
38
- */
39
- export const APP_CIRCUIT_TYPE = 'aztec.circuit.app_circuit_type';
40
-
41
40
  /** The block archive */
42
41
  export const BLOCK_ARCHIVE = 'aztec.block.archive';
43
42
  /** The block number */
44
43
  export const BLOCK_NUMBER = 'aztec.block.number';
44
+ /** The L2 block hash */
45
+ export const BLOCK_HASH = 'aztec.block.hash';
45
46
  /** The slot number */
46
47
  export const SLOT_NUMBER = 'aztec.slot.number';
48
+ /** Whether an event happened before or after a slot boundary. */
49
+ export const SLOT_BOUNDARY_SIDE = 'aztec.slot_boundary_side';
50
+ /** The checkpoint number */
51
+ export const CHECKPOINT_NUMBER = 'aztec.checkpoint.number';
47
52
  /** The parent's block number */
48
53
  export const BLOCK_PARENT = 'aztec.block.parent';
49
54
  /** How many txs are being processed to build this block */
@@ -70,6 +75,8 @@ export const ERROR_TYPE = 'aztec.error_type';
70
75
  export const L1_TX_TYPE = 'aztec.l1.tx_type';
71
76
  /** The L1 address of the entity that sent a transaction to L1 */
72
77
  export const L1_SENDER = 'aztec.l1.sender';
78
+ /** The L1 address receiving rewards */
79
+ export const COINBASE = 'aztec.coinbase';
73
80
  /** The phase of the transaction */
74
81
  export const TX_PHASE_NAME = 'aztec.tx.phase_name';
75
82
  /** The reason for disconnecting a peer */
@@ -78,24 +85,30 @@ export const P2P_GOODBYE_REASON = 'aztec.p2p.goodbye.reason';
78
85
  export const PROVING_JOB_TYPE = 'aztec.proving.job_type';
79
86
  /** The proving job id */
80
87
  export const PROVING_JOB_ID = 'aztec.proving.job_id';
81
-
88
+ /** Merkle tree name */
82
89
  export const MERKLE_TREE_NAME = 'aztec.merkle_tree.name';
83
90
  /** The prover-id in a root rollup proof. */
84
91
  export const ROLLUP_PROVER_ID = 'aztec.rollup.prover_id';
85
92
  /** Whether the proof submission was timed out (delayed more than 20 min) */
86
93
  export const PROOF_TIMED_OUT = 'aztec.proof.timed_out';
94
+ /** Status of the validator (eg proposer, in-committee, none) */
95
+ export const VALIDATOR_STATUS = 'aztec.validator_status';
87
96
 
88
97
  export const P2P_ID = 'aztec.p2p.id';
89
98
  export const P2P_REQ_RESP_PROTOCOL = 'aztec.p2p.req_resp.protocol';
90
- export const P2P_REQ_RESP_BATCH_REQUESTS_COUNT = 'aztec.p2p.req_resp.batch_requests_count';
99
+ /** The state of a peer (Healthy, Disconnect, Banned) */
100
+ export const P2P_PEER_SCORE_STATE = 'aztec.p2p.peer_score_state';
91
101
  export const POOL_NAME = 'aztec.pool.name';
92
102
 
103
+ export const PEER_ID = 'aztec.p2p.peer_id';
104
+
93
105
  export const SEQUENCER_STATE = 'aztec.sequencer.state';
94
106
 
95
107
  export const SIMULATOR_PHASE = 'aztec.simulator.phase';
96
108
  export const TARGET_ADDRESS = 'aztec.address.target';
97
109
  export const SENDER_ADDRESS = 'aztec.address.sender';
98
110
  export const MANA_USED = 'aztec.mana.used';
111
+ export const TOTAL_INSTRUCTIONS = 'aztec.total_instructions';
99
112
 
100
113
  /** Whether a sync process is the initial run, which is usually slower than iterative ones. */
101
114
  export const INITIAL_SYNC = 'aztec.initial_sync';
@@ -113,3 +126,37 @@ export const GAS_DIMENSION = 'aztec.gas_dimension';
113
126
  export const WORLD_STATE_REQUEST_TYPE = 'aztec.world_state_request';
114
127
 
115
128
  export const NODEJS_EVENT_LOOP_STATE = 'nodejs.eventloop.state';
129
+
130
+ export const TOPIC_NAME = 'aztec.gossip.topic_name';
131
+
132
+ /** The reason a transaction was evicted from the tx pool */
133
+ export const TX_POOL_EVICTION_REASON = 'aztec.mempool.eviction_reason';
134
+
135
+ export const TX_COLLECTION_METHOD = 'aztec.tx_collection.method';
136
+
137
+ /** Scope of L1 transaction (sequencer, prover, or other) */
138
+ export const L1_TX_SCOPE = 'aztec.l1_tx.scope';
139
+
140
+ /** Generic error type attribute */
141
+ export const IS_COMMITTEE_MEMBER = 'aztec.is_committee_member';
142
+
143
+ /** Fisherman fee analysis strategy identifier */
144
+ export const FISHERMAN_FEE_STRATEGY_ID = 'aztec.fisherman.strategy_id';
145
+
146
+ /** Whether the analyzed block reached 100% blob capacity */
147
+ export const BLOCK_FULL = 'aztec.block_full';
148
+
149
+ /** The L1 transaction target for block proposal */
150
+ export const L1_BLOCK_PROPOSAL_TX_TARGET = 'aztec.l1.block_proposal_tx_target';
151
+
152
+ /** Whether tracing methods were used to extract block proposal data */
153
+ export const L1_BLOCK_PROPOSAL_USED_TRACE = 'aztec.l1.block_proposal_used_trace';
154
+
155
+ /** HA signer duty type (e.g., BLOCK_PROPOSAL, CHECKPOINT_ATTESTATION) */
156
+ export const HA_DUTY_TYPE = 'aztec.ha_signer.duty_type';
157
+
158
+ /** HA signer node identifier */
159
+ export const HA_NODE_ID = 'aztec.ha_signer.node_id';
160
+
161
+ /** The address of an attester (validator) participating in consensus */
162
+ export const ATTESTER_ADDRESS = 'aztec.attester.address';
package/src/bench.ts CHANGED
@@ -1,12 +1,14 @@
1
+ import { createLogger } from '@aztec/foundation/log';
2
+
1
3
  import type { BatchObservableCallback, Context, MetricOptions, Observable, ValueType } from '@opentelemetry/api';
2
4
 
5
+ import type { MetricDefinition } from './metrics.js';
3
6
  import { NoopTracer } from './noop.js';
4
7
  import type {
5
8
  AttributesType,
6
9
  Gauge,
7
10
  Histogram,
8
11
  Meter,
9
- MetricsType,
10
12
  ObservableGauge,
11
13
  ObservableUpDownCounter,
12
14
  TelemetryClient,
@@ -29,6 +31,14 @@ export type BenchmarkMetricsType = {
29
31
  export class BenchmarkTelemetryClient implements TelemetryClient {
30
32
  private meters: InMemoryPlainMeter[] = [];
31
33
 
34
+ constructor() {
35
+ const log = createLogger('telemetry:client');
36
+ log.info(`Using benchmark telemetry client`);
37
+ }
38
+
39
+ setExportedPublicTelemetry(_prefixes: string[]): void {}
40
+ setPublicTelemetryCollectFrom(_roles: string[]): void {}
41
+
32
42
  getMeter(name: string): Meter {
33
43
  const meter = new InMemoryPlainMeter(name);
34
44
  this.meters.push(meter);
@@ -51,6 +61,14 @@ export class BenchmarkTelemetryClient implements TelemetryClient {
51
61
  return true;
52
62
  }
53
63
 
64
+ getTraceContext(): string | undefined {
65
+ return undefined;
66
+ }
67
+
68
+ extractPropagatedContext() {
69
+ return undefined;
70
+ }
71
+
54
72
  getMeters(): BenchmarkMetricsType {
55
73
  return this.meters;
56
74
  }
@@ -69,30 +87,34 @@ class InMemoryPlainMeter implements Meter {
69
87
  this.metrics.forEach(metric => metric.clear());
70
88
  }
71
89
 
72
- createGauge(name: MetricsType, options?: MetricOptions | undefined): Gauge {
73
- return this.createMetric('gauge', name, options);
90
+ createGauge(metric: MetricDefinition): Gauge {
91
+ return this.createMetric('gauge', metric);
74
92
  }
75
93
 
76
- createObservableGauge(name: MetricsType, options?: MetricOptions | undefined): ObservableGauge {
77
- return this.createMetric('gauge', name, options);
94
+ createObservableGauge(metric: MetricDefinition): ObservableGauge {
95
+ return this.createMetric('gauge', metric);
78
96
  }
79
97
 
80
- createHistogram(name: MetricsType, options?: MetricOptions | undefined): Histogram {
81
- return this.createMetric('histogram', name, options);
98
+ createHistogram(metric: MetricDefinition, _extraOptions?: Partial<MetricOptions>): Histogram {
99
+ return this.createMetric('histogram', metric);
82
100
  }
83
101
 
84
- createUpDownCounter(name: MetricsType, options?: MetricOptions | undefined): UpDownCounter {
85
- return this.createMetric('counter', name, options);
102
+ createUpDownCounter(metric: MetricDefinition): UpDownCounter {
103
+ return this.createMetric('counter', metric);
86
104
  }
87
105
 
88
- createObservableUpDownCounter(name: MetricsType, options?: MetricOptions | undefined): ObservableUpDownCounter {
89
- return this.createMetric('counter', name, options);
106
+ createObservableUpDownCounter(metric: MetricDefinition): ObservableUpDownCounter {
107
+ return this.createMetric('counter', metric);
90
108
  }
91
109
 
92
- private createMetric(type: 'gauge' | 'counter' | 'histogram', name: string, options?: MetricOptions) {
93
- const metric = new InMemoryPlainMetric(type, name, options);
94
- this.metrics.push(metric);
95
- return metric;
110
+ private createMetric(type: 'gauge' | 'counter' | 'histogram', metric: MetricDefinition) {
111
+ const m = new InMemoryPlainMetric(type, metric.name, {
112
+ description: metric.description,
113
+ unit: metric.unit,
114
+ valueType: metric.valueType,
115
+ });
116
+ this.metrics.push(m);
117
+ return m;
96
118
  }
97
119
 
98
120
  addBatchObservableCallback(
package/src/config.ts CHANGED
@@ -1,41 +1,51 @@
1
- import { type ConfigMappingsType, getConfigFromMappings } from '@aztec/foundation/config';
1
+ import {
2
+ type ConfigMappingsType,
3
+ booleanConfigHelper,
4
+ getConfigFromMappings,
5
+ numberConfigHelper,
6
+ } from '@aztec/foundation/config';
2
7
 
3
8
  export interface TelemetryClientConfig {
4
9
  metricsCollectorUrl?: URL;
10
+ publicMetricsCollectorUrl?: URL;
11
+ publicIncludeMetrics: string[];
12
+ publicMetricsOptOut: boolean;
13
+ publicMetricsCollectFrom: string[];
5
14
  tracesCollectorUrl?: URL;
6
15
  logsCollectorUrl?: URL;
7
16
  otelCollectIntervalMs: number;
8
17
  otelExportTimeoutMs: number;
9
- otelExcludeMetrics?: string[];
18
+ otelExcludeMetrics: string[];
19
+ otelIncludeMetrics: string[];
20
+ otelMinTraceDurationMs: number;
21
+ otelBspMaxQueueSize: number;
10
22
  }
11
23
 
12
24
  export const telemetryClientConfigMappings: ConfigMappingsType<TelemetryClientConfig> = {
13
25
  metricsCollectorUrl: {
14
26
  env: 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT',
15
27
  description: 'The URL of the telemetry collector for metrics',
16
- parseEnv: (val: string) => val && new URL(val),
28
+ parseEnv: (val: string) => new URL(val),
17
29
  },
18
30
  tracesCollectorUrl: {
19
31
  env: 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT',
20
32
  description: 'The URL of the telemetry collector for traces',
21
- parseEnv: (val: string) => val && new URL(val),
33
+ parseEnv: (val: string) => new URL(val),
22
34
  },
23
35
  logsCollectorUrl: {
24
36
  env: 'OTEL_EXPORTER_OTLP_LOGS_ENDPOINT',
25
37
  description: 'The URL of the telemetry collector for logs',
26
- parseEnv: (val: string) => val && new URL(val),
38
+ parseEnv: (val: string) => new URL(val),
27
39
  },
28
40
  otelCollectIntervalMs: {
29
41
  env: 'OTEL_COLLECT_INTERVAL_MS',
30
42
  description: 'The interval at which to collect metrics',
31
- defaultValue: 60000, // Default extracted from otel client
32
- parseEnv: (val: string) => parseInt(val),
43
+ ...numberConfigHelper(60000),
33
44
  },
34
45
  otelExportTimeoutMs: {
35
46
  env: 'OTEL_EXPORT_TIMEOUT_MS',
36
47
  description: 'The timeout for exporting metrics',
37
- defaultValue: 30000, // Default extracted from otel client
38
- parseEnv: (val: string) => parseInt(val),
48
+ ...numberConfigHelper(30000),
39
49
  },
40
50
  otelExcludeMetrics: {
41
51
  env: 'OTEL_EXCLUDE_METRICS',
@@ -49,6 +59,63 @@ export const telemetryClientConfigMappings: ConfigMappingsType<TelemetryClientCo
49
59
  : [],
50
60
  defaultValue: [],
51
61
  },
62
+ otelMinTraceDurationMs: {
63
+ env: 'OTEL_MIN_TRACE_DURATION_MS',
64
+ description: 'The minimum successful trace duration to export in milliseconds. Set to 0 to export all traces.',
65
+ ...numberConfigHelper(10),
66
+ },
67
+ otelBspMaxQueueSize: {
68
+ env: 'OTEL_BSP_MAX_QUEUE_SIZE',
69
+ description: 'The maximum number of completed spans to queue before export.',
70
+ ...numberConfigHelper(2048),
71
+ },
72
+ otelIncludeMetrics: {
73
+ env: 'OTEL_INCLUDE_METRICS',
74
+ description: 'A list of metric prefixes to include in export (ignored if OTEL_EXCLUDE_METRICS is set)',
75
+ parseEnv: (val: string) =>
76
+ val
77
+ ? val
78
+ .split(',')
79
+ .map(s => s.trim())
80
+ .filter(s => s.length > 0)
81
+ : [],
82
+ defaultValue: [],
83
+ },
84
+
85
+ publicMetricsCollectorUrl: {
86
+ env: 'PUBLIC_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT',
87
+ description: 'A URL to publish a subset of metrics for public consumption',
88
+ parseEnv: (val: string) => new URL(val),
89
+ },
90
+ publicMetricsCollectFrom: {
91
+ env: 'PUBLIC_OTEL_COLLECT_FROM',
92
+ description: 'The role types to collect metrics from',
93
+ parseEnv: (val: string) =>
94
+ val
95
+ ? val
96
+ .split(',')
97
+ .map(s => s.trim())
98
+ .filter(s => s.length > 0)
99
+ : [],
100
+ defaultValue: [],
101
+ },
102
+ publicIncludeMetrics: {
103
+ env: 'PUBLIC_OTEL_INCLUDE_METRICS',
104
+ description: 'A list of metric prefixes to publicly export',
105
+ parseEnv: (val: string) =>
106
+ val
107
+ ? val
108
+ .split(',')
109
+ .map(s => s.trim())
110
+ .filter(s => s.length > 0)
111
+ : [],
112
+ defaultValue: [],
113
+ },
114
+ publicMetricsOptOut: {
115
+ env: 'PUBLIC_OTEL_OPT_OUT',
116
+ description: 'Whether to opt out of sharing optional telemetry',
117
+ ...booleanConfigHelper(true),
118
+ },
52
119
  };
53
120
 
54
121
  export function getConfigEnvVars(): TelemetryClientConfig {
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ export * as Attributes from './attributes.js';
4
4
  export * from './with_tracer.js';
5
5
  export * from './prom_otel_adapter.js';
6
6
  export * from './lmdb_metrics.js';
7
+ export * from './l1_metrics.js';
7
8
  export * from './wrappers/index.js';
8
9
  export * from './start.js';
9
10
  export * from './otel_propagation.js';
@@ -0,0 +1,65 @@
1
+ import type { EthAddress } from '@aztec/foundation/eth-address';
2
+
3
+ import { type Chain, type FallbackTransport, type Hex, type HttpTransport, type PublicClient, formatEther } from 'viem';
4
+
5
+ import { L1_SENDER } from './attributes.js';
6
+ import { L1_BALANCE_ETH, L1_BLOB_BASE_FEE_WEI, L1_BLOCK_HEIGHT, L1_GAS_PRICE_WEI } from './metrics.js';
7
+ import type { BatchObservableResult, Meter, ObservableGauge } from './telemetry.js';
8
+
9
+ export class L1Metrics {
10
+ private l1BlockHeight: ObservableGauge;
11
+ private l1BalanceEth: ObservableGauge;
12
+ private gasPriceWei: ObservableGauge;
13
+ private blobBaseFeeWei: ObservableGauge;
14
+ private addresses: Hex[];
15
+
16
+ constructor(
17
+ private meter: Meter,
18
+ private client: PublicClient<FallbackTransport<HttpTransport[]>, Chain>,
19
+ addresses: EthAddress[],
20
+ ) {
21
+ this.l1BlockHeight = meter.createObservableGauge(L1_BLOCK_HEIGHT);
22
+ this.l1BalanceEth = meter.createObservableGauge(L1_BALANCE_ETH);
23
+ this.gasPriceWei = meter.createObservableGauge(L1_GAS_PRICE_WEI);
24
+ this.blobBaseFeeWei = meter.createObservableGauge(L1_BLOB_BASE_FEE_WEI);
25
+
26
+ this.addresses = addresses.map(addr => addr.toString());
27
+ }
28
+
29
+ start() {
30
+ this.meter.addBatchObservableCallback(this.observe, [this.l1BalanceEth, this.l1BlockHeight]);
31
+ }
32
+
33
+ stop() {
34
+ this.meter.removeBatchObservableCallback(this.observe, [this.l1BalanceEth, this.l1BlockHeight]);
35
+ }
36
+
37
+ private observe = async (observer: BatchObservableResult) => {
38
+ const blockNumber = await this.client.getBlockNumber();
39
+ const ethBalances = await Promise.all(
40
+ this.addresses.map(address =>
41
+ this.client.getBalance({
42
+ address,
43
+ blockNumber,
44
+ }),
45
+ ),
46
+ );
47
+
48
+ const gasPrice = await this.client.getGasPrice();
49
+ const blobFee = await this.client.getBlobBaseFee();
50
+
51
+ observer.observe(this.l1BlockHeight, Number(blockNumber));
52
+ observer.observe(this.gasPriceWei, Number(gasPrice));
53
+ observer.observe(this.blobBaseFeeWei, Number(blobFee));
54
+
55
+ for (let i = 0; i < ethBalances.length; i++) {
56
+ const wei = ethBalances[i];
57
+ const address = this.addresses[i];
58
+ const eth = parseFloat(formatEther(wei, 'wei'));
59
+
60
+ observer.observe(this.l1BalanceEth, eth, {
61
+ [L1_SENDER]: address,
62
+ });
63
+ }
64
+ };
65
+ }
@@ -1,36 +1,35 @@
1
1
  import * as Metrics from './metrics.js';
2
- import {
3
- type AttributesType,
4
- type BatchObservableResult,
5
- type Meter,
6
- type ObservableGauge,
7
- ValueType,
8
- } from './telemetry.js';
2
+ import type { AttributesType, BatchObservableResult, Meter, ObservableGauge } from './telemetry.js';
9
3
 
10
- export type LmdbStatsCallback = () => Promise<{ mappingSize: number; numItems: number; actualSize: number }>;
4
+ export type LmdbStatsCallback = () => Promise<{
5
+ mappingSize: number;
6
+ physicalFileSize: number;
7
+ numItems: number;
8
+ actualSize: number;
9
+ }>;
11
10
 
12
11
  export class LmdbMetrics {
13
12
  private dbMapSize: ObservableGauge;
13
+ private dbPhysicalFileSize: ObservableGauge;
14
14
  private dbUsedSize: ObservableGauge;
15
15
  private dbNumItems: ObservableGauge;
16
16
 
17
- constructor(meter: Meter, private attributes?: AttributesType, private getStats?: LmdbStatsCallback) {
18
- this.dbMapSize = meter.createObservableGauge(Metrics.DB_MAP_SIZE, {
19
- description: 'LMDB Map Size',
20
- valueType: ValueType.INT,
21
- unit: 'By',
22
- });
23
- this.dbUsedSize = meter.createObservableGauge(Metrics.DB_USED_SIZE, {
24
- description: 'LMDB Used Size',
25
- valueType: ValueType.INT,
26
- unit: 'By',
27
- });
28
- this.dbNumItems = meter.createObservableGauge(Metrics.DB_NUM_ITEMS, {
29
- description: 'LMDB Num Items',
30
- valueType: ValueType.INT,
31
- });
17
+ constructor(
18
+ meter: Meter,
19
+ private attributes?: AttributesType,
20
+ private getStats?: LmdbStatsCallback,
21
+ ) {
22
+ this.dbMapSize = meter.createObservableGauge(Metrics.DB_MAP_SIZE);
23
+ this.dbPhysicalFileSize = meter.createObservableGauge(Metrics.DB_PHYSICAL_FILE_SIZE);
24
+ this.dbUsedSize = meter.createObservableGauge(Metrics.DB_USED_SIZE);
25
+ this.dbNumItems = meter.createObservableGauge(Metrics.DB_NUM_ITEMS);
32
26
 
33
- meter.addBatchObservableCallback(this.recordDBMetrics, [this.dbMapSize, this.dbUsedSize, this.dbNumItems]);
27
+ meter.addBatchObservableCallback(this.recordDBMetrics, [
28
+ this.dbMapSize,
29
+ this.dbPhysicalFileSize,
30
+ this.dbUsedSize,
31
+ this.dbNumItems,
32
+ ]);
34
33
  }
35
34
 
36
35
  private recordDBMetrics = async (observable: BatchObservableResult) => {
@@ -39,6 +38,7 @@ export class LmdbMetrics {
39
38
  }
40
39
  const metrics = await this.getStats();
41
40
  observable.observe(this.dbMapSize, metrics.mappingSize, this.attributes);
41
+ observable.observe(this.dbPhysicalFileSize, metrics.physicalFileSize, this.attributes);
42
42
  observable.observe(this.dbNumItems, metrics.numItems, this.attributes);
43
43
  observable.observe(this.dbUsedSize, metrics.actualSize, this.attributes);
44
44
  };
@@ -0,0 +1,75 @@
1
+ import type { AttributeValue, MetricOptions } from '@opentelemetry/api';
2
+
3
+ import type { MetricDefinition } from './metrics.js';
4
+ import type { AllowedAttributeNames, Meter, MetricAttributesType, UpDownCounter } from './telemetry.js';
5
+
6
+ /** Extracts OpenTelemetry MetricOptions from a MetricDefinition */
7
+ export function toMetricOptions(def: MetricDefinition): MetricOptions {
8
+ return {
9
+ description: def.description,
10
+ unit: def.unit,
11
+ valueType: def.valueType,
12
+ };
13
+ }
14
+
15
+ /** A mapping of attribute keys to their possible values */
16
+ export type AttributeValuesMap = Partial<Record<AllowedAttributeNames, AttributeValue[]>>;
17
+
18
+ /**
19
+ * Expands an attribute values map into all combinations of attribute objects.
20
+ * Example: { status: ['ok', 'fail'], type: ['a', 'b'] } =>
21
+ * [{ status: 'ok', type: 'a' }, { status: 'ok', type: 'b' }, { status: 'fail', type: 'a' }, { status: 'fail', type: 'b' }]
22
+ */
23
+ export function expandAttributeCombinations(attrMap: AttributeValuesMap): MetricAttributesType[] {
24
+ const keys = Object.keys(attrMap) as AllowedAttributeNames[];
25
+ if (keys.length === 0) {
26
+ return [{}];
27
+ }
28
+
29
+ const result: MetricAttributesType[] = [];
30
+
31
+ function generate(index: number, current: MetricAttributesType) {
32
+ if (index === keys.length) {
33
+ result.push({ ...current });
34
+ return;
35
+ }
36
+ const key = keys[index];
37
+ for (const value of attrMap[key]!) {
38
+ current[key] = value;
39
+ generate(index + 1, current);
40
+ }
41
+ }
42
+
43
+ generate(0, {});
44
+ return result;
45
+ }
46
+
47
+ /**
48
+ * Creates an UpDownCounter and initializes it to 0.
49
+ * @param meter - The meter to create the counter on
50
+ * @param metric - The metric definition
51
+ * @param attributes - Optional attributes for initialization. Can be:
52
+ * - AttributeValuesMap: mapping of attribute keys to arrays of possible values (generates cartesian product)
53
+ * - MetricAttributesType[]: explicit array of attribute objects
54
+ * - undefined: initializes without attributes
55
+ */
56
+ export function createUpDownCounterWithDefault(
57
+ meter: Meter,
58
+ metric: MetricDefinition,
59
+ attributes: AttributeValuesMap | MetricAttributesType[] | undefined = undefined,
60
+ ): UpDownCounter {
61
+ const counter = meter.createUpDownCounter(metric);
62
+ if (attributes === undefined) {
63
+ counter.add(0);
64
+ } else if (Array.isArray(attributes)) {
65
+ for (const attrs of attributes) {
66
+ counter.add(0, attrs);
67
+ }
68
+ } else {
69
+ const combinations = expandAttributeCombinations(attributes);
70
+ for (const attrs of combinations) {
71
+ counter.add(0, attrs);
72
+ }
73
+ }
74
+ return counter;
75
+ }