@aztec/telemetry-client 4.0.0-nightly.20250907 → 4.0.0-nightly.20260107

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 (60) hide show
  1. package/dest/attributes.d.ts +21 -1
  2. package/dest/attributes.d.ts.map +1 -1
  3. package/dest/attributes.js +11 -1
  4. package/dest/bench.d.ts +1 -1
  5. package/dest/bench.d.ts.map +1 -1
  6. package/dest/config.d.ts +2 -1
  7. package/dest/config.d.ts.map +1 -1
  8. package/dest/config.js +7 -1
  9. package/dest/index.d.ts +1 -1
  10. package/dest/l1_metrics.d.ts +1 -1
  11. package/dest/l1_metrics.d.ts.map +1 -1
  12. package/dest/lmdb_metrics.d.ts +3 -3
  13. package/dest/lmdb_metrics.d.ts.map +1 -1
  14. package/dest/metrics.d.ts +44 -9
  15. package/dest/metrics.d.ts.map +1 -1
  16. package/dest/metrics.js +44 -8
  17. package/dest/nodejs_metrics_monitor.d.ts +1 -1
  18. package/dest/nodejs_metrics_monitor.d.ts.map +1 -1
  19. package/dest/nodejs_metrics_monitor.js +16 -9
  20. package/dest/noop.d.ts +1 -1
  21. package/dest/noop.d.ts.map +1 -1
  22. package/dest/otel.d.ts +1 -1
  23. package/dest/otel.d.ts.map +1 -1
  24. package/dest/otel.js +15 -1
  25. package/dest/otel_filter_metric_exporter.d.ts +1 -1
  26. package/dest/otel_filter_metric_exporter.d.ts.map +1 -1
  27. package/dest/otel_logger_provider.d.ts +1 -1
  28. package/dest/otel_propagation.d.ts +1 -1
  29. package/dest/otel_resource.d.ts +1 -1
  30. package/dest/otel_resource.js +2 -0
  31. package/dest/prom_otel_adapter.d.ts +1 -1
  32. package/dest/prom_otel_adapter.d.ts.map +1 -1
  33. package/dest/start.d.ts +2 -2
  34. package/dest/start.d.ts.map +1 -1
  35. package/dest/start.js +3 -2
  36. package/dest/telemetry.d.ts +1 -1
  37. package/dest/telemetry.d.ts.map +1 -1
  38. package/dest/telemetry.js +9 -2
  39. package/dest/vendor/attributes.d.ts +1 -1
  40. package/dest/vendor/otel-pino-stream.d.ts +1 -1
  41. package/dest/vendor/otel-pino-stream.d.ts.map +1 -1
  42. package/dest/with_tracer.d.ts +1 -1
  43. package/dest/with_tracer.d.ts.map +1 -1
  44. package/dest/wrappers/fetch.d.ts +2 -2
  45. package/dest/wrappers/fetch.d.ts.map +1 -1
  46. package/dest/wrappers/index.d.ts +1 -1
  47. package/dest/wrappers/json_rpc_server.d.ts +1 -1
  48. package/dest/wrappers/l2_block_stream.d.ts +3 -2
  49. package/dest/wrappers/l2_block_stream.d.ts.map +1 -1
  50. package/dest/wrappers/l2_block_stream.js +385 -11
  51. package/package.json +10 -7
  52. package/src/attributes.ts +26 -1
  53. package/src/config.ts +14 -1
  54. package/src/metrics.ts +53 -9
  55. package/src/nodejs_metrics_monitor.ts +19 -9
  56. package/src/otel.ts +16 -2
  57. package/src/otel_resource.ts +2 -0
  58. package/src/start.ts +3 -2
  59. package/src/telemetry.ts +29 -17
  60. package/src/wrappers/l2_block_stream.ts +2 -1
package/src/metrics.ts CHANGED
@@ -34,6 +34,9 @@ export const CIRCUIT_SIZE = 'aztec.circuit.size';
34
34
 
35
35
  export const MEMPOOL_TX_COUNT = 'aztec.mempool.tx_count';
36
36
  export const MEMPOOL_TX_SIZE = 'aztec.mempool.tx_size';
37
+ export const MEMPOOL_TX_ADDED_COUNT = 'aztec.mempool.tx_added_count';
38
+ export const MEMPOOL_TX_MINED_DELAY = 'aztec.mempool.tx_mined_delay';
39
+
37
40
  export const DB_NUM_ITEMS = 'aztec.db.num_items';
38
41
  export const DB_MAP_SIZE = 'aztec.db.map_size';
39
42
  export const DB_PHYSICAL_FILE_SIZE = 'aztec.db.physical_file_size';
@@ -41,6 +44,8 @@ export const DB_USED_SIZE = 'aztec.db.used_size';
41
44
 
42
45
  export const MEMPOOL_ATTESTATIONS_COUNT = 'aztec.mempool.attestations_count';
43
46
  export const MEMPOOL_ATTESTATIONS_SIZE = 'aztec.mempool.attestations_size';
47
+ export const MEMPOOL_ATTESTATIONS_ADDED_COUNT = 'aztec.mempool.attestations_added_count';
48
+ export const MEMPOOL_ATTESTATIONS_MINED_DELAY = 'aztec.mempool.attestations_mined_delay';
44
49
 
45
50
  export const ARCHIVER_L1_BLOCK_HEIGHT = 'aztec.archiver.l1_block_height';
46
51
  export const ARCHIVER_BLOCK_HEIGHT = 'aztec.archiver.block_height';
@@ -60,27 +65,50 @@ export const ARCHIVER_PRUNE_COUNT = 'aztec.archiver.prune_count';
60
65
 
61
66
  export const ARCHIVER_TOTAL_TXS = 'aztec.archiver.tx_count';
62
67
 
68
+ export const ARCHIVER_BLOCK_PROPOSAL_TX_TARGET_COUNT = 'aztec.archiver.block_proposal_tx_target_count';
69
+
63
70
  export const NODE_RECEIVE_TX_DURATION = 'aztec.node.receive_tx.duration';
64
71
  export const NODE_RECEIVE_TX_COUNT = 'aztec.node.receive_tx.count';
65
72
 
73
+ export const NODE_SNAPSHOT_DURATION = 'aztec.node.snapshot_duration';
74
+ export const NODE_SNAPSHOT_ERROR_COUNT = 'aztec.node.snapshot_error_count';
75
+
66
76
  export const SEQUENCER_STATE_TRANSITION_BUFFER_DURATION = 'aztec.sequencer.state_transition_buffer.duration';
67
77
  export const SEQUENCER_BLOCK_BUILD_DURATION = 'aztec.sequencer.block.build_duration';
68
78
  export const SEQUENCER_BLOCK_BUILD_MANA_PER_SECOND = 'aztec.sequencer.block.build_mana_per_second';
69
79
  export const SEQUENCER_BLOCK_COUNT = 'aztec.sequencer.block.count';
70
- export const SEQUENCER_CURRENT_STATE = 'aztec.sequencer.current.state';
71
- export const SEQUENCER_CURRENT_BLOCK_NUMBER = 'aztec.sequencer.current.block_number';
72
- export const SEQUENCER_CURRENT_BLOCK_SIZE = 'aztec.sequencer.current.block_size';
73
- export const SEQUENCER_BLOCK_BUILD_INSERTION_TIME = 'aztec.sequencer.block_builder_tree_insertion_duration';
74
80
  export const SEQUENCER_CURRENT_BLOCK_REWARDS = 'aztec.sequencer.current_block_rewards';
75
81
  export const SEQUENCER_SLOT_COUNT = 'aztec.sequencer.slot.total_count';
76
82
  export const SEQUENCER_FILLED_SLOT_COUNT = 'aztec.sequencer.slot.filled_count';
77
- export const SEQUENCER_MISSED_SLOT_COUNT = 'aztec.sequencer.slot.missed_count';
83
+
84
+ export const SEQUENCER_BLOCK_ATTESTATION_DELAY = 'aztec.sequencer.block.attestation_delay';
78
85
 
79
86
  export const SEQUENCER_COLLECTED_ATTESTATIONS_COUNT = 'aztec.sequencer.attestations.collected_count';
80
87
  export const SEQUENCER_REQUIRED_ATTESTATIONS_COUNT = 'aztec.sequencer.attestations.required_count';
81
88
  export const SEQUENCER_COLLECT_ATTESTATIONS_DURATION = 'aztec.sequencer.attestations.collect_duration';
82
89
  export const SEQUENCER_COLLECT_ATTESTATIONS_TIME_ALLOWANCE = 'aztec.sequencer.attestations.collect_allowance';
83
90
 
91
+ export const SEQUENCER_BLOCK_PROPOSAL_FAILED_COUNT = 'aztec.sequencer.block.proposal_failed_count';
92
+ export const SEQUENCER_BLOCK_PROPOSAL_SUCCESS_COUNT = 'aztec.sequencer.block.proposal_success_count';
93
+ export const SEQUENCER_BLOCK_PROPOSAL_PRECHECK_FAILED_COUNT = 'aztec.sequencer.block.proposal_precheck_failed_count';
94
+ export const SEQUENCER_SLASHING_ATTEMPTS_COUNT = 'aztec.sequencer.slashing.attempts_count';
95
+ export const SEQUENCER_CHECKPOINT_SUCCESS_COUNT = 'aztec.sequencer.checkpoint.success_count';
96
+
97
+ // Fisherman fee analysis metrics
98
+ export const FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED = 'aztec.fisherman.fee_analysis.would_be_included';
99
+ export const FISHERMAN_FEE_ANALYSIS_TIME_BEFORE_BLOCK = 'aztec.fisherman.fee_analysis.time_before_block';
100
+ export const FISHERMAN_FEE_ANALYSIS_PENDING_BLOB_TX_COUNT = 'aztec.fisherman.fee_analysis.pending_blob_tx_count';
101
+ export const FISHERMAN_FEE_ANALYSIS_INCLUDED_BLOB_TX_COUNT = 'aztec.fisherman.fee_analysis.included_blob_tx_count';
102
+ export const FISHERMAN_FEE_ANALYSIS_CALCULATED_PRIORITY_FEE = 'aztec.fisherman.fee_analysis.calculated_priority_fee';
103
+ export const FISHERMAN_FEE_ANALYSIS_PRIORITY_FEE_DELTA = 'aztec.fisherman.fee_analysis.priority_fee_delta';
104
+ export const FISHERMAN_FEE_ANALYSIS_ESTIMATED_COST = 'aztec.fisherman.fee_analysis.estimated_cost';
105
+ export const FISHERMAN_FEE_ANALYSIS_ESTIMATED_OVERPAYMENT = 'aztec.fisherman.fee_analysis.estimated_overpayment';
106
+ export const FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_PRIORITY_FEE =
107
+ 'aztec.fisherman.fee_analysis.mined_blob_tx_priority_fee';
108
+ export const FISHERMAN_FEE_ANALYSIS_MINED_BLOB_TX_TOTAL_COST = 'aztec.fisherman.fee_analysis.mined_blob_tx_total_cost';
109
+
110
+ export const VALIDATOR_INVALID_ATTESTATION_RECEIVED_COUNT = 'aztec.validator.invalid_attestation_received_count';
111
+
84
112
  export const L1_PUBLISHER_GAS_PRICE = 'aztec.l1_publisher.gas_price';
85
113
  export const L1_PUBLISHER_TX_COUNT = 'aztec.l1_publisher.tx_count';
86
114
  export const L1_PUBLISHER_TX_DURATION = 'aztec.l1_publisher.tx_duration';
@@ -101,9 +129,22 @@ export const L1_BALANCE_ETH = 'aztec.l1.balance';
101
129
  export const L1_GAS_PRICE_WEI = 'aztec.l1.gas_price';
102
130
  export const L1_BLOB_BASE_FEE_WEI = 'aztec.l1.blob_base_fee';
103
131
 
132
+ export const L1_TX_MINED_DURATION = 'aztec.l1_tx.mined_duration';
133
+ export const L1_TX_MINED_COUNT = 'aztec.l1_tx.mined_count';
134
+ export const L1_TX_REVERTED_COUNT = 'aztec.l1_tx.reverted_count';
135
+ export const L1_TX_CANCELLED_COUNT = 'aztec.l1_tx.cancelled_count';
136
+ export const L1_TX_NOT_MINED_COUNT = 'aztec.l1_tx.not_mined_count';
137
+ export const L1_TX_ATTEMPTS_UNTIL_MINED = 'aztec.l1_tx.attempts_until_mined';
138
+ export const L1_TX_MAX_PRIORITY_FEE = 'aztec.l1_tx.max_priority_fee';
139
+ export const L1_TX_MAX_FEE = 'aztec.l1_tx.max_fee';
140
+ export const L1_TX_BLOB_FEE = 'aztec.l1_tx.blob_fee';
141
+
104
142
  export const PEER_MANAGER_GOODBYES_SENT = 'aztec.peer_manager.goodbyes_sent';
105
143
  export const PEER_MANAGER_GOODBYES_RECEIVED = 'aztec.peer_manager.goodbyes_received';
106
144
  export const PEER_MANAGER_PEER_COUNT = 'aztec.peer_manager.peer_count';
145
+ export const PEER_MANAGER_LOW_SCORE_DISCONNECTS = 'aztec.peer_manager.low_score_disconnects';
146
+ export const PEER_MANAGER_PEER_CONNECTION_DURATION = 'aztec.peer_manager.peer_connection_duration';
147
+ export const P2P_PEER_STATE_COUNT = 'aztec.p2p.peer_state_count';
107
148
 
108
149
  export const P2P_REQ_RESP_SENT_REQUESTS = 'aztec.p2p.req_resp.sent_requests';
109
150
  export const P2P_REQ_RESP_RECEIVED_REQUESTS = 'aztec.p2p.req_resp.received_requests';
@@ -113,6 +154,7 @@ export const P2P_REQ_RESP_FAILED_INBOUND_REQUESTS = 'aztec.p2p.req_resp.failed_i
113
154
  export const P2P_GOSSIP_MESSAGE_VALIDATION_DURATION = 'aztec.p2p.gossip.message_validation_duration';
114
155
  export const P2P_GOSSIP_MESSAGE_PREVALIDATION_COUNT = 'aztec.p2p.gossip.message_validation_count';
115
156
  export const P2P_GOSSIP_MESSAGE_LATENCY = 'aztec.p2p.gossip.message_latency';
157
+ export const P2P_GOSSIP_TX_RECEIVED_COUNT = 'aztec.p2p.gossip.tx_received_count';
116
158
 
117
159
  export const P2P_GOSSIP_AGG_MESSAGE_LATENCY_MIN = 'aztec.p2p.gossip.agg_message_latency_min';
118
160
  export const P2P_GOSSIP_AGG_MESSAGE_LATENCY_MAX = 'aztec.p2p.gossip.agg_message_latency_max';
@@ -151,8 +193,6 @@ export const PUBLIC_EXECUTOR_SIMULATION_BYTECODE_SIZE = 'aztec.public_executor.s
151
193
  export const PROVING_ORCHESTRATOR_BASE_ROLLUP_INPUTS_DURATION =
152
194
  'aztec.proving_orchestrator.base_rollup.inputs_duration';
153
195
 
154
- export const PROVING_ORCHESTRATOR_AVM_FALLBACK_COUNT = 'aztec.proving_orchestrator.avm.fallback_count';
155
-
156
196
  export const PROVING_QUEUE_JOB_SIZE = 'aztec.proving_queue.job_size';
157
197
  export const PROVING_QUEUE_SIZE = 'aztec.proving_queue.size';
158
198
  export const PROVING_QUEUE_TOTAL_JOBS = 'aztec.proving_queue.enqueued_jobs_count';
@@ -172,6 +212,7 @@ export const PROVING_AGENT_IDLE = 'aztec.proving_queue.agent.idle';
172
212
 
173
213
  export const PROVER_NODE_EXECUTION_DURATION = 'aztec.prover_node.execution.duration';
174
214
  export const PROVER_NODE_JOB_DURATION = 'aztec.prover_node.job_duration';
215
+ export const PROVER_NODE_JOB_CHECKPOINTS = 'aztec.prover_node.job_checkpoints';
175
216
  export const PROVER_NODE_JOB_BLOCKS = 'aztec.prover_node.job_blocks';
176
217
  export const PROVER_NODE_JOB_TRANSACTIONS = 'aztec.prover_node.job_transactions';
177
218
  export const PROVER_NODE_REWARDS_TOTAL = 'aztec.prover_node.rewards_total';
@@ -199,8 +240,9 @@ export const VALIDATOR_RE_EXECUTION_MANA = 'aztec.validator.re_execution_mana';
199
240
  export const VALIDATOR_RE_EXECUTION_TX_COUNT = 'aztec.validator.re_execution_tx_count';
200
241
 
201
242
  export const VALIDATOR_FAILED_REEXECUTION_COUNT = 'aztec.validator.failed_reexecution_count';
202
- export const VALIDATOR_ATTESTATION_COUNT = 'aztec.validator.attestation_count';
203
- export const VALIDATOR_FAILED_ATTESTATION_COUNT = 'aztec.validator.failed_attestation_count';
243
+ export const VALIDATOR_ATTESTATION_SUCCESS_COUNT = 'aztec.validator.attestation_success_count';
244
+ export const VALIDATOR_ATTESTATION_FAILED_BAD_PROPOSAL_COUNT = 'aztec.validator.attestation_failed_bad_proposal_count';
245
+ export const VALIDATOR_ATTESTATION_FAILED_NODE_ISSUE_COUNT = 'aztec.validator.attestation_failed_node_issue_count';
204
246
 
205
247
  export const NODEJS_EVENT_LOOP_DELAY_MIN = 'nodejs.eventloop.delay.min';
206
248
  export const NODEJS_EVENT_LOOP_DELAY_MEAN = 'nodejs.eventloop.delay.mean';
@@ -222,6 +264,8 @@ export const TX_PROVIDER_TXS_FROM_PROPOSALS_COUNT = 'aztec.tx_collector.txs_from
222
264
  export const TX_PROVIDER_TXS_FROM_MEMPOOL_COUNT = 'aztec.tx_collector.txs_from_mempool_count';
223
265
  export const TX_PROVIDER_TXS_FROM_P2P_COUNT = 'aztec.tx_collector.txs_from_p2p_count';
224
266
  export const TX_PROVIDER_MISSING_TXS_COUNT = 'aztec.tx_collector.missing_txs_count';
267
+ export const TX_PROVIDER_P2P_TXS_REQUESTED_FRACTION = 'aztec.tx_collector.txs_requested_fraction';
268
+ export const TX_PROVIDER_P2P_TXS_REQUEST_DELAY = 'aztec.tx_collector.txs_requested_delay';
225
269
 
226
270
  export const TX_COLLECTOR_COUNT = 'aztec.tx_collector.tx_count';
227
271
  export const TX_COLLECTOR_DURATION_PER_REQUEST = 'aztec.tx_collector.duration_per_request';
@@ -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';
@@ -142,17 +143,26 @@ export class NodejsMetricsMonitor {
142
143
  // - https://youtu.be/WetXnEPraYM
143
144
  obs.observe(this.eventLoopUilization, delta.utilization);
144
145
 
145
- this.eventLoopTime.add(Math.floor(delta.idle), { [Attributes.NODEJS_EVENT_LOOP_STATE]: 'idle' });
146
- 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' });
147
148
 
148
- obs.observe(this.eventLoopDelayGauges.min, Math.floor(this.eventLoopDelay.min));
149
- obs.observe(this.eventLoopDelayGauges.mean, Math.floor(this.eventLoopDelay.mean));
150
- obs.observe(this.eventLoopDelayGauges.max, Math.floor(this.eventLoopDelay.max));
151
- obs.observe(this.eventLoopDelayGauges.stddev, Math.floor(this.eventLoopDelay.stddev));
152
- obs.observe(this.eventLoopDelayGauges.p50, Math.floor(this.eventLoopDelay.percentile(50)));
153
- obs.observe(this.eventLoopDelayGauges.p90, Math.floor(this.eventLoopDelay.percentile(90)));
154
- 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));
155
156
 
156
157
  this.eventLoopDelay.reset();
157
158
  };
158
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/otel.ts CHANGED
@@ -283,11 +283,25 @@ export class OpenTelemetryClient implements TelemetryClient {
283
283
 
284
284
  const exporters: PeriodicExportingMetricReaderOptions[] = [];
285
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
+ }
286
300
  exporters.push({
287
301
  exporter: new OtelFilterMetricExporter(
288
302
  new OTLPMetricExporter({ url: config.metricsCollectorUrl.href }),
289
- config.otelExcludeMetrics,
290
- 'deny',
303
+ filter,
304
+ mode,
291
305
  ),
292
306
  exportTimeoutMillis: config.otelExportTimeoutMs,
293
307
  exportIntervalMillis: config.otelCollectIntervalMs,
@@ -37,6 +37,8 @@ const aztecNetworkDetectorSync: DetectorSync = {
37
37
  role = 'prover-node';
38
38
  } else if (process.argv.includes('--node')) {
39
39
  role = 'node';
40
+ } else if (process.argv.includes('--p2p-bootstrap')) {
41
+ role = 'bootnode';
40
42
  }
41
43
  const aztecAttributes = {
42
44
  // this gets overwritten by OTEL_RESOURCE_ATTRIBUTES (if set)
package/src/start.ts CHANGED
@@ -2,7 +2,6 @@ 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';
@@ -10,7 +9,7 @@ export * from './config.js';
10
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
14
  if (initialized) {
16
15
  log.warn('Telemetry client has already been initialized once');
@@ -19,6 +18,8 @@ export function initTelemetryClient(config: TelemetryClientConfig): TelemetryCli
19
18
 
20
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');
package/src/telemetry.ts CHANGED
@@ -204,24 +204,36 @@ export function trackSpan<T extends Traceable, F extends (...args: any[]) => any
204
204
  // "active" means the span will be alive for the duration of the function execution
205
205
  // and if any other spans are started during the execution of originalMethod, they will be children of this span
206
206
  // behind the scenes this uses AsyncLocalStorage https://nodejs.org/dist/latest-v22.x/docs/api/async_context.html
207
- return this.tracer.startActiveSpan(name, async (span: Span) => {
208
- span.setAttributes(currentAttrs ?? {});
207
+ return this.tracer.startActiveSpan(
208
+ name,
209
+ {
210
+ attributes: currentAttrs,
211
+ },
212
+ async (span: Span) => {
213
+ try {
214
+ const res = await originalMethod.call(this, ...args);
215
+ const extraAttrs = extraAttributes?.call(this, res);
216
+ span.setAttributes(extraAttrs ?? {});
217
+ span.setStatus({
218
+ code: SpanStatusCode.OK,
219
+ });
220
+ return res;
221
+ } catch (err) {
222
+ span.setStatus({
223
+ code: SpanStatusCode.ERROR,
224
+ message: String(err),
225
+ });
209
226
 
210
- try {
211
- const res = await originalMethod.call(this, ...args);
212
- const extraAttrs = extraAttributes?.call(this, res);
213
- span.setAttributes(extraAttrs ?? {});
214
- return res;
215
- } catch (err) {
216
- span.setStatus({
217
- code: SpanStatusCode.ERROR,
218
- message: String(err),
219
- });
220
- throw err;
221
- } finally {
222
- span.end();
223
- }
224
- });
227
+ if (typeof err === 'string' || (err && err instanceof Error)) {
228
+ span.recordException(err);
229
+ }
230
+
231
+ throw err;
232
+ } finally {
233
+ span.end();
234
+ }
235
+ },
236
+ );
225
237
  } as F;
226
238
  };
227
239
  }
@@ -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,
@@ -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);