@aztec/telemetry-client 0.0.1-commit.f504929 → 0.0.1-commit.f5a9928

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 (62) hide show
  1. package/dest/attributes.d.ts +12 -2
  2. package/dest/attributes.d.ts.map +1 -1
  3. package/dest/attributes.js +6 -1
  4. package/dest/config.d.ts +3 -1
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +17 -9
  7. package/dest/index.d.ts +2 -1
  8. package/dest/index.d.ts.map +1 -1
  9. package/dest/index.js +1 -0
  10. package/dest/json_rpc_server_metrics.d.ts +27 -0
  11. package/dest/json_rpc_server_metrics.d.ts.map +1 -0
  12. package/dest/json_rpc_server_metrics.js +154 -0
  13. package/dest/lmdb_metrics.d.ts +2 -2
  14. package/dest/lmdb_metrics.d.ts.map +1 -1
  15. package/dest/metrics.d.ts +44 -2
  16. package/dest/metrics.d.ts.map +1 -1
  17. package/dest/metrics.js +241 -8
  18. package/dest/monitored_batch_span_processor.d.ts +29 -0
  19. package/dest/monitored_batch_span_processor.d.ts.map +1 -0
  20. package/dest/monitored_batch_span_processor.js +75 -0
  21. package/dest/otel.d.ts +6 -1
  22. package/dest/otel.d.ts.map +1 -1
  23. package/dest/otel.js +99 -4
  24. package/dest/otel_propagation.d.ts +4 -1
  25. package/dest/otel_propagation.d.ts.map +1 -1
  26. package/dest/otel_propagation.js +64 -6
  27. package/dest/start.d.ts +1 -1
  28. package/dest/start.d.ts.map +1 -1
  29. package/dest/start.js +1 -1
  30. package/dest/telemetry.d.ts +5 -3
  31. package/dest/telemetry.d.ts.map +1 -1
  32. package/dest/vendor/attributes.d.ts +2 -1
  33. package/dest/vendor/attributes.d.ts.map +1 -1
  34. package/dest/vendor/attributes.js +1 -0
  35. package/dest/wrappers/fetch.d.ts +3 -3
  36. package/dest/wrappers/fetch.d.ts.map +1 -1
  37. package/dest/wrappers/fetch.js +3 -2
  38. package/dest/wrappers/index.d.ts +1 -2
  39. package/dest/wrappers/index.d.ts.map +1 -1
  40. package/dest/wrappers/index.js +0 -1
  41. package/dest/wrappers/json_rpc_server.d.ts +1 -1
  42. package/dest/wrappers/json_rpc_server.d.ts.map +1 -1
  43. package/dest/wrappers/json_rpc_server.js +6 -1
  44. package/package.json +3 -3
  45. package/src/attributes.ts +14 -1
  46. package/src/config.ts +24 -9
  47. package/src/index.ts +1 -0
  48. package/src/json_rpc_server_metrics.ts +151 -0
  49. package/src/metrics.ts +259 -8
  50. package/src/monitored_batch_span_processor.ts +100 -0
  51. package/src/otel.ts +69 -3
  52. package/src/otel_propagation.ts +63 -5
  53. package/src/start.ts +6 -1
  54. package/src/telemetry.ts +6 -2
  55. package/src/vendor/attributes.ts +1 -0
  56. package/src/wrappers/fetch.ts +9 -3
  57. package/src/wrappers/index.ts +0 -1
  58. package/src/wrappers/json_rpc_server.ts +13 -2
  59. package/dest/wrappers/l2_block_stream.d.ts +0 -16
  60. package/dest/wrappers/l2_block_stream.d.ts.map +0 -1
  61. package/dest/wrappers/l2_block_stream.js +0 -400
  62. package/src/wrappers/l2_block_stream.ts +0 -41
package/src/metrics.ts CHANGED
@@ -33,6 +33,46 @@ export interface MetricDefinition {
33
33
  readonly valueType?: ValueType;
34
34
  }
35
35
 
36
+ export const JSON_RPC_SERVER_REQUEST_COUNT: MetricDefinition = {
37
+ name: 'aztec.json_rpc.server.request_count',
38
+ description: 'Number of completed JSON-RPC server requests',
39
+ valueType: ValueType.INT,
40
+ };
41
+ export const JSON_RPC_SERVER_REQUEST_DURATION: MetricDefinition = {
42
+ name: 'aztec.json_rpc.server.request_duration',
43
+ description: 'JSON-RPC server request handler duration',
44
+ unit: 'ms',
45
+ valueType: ValueType.DOUBLE,
46
+ };
47
+ export const JSON_RPC_SERVER_REQUEST_VALIDATION_DURATION: MetricDefinition = {
48
+ name: 'aztec.json_rpc.server.request_validation_duration',
49
+ description: 'JSON-RPC server request parameter validation duration',
50
+ unit: 'ms',
51
+ valueType: ValueType.DOUBLE,
52
+ };
53
+ export const JSON_RPC_SERVER_REJECTED_REQUEST_COUNT: MetricDefinition = {
54
+ name: 'aztec.json_rpc.server.rejected_request_count',
55
+ description: 'Number of JSON-RPC requests rejected before handler dispatch',
56
+ valueType: ValueType.INT,
57
+ };
58
+ export const JSON_RPC_SERVER_BATCH_COUNT: MetricDefinition = {
59
+ name: 'aztec.json_rpc.server.batch_count',
60
+ description: 'Number of JSON-RPC batches received',
61
+ valueType: ValueType.INT,
62
+ };
63
+ export const JSON_RPC_SERVER_BATCH_DURATION: MetricDefinition = {
64
+ name: 'aztec.json_rpc.server.batch_duration',
65
+ description: 'JSON-RPC batch processing duration',
66
+ unit: 'ms',
67
+ valueType: ValueType.DOUBLE,
68
+ };
69
+ export const JSON_RPC_SERVER_BATCH_SIZE: MetricDefinition = {
70
+ name: 'aztec.json_rpc.server.batch_size',
71
+ description: 'Number of requests in a JSON-RPC batch',
72
+ unit: 'requests',
73
+ valueType: ValueType.INT,
74
+ };
75
+
36
76
  export const BLOB_SINK_STORE_REQUESTS: MetricDefinition = {
37
77
  name: 'aztec.blob_sink.store_request_count',
38
78
  description: 'Number of blob store requests',
@@ -162,7 +202,7 @@ export const MEMPOOL_TX_ADDED_COUNT: MetricDefinition = {
162
202
  };
163
203
  export const MEMPOOL_TX_MINED_DELAY: MetricDefinition = {
164
204
  name: 'aztec.mempool.tx_mined_delay',
165
- description: 'Delay between transaction added and evicted from the mempool',
205
+ description: 'Delay (ms) from a transaction being received into the pool to being mined',
166
206
  unit: 'ms',
167
207
  valueType: ValueType.INT,
168
208
  };
@@ -204,6 +244,24 @@ export const MEMPOOL_TX_POOL_V2_METADATA_MEMORY: MetricDefinition = {
204
244
  valueType: ValueType.INT,
205
245
  };
206
246
 
247
+ export const MEMPOOL_TX_POOL_V2_QUEUE_WAIT: MetricDefinition = {
248
+ name: 'aztec.mempool.tx_pool_v2.queue_wait',
249
+ description: 'Time an operation waits in the tx pool serial queue before executing, keyed by mempool.operation',
250
+ unit: 'ms',
251
+ valueType: ValueType.INT,
252
+ };
253
+ export const MEMPOOL_TX_POOL_V2_QUEUE_EXECUTION: MetricDefinition = {
254
+ name: 'aztec.mempool.tx_pool_v2.queue_execution',
255
+ description: 'Time an operation spends executing in the tx pool serial queue, keyed by mempool.operation',
256
+ unit: 'ms',
257
+ valueType: ValueType.INT,
258
+ };
259
+ export const MEMPOOL_TX_POOL_V2_QUEUE_LENGTH: MetricDefinition = {
260
+ name: 'aztec.mempool.tx_pool_v2.queue_length',
261
+ description: 'Number of operations waiting in the tx pool serial queue',
262
+ valueType: ValueType.INT,
263
+ };
264
+
207
265
  export const MEMPOOL_TX_POOL_V2_DUPLICATE_ADD: MetricDefinition = {
208
266
  name: 'aztec.mempool.tx_pool_v2.duplicate_add',
209
267
  description: 'Transactions received via addPendingTxs that were already in the pool',
@@ -308,6 +366,12 @@ export const ARCHIVER_SYNC_PER_BLOCK: MetricDefinition = {
308
366
  unit: 'ms',
309
367
  valueType: ValueType.INT,
310
368
  };
369
+ export const ARCHIVER_SYNC_PER_CHECKPOINT: MetricDefinition = {
370
+ name: 'aztec.archiver.checkpoint.sync_per_item_duration',
371
+ description: 'Duration to sync a checkpoint',
372
+ unit: 'ms',
373
+ valueType: ValueType.INT,
374
+ };
311
375
  export const ARCHIVER_SYNC_BLOCK_COUNT: MetricDefinition = {
312
376
  name: 'aztec.archiver.block.sync_count',
313
377
  description: 'Number of blocks synced from L1',
@@ -334,7 +398,8 @@ export const ARCHIVER_PRUNE_DURATION: MetricDefinition = {
334
398
  };
335
399
  export const ARCHIVER_PRUNE_COUNT: MetricDefinition = {
336
400
  name: 'aztec.archiver.prune_count',
337
- description: 'Number of prunes detected',
401
+ description:
402
+ 'Number of prunes detected, dimensioned by prune_type: unproven (epoch prune of checkpoints that will not be proven), uncheckpointed (proposed blocks whose slot ended without a checkpoint), l1_conflict (proposed blocks conflicting with an L1 checkpoint), orphan (proposed blocks whose matching proposed checkpoint never arrived before the deadline), and l1_mismatch (the local checkpointed tip diverged from L1 — an L1 reorg or a pruned/missed-proof checkpoint — rewinding already-checkpointed blocks).',
338
403
  valueType: ValueType.INT,
339
404
  };
340
405
 
@@ -357,6 +422,12 @@ export const ARCHIVER_CHECKPOINT_L1_INCLUSION_DELAY: MetricDefinition = {
357
422
  valueType: ValueType.INT,
358
423
  };
359
424
 
425
+ export const ARCHIVER_CHECKPOINT_PROMOTED_COUNT: MetricDefinition = {
426
+ name: 'aztec.archiver.checkpoint_promoted_count',
427
+ description: 'Number of checkpoints promoted from proposed (blob fetch skipped)',
428
+ valueType: ValueType.INT,
429
+ };
430
+
360
431
  export const NODE_RECEIVE_TX_DURATION: MetricDefinition = {
361
432
  name: 'aztec.node.receive_tx.duration',
362
433
  description: 'The duration of the receiveTx method',
@@ -388,6 +459,12 @@ export const SEQUENCER_STATE_TRANSITION_BUFFER_DURATION: MetricDefinition = {
388
459
  unit: 'ms',
389
460
  valueType: ValueType.INT,
390
461
  };
462
+ export const SEQUENCER_STATE_DURATION: MetricDefinition = {
463
+ name: 'aztec.sequencer.state_duration',
464
+ description: 'Wall-clock time spent in each sequencer state, labelled by the state being left',
465
+ unit: 'ms',
466
+ valueType: ValueType.INT,
467
+ };
391
468
  export const SEQUENCER_BLOCK_BUILD_DURATION: MetricDefinition = {
392
469
  name: 'aztec.sequencer.block.build_duration',
393
470
  description: 'Duration to build a block',
@@ -405,6 +482,12 @@ export const SEQUENCER_BLOCK_COUNT: MetricDefinition = {
405
482
  description: 'Number of blocks built by this sequencer',
406
483
  valueType: ValueType.INT,
407
484
  };
485
+ export const SEQUENCER_BLOCK_INTER_BLOCK_TIME: MetricDefinition = {
486
+ name: 'aztec.sequencer.block.inter_block_time',
487
+ description: 'Wall-clock time elapsed between consecutive blocks being built by this sequencer',
488
+ unit: 'ms',
489
+ valueType: ValueType.INT,
490
+ };
408
491
  export const SEQUENCER_CURRENT_SLOT_REWARDS: MetricDefinition = {
409
492
  name: 'aztec.sequencer.current_slot_rewards',
410
493
  description: 'The rewards earned per filled slot',
@@ -477,6 +560,25 @@ export const SEQUENCER_CHECKPOINT_BUILD_DURATION: MetricDefinition = {
477
560
  unit: 'ms',
478
561
  valueType: ValueType.INT,
479
562
  };
563
+ export const SEQUENCER_CHECKPOINT_START_TO_FIRST_BLOCK_DURATION: MetricDefinition = {
564
+ name: 'aztec.sequencer.checkpoint.start_to_first_block_duration',
565
+ description: 'Time from starting checkpoint work to the first block finishing build',
566
+ unit: 'ms',
567
+ valueType: ValueType.INT,
568
+ };
569
+ export const SEQUENCER_CHECKPOINT_LAST_BLOCK_TO_BROADCAST_DURATION: MetricDefinition = {
570
+ name: 'aztec.sequencer.checkpoint.last_block_to_broadcast_duration',
571
+ description: 'Time from the final block finishing build to the checkpoint proposal being broadcast',
572
+ unit: 'ms',
573
+ valueType: ValueType.INT,
574
+ };
575
+ export const SEQUENCER_PIPELINED_CHECKPOINT_BUILD_START_OFFSET_FROM_SLOT_BOUNDARY: MetricDefinition = {
576
+ name: 'aztec.sequencer.pipelined_checkpoint.build_start_offset_from_slot_boundary',
577
+ description:
578
+ 'Absolute offset from the wall-clock slot boundary when a pipelined checkpoint build starts. Use aztec.slot_boundary_side to distinguish before vs after the boundary.',
579
+ unit: 'ms',
580
+ valueType: ValueType.INT,
581
+ };
480
582
  export const SEQUENCER_CHECKPOINT_BLOCK_COUNT: MetricDefinition = {
481
583
  name: 'aztec.sequencer.checkpoint.block_count',
482
584
  description: 'Number of blocks built in a checkpoint',
@@ -499,11 +601,66 @@ export const SEQUENCER_SLASHING_ATTEMPTS_COUNT: MetricDefinition = {
499
601
  description: 'The number of slashing action attempts',
500
602
  valueType: ValueType.INT,
501
603
  };
604
+ export const SLASHER_ROUND_EXECUTED_COUNT: MetricDefinition = {
605
+ name: 'aztec.slasher.round.executed_count',
606
+ description: 'The number of slashing rounds executed',
607
+ valueType: ValueType.INT,
608
+ };
609
+ export const SLASHER_OWN_VALIDATOR_TARGETED_COUNT: MetricDefinition = {
610
+ name: 'aztec.slasher.own_validator.targeted_count',
611
+ description:
612
+ "The number of times one of the node's own validators was named as a slash target by an onchain vote, counted " +
613
+ 'once per vote per validator. Votes cast while the node is offline or starting up are not counted, and L1 ' +
614
+ 'reorgs can cause small drift within a round.',
615
+ valueType: ValueType.INT,
616
+ };
617
+ export const SLASHER_OWN_VALIDATOR_CURRENT_ROUND_VOTES_MAX: MetricDefinition = {
618
+ name: 'aztec.slasher.own_validator.current_round_votes_max',
619
+ description:
620
+ "Highest number of votes cast against any committee position held by the node's own validators in the current " +
621
+ 'slashing round, to compare against aztec.slasher.quorum_size (the contract tallies quorum per position). ' +
622
+ 'Resets to zero when a new round starts. Votes cast while the node is offline or starting up are not counted, ' +
623
+ 'and L1 reorgs can cause small drift within a round.',
624
+ valueType: ValueType.INT,
625
+ };
626
+ export const SLASHER_QUORUM_SIZE: MetricDefinition = {
627
+ name: 'aztec.slasher.quorum_size',
628
+ description: 'The number of votes a validator must receive in a round to be slashed',
629
+ valueType: ValueType.INT,
630
+ };
631
+ export const SLASHER_OWN_VALIDATOR_SLASHED_COUNT: MetricDefinition = {
632
+ name: 'aztec.slasher.own_validator.slashed_count',
633
+ description: "The number of times one of the node's own validators was slashed, from executed Slashed events",
634
+ valueType: ValueType.INT,
635
+ };
636
+ export const SLASHER_OWN_VALIDATOR_SLASHED_AMOUNT: MetricDefinition = {
637
+ name: 'aztec.slasher.own_validator.slashed_amount',
638
+ description:
639
+ "Cumulative amount slashed from the node's own validators in whole staking-asset tokens, from executed " +
640
+ 'Slashed events',
641
+ unit: 'tokens',
642
+ valueType: ValueType.DOUBLE,
643
+ };
502
644
  export const SEQUENCER_CHECKPOINT_SUCCESS_COUNT: MetricDefinition = {
503
645
  name: 'aztec.sequencer.checkpoint.success_count',
504
646
  description: 'The number of times checkpoint publishing succeeded',
505
647
  valueType: ValueType.INT,
506
648
  };
649
+ export const SEQUENCER_PIPELINE_DEPTH: MetricDefinition = {
650
+ name: 'aztec.sequencer.pipeline.depth',
651
+ description: 'Current pipeline depth when builder pipelining is enabled',
652
+ valueType: ValueType.INT,
653
+ };
654
+ export const SEQUENCER_PIPELINE_DISCARDS_COUNT: MetricDefinition = {
655
+ name: 'aztec.sequencer.pipeline.discards_count',
656
+ description: 'The number of times a pipeline was discarded',
657
+ valueType: ValueType.INT,
658
+ };
659
+ export const SEQUENCER_PIPELINE_PARENT_CHECKPOINT_MISMATCH_COUNT: MetricDefinition = {
660
+ name: 'aztec.sequencer.pipeline.parent_checkpoint_mismatch_count',
661
+ description: 'The number of times a pipelined checkpoint was discarded because the parent did not match expectations',
662
+ valueType: ValueType.INT,
663
+ };
507
664
 
508
665
  // Fisherman fee analysis metrics
509
666
  export const FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED: MetricDefinition = {
@@ -671,6 +828,24 @@ export const L1_PUBLISHER_TX_TOTAL_FEE: MetricDefinition = {
671
828
  unit: 'eth',
672
829
  valueType: ValueType.DOUBLE,
673
830
  };
831
+ export const PROVER_NODE_ESTIMATED_SUBMISSION_GAS: MetricDefinition = {
832
+ name: 'aztec.prover_node.estimated_submission.gas',
833
+ description: 'Estimated gas for a proof submission tx (proof publishing disabled, not actually sent)',
834
+ unit: 'gas',
835
+ valueType: ValueType.INT,
836
+ };
837
+ export const PROVER_NODE_ESTIMATED_SUBMISSION_GAS_PRICE: MetricDefinition = {
838
+ name: 'aztec.prover_node.estimated_submission.gas_price',
839
+ description: 'Estimated effective gas price for a proof submission tx (proof publishing disabled, not actually sent)',
840
+ unit: 'gwei',
841
+ valueType: ValueType.DOUBLE,
842
+ };
843
+ export const PROVER_NODE_ESTIMATED_SUBMISSION_TOTAL_FEE: MetricDefinition = {
844
+ name: 'aztec.prover_node.estimated_submission.total_fee',
845
+ description: 'Estimated total L1 fee for a proof submission tx (proof publishing disabled, not actually sent)',
846
+ unit: 'eth',
847
+ valueType: ValueType.DOUBLE,
848
+ };
674
849
 
675
850
  export const L1_BLOCK_HEIGHT: MetricDefinition = {
676
851
  name: 'aztec.l1.block_height',
@@ -899,6 +1074,19 @@ export const P2P_GOSSIP_AGG_MESSAGE_VALIDATION_DURATION_AVG: MetricDefinition =
899
1074
  valueType: ValueType.INT,
900
1075
  };
901
1076
 
1077
+ export const P2P_GOSSIP_SLOW_VALIDATION_COUNT: MetricDefinition = {
1078
+ name: 'aztec.p2p.gossip.slow_validation_count',
1079
+ description: 'Number of gossip validations that exceeded 75% of the mcache eviction window',
1080
+ valueType: ValueType.INT,
1081
+ };
1082
+
1083
+ export const P2P_GOSSIP_TX_VALIDATION_STAGE_DURATION: MetricDefinition = {
1084
+ name: 'aztec.p2p.gossip.tx_validation_stage_duration',
1085
+ description: 'Duration of each stage of gossiped tx validation, keyed by the tx_validation_stage attribute',
1086
+ unit: 'ms',
1087
+ valueType: ValueType.INT,
1088
+ };
1089
+
902
1090
  export const PUBLIC_PROCESSOR_TX_DURATION: MetricDefinition = {
903
1091
  name: 'aztec.public_processor.tx_duration',
904
1092
  description: 'Duration to process a public transaction',
@@ -962,6 +1150,17 @@ export const PUBLIC_PROCESSOR_TREE_INSERTION: MetricDefinition = {
962
1150
  unit: 'ms',
963
1151
  valueType: ValueType.INT,
964
1152
  };
1153
+ export const PUBLIC_PROCESSOR_SILENTLY_SKIPPED_COUNT: MetricDefinition = {
1154
+ name: 'aztec.public_processor.silently_skipped_count',
1155
+ description: 'Public txs fully processed then skipped (e.g. blob-field limit); not counted as processed or failed',
1156
+ valueType: ValueType.INT,
1157
+ };
1158
+ export const PUBLIC_PROCESSOR_SILENTLY_SKIPPED_DURATION: MetricDefinition = {
1159
+ name: 'aztec.public_processor.silently_skipped_duration',
1160
+ description: 'Wall-clock time spent processing txs that were then silently skipped',
1161
+ unit: 'ms',
1162
+ valueType: ValueType.INT,
1163
+ };
965
1164
 
966
1165
  export const PUBLIC_EXECUTOR_PREFIX = 'aztec.public_executor.';
967
1166
  export const PUBLIC_EXECUTOR_SIMULATION_COUNT: MetricDefinition = {
@@ -1106,12 +1305,6 @@ export const PROVING_AGENT_IDLE: MetricDefinition = {
1106
1305
  valueType: ValueType.DOUBLE,
1107
1306
  };
1108
1307
 
1109
- export const PROVER_NODE_EXECUTION_DURATION: MetricDefinition = {
1110
- name: 'aztec.prover_node.execution.duration',
1111
- description: 'Duration of execution of an epoch by the prover',
1112
- unit: 'ms',
1113
- valueType: ValueType.INT,
1114
- };
1115
1308
  export const PROVER_NODE_JOB_DURATION: MetricDefinition = {
1116
1309
  name: 'aztec.prover_node.job_duration',
1117
1310
  description: 'Duration of proving job',
@@ -1133,6 +1326,51 @@ export const PROVER_NODE_JOB_TRANSACTIONS: MetricDefinition = {
1133
1326
  description: 'Number of transactions in a proven epoch',
1134
1327
  valueType: ValueType.INT,
1135
1328
  };
1329
+ export const PROVER_NODE_BLOB_PROCESSING_LAST_DURATION: MetricDefinition = {
1330
+ name: 'aztec.prover_node.blob_processing.last_duration',
1331
+ description: 'Duration of blob processing step in epoch proving job',
1332
+ unit: 'ms',
1333
+ valueType: ValueType.INT,
1334
+ };
1335
+ export const PROVER_NODE_BLOCK_PROCESSING_DURATION: MetricDefinition = {
1336
+ name: 'aztec.prover_node.block_processing.duration',
1337
+ description: 'Duration of processing a single block in epoch proving job',
1338
+ unit: 'ms',
1339
+ valueType: ValueType.INT,
1340
+ };
1341
+ export const PROVER_NODE_CHECKPOINT_PROCESSING_DURATION: MetricDefinition = {
1342
+ name: 'aztec.prover_node.checkpoint_processing.duration',
1343
+ description: 'Duration of processing a single checkpoint in epoch proving job',
1344
+ unit: 'ms',
1345
+ valueType: ValueType.INT,
1346
+ };
1347
+ export const PROVER_NODE_CHECKPOINT_BLOCKS: MetricDefinition = {
1348
+ name: 'aztec.prover_node.checkpoint_blocks',
1349
+ description: 'Number of blocks in a proven checkpoint',
1350
+ valueType: ValueType.INT,
1351
+ };
1352
+ export const PROVER_NODE_CHECKPOINT_TRANSACTIONS: MetricDefinition = {
1353
+ name: 'aztec.prover_node.checkpoint_transactions',
1354
+ description: 'Number of transactions in a proven checkpoint',
1355
+ valueType: ValueType.INT,
1356
+ };
1357
+ export const PROVER_NODE_CHECKPOINT_PROVING_DURATION: MetricDefinition = {
1358
+ name: 'aztec.prover_node.checkpoint_proving.duration',
1359
+ description:
1360
+ 'Duration from the start of checkpoint processing to its block proofs being ready (excludes tx gathering)',
1361
+ unit: 'ms',
1362
+ valueType: ValueType.INT,
1363
+ };
1364
+ export const PROVER_NODE_ACTIVE_CHECKPOINTS: MetricDefinition = {
1365
+ name: 'aztec.prover_node.active_checkpoints',
1366
+ description: 'Current number of canonical CheckpointProvers in the store (i.e. checkpoints currently being proven)',
1367
+ valueType: ValueType.INT,
1368
+ };
1369
+ export const PROVER_NODE_ACTIVE_EPOCH_SESSIONS: MetricDefinition = {
1370
+ name: 'aztec.prover_node.active_epoch_sessions',
1371
+ description: 'Current number of live EpochSessions, broken down by kind (full|partial)',
1372
+ valueType: ValueType.INT,
1373
+ };
1136
1374
  export const PROVER_NODE_REWARDS_TOTAL: MetricDefinition = {
1137
1375
  name: 'aztec.prover_node.rewards_total',
1138
1376
  description: 'The rewards earned (total)',
@@ -1246,6 +1484,19 @@ export const VALIDATOR_RE_EXECUTION_TX_COUNT: MetricDefinition = {
1246
1484
  unit: 'tx',
1247
1485
  valueType: ValueType.INT,
1248
1486
  };
1487
+ export const VALIDATOR_CHECKPOINT_PROPOSAL_TO_PIPELINED_STATE_DURATION: MetricDefinition = {
1488
+ name: 'aztec.validator.checkpoint_proposal_to_pipelined_state_duration',
1489
+ description: 'Time from receiving a checkpoint proposal to setting proposed checkpoint state for pipelining',
1490
+ unit: 'ms',
1491
+ valueType: ValueType.INT,
1492
+ };
1493
+ export const VALIDATOR_CHECKPOINT_PROPOSAL_RECEIVE_OFFSET_FROM_NEXT_SLOT_BOUNDARY: MetricDefinition = {
1494
+ name: 'aztec.validator.checkpoint.proposal_receive_offset_from_next_slot_boundary',
1495
+ description:
1496
+ 'Absolute offset from the next slot boundary when a foreign checkpoint proposal is received. Use aztec.slot_boundary_side to distinguish before vs after the boundary.',
1497
+ unit: 'ms',
1498
+ valueType: ValueType.INT,
1499
+ };
1249
1500
 
1250
1501
  export const VALIDATOR_FAILED_REEXECUTION_COUNT: MetricDefinition = {
1251
1502
  name: 'aztec.validator.failed_reexecution_count',
@@ -0,0 +1,100 @@
1
+ import type { Logger } from '@aztec/foundation/log';
2
+
3
+ import { type Context, SpanStatusCode } from '@opentelemetry/api';
4
+ import { hrTimeToMilliseconds } from '@opentelemetry/core';
5
+ import type { SpanExporter } from '@opentelemetry/sdk-trace-base';
6
+ import { BatchSpanProcessor, type BufferConfig, type ReadableSpan, type Span } from '@opentelemetry/sdk-trace-node';
7
+
8
+ /** Minimum interval between drop warnings to avoid log spam. */
9
+ const DROP_WARNING_INTERVAL_MS = 30_000;
10
+
11
+ const DEFAULT_MIN_TRACE_DURATION_MS = 10;
12
+
13
+ const DEFAULT_MAX_QUEUE_SIZE = 16384;
14
+
15
+ /** Cap on the per-export batch size, so a large queue can actually be drained instead of dribbling out
16
+ * at the SDK default of 512 spans per scheduled export. Kept <= maxQueueSize per the BatchSpanProcessor contract. */
17
+ const DEFAULT_MAX_EXPORT_BATCH_SIZE = 2048;
18
+
19
+ export type MonitoredBatchSpanProcessorConfig = BufferConfig & {
20
+ minTraceDurationMs?: number;
21
+ };
22
+
23
+ /**
24
+ * Wraps BatchSpanProcessor to emit warnings when spans are dropped due to a full queue.
25
+ * The standard BatchSpanProcessor silently discards spans when its internal queue reaches
26
+ * maxQueueSize, making telemetry data loss invisible to operators.
27
+ */
28
+ export class MonitoredBatchSpanProcessor extends BatchSpanProcessor {
29
+ private readonly maxQueueSize: number;
30
+ private readonly minTraceDurationMs: number;
31
+ private readonly log: Logger;
32
+
33
+ private approxQueueSize = 0;
34
+ private droppedSinceLastWarning = 0;
35
+ private totalDropped = 0;
36
+ private lastWarningTime = 0;
37
+
38
+ constructor(exporter: SpanExporter, log: Logger, config?: MonitoredBatchSpanProcessorConfig) {
39
+ const maxQueueSize = config?.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE;
40
+ const maxExportBatchSize = Math.min(config?.maxExportBatchSize ?? DEFAULT_MAX_EXPORT_BATCH_SIZE, maxQueueSize);
41
+ super(exporter, { ...config, maxQueueSize, maxExportBatchSize });
42
+ this.maxQueueSize = maxQueueSize;
43
+ this.minTraceDurationMs = Math.max(0, config?.minTraceDurationMs ?? DEFAULT_MIN_TRACE_DURATION_MS);
44
+ this.log = log;
45
+ }
46
+
47
+ override onStart(span: Span, parentContext: Context): void {
48
+ super.onStart(span, parentContext);
49
+ }
50
+
51
+ override onEnd(span: ReadableSpan): void {
52
+ if (this.shouldDropShortSpan(span)) {
53
+ return;
54
+ }
55
+
56
+ if (this.approxQueueSize >= this.maxQueueSize) {
57
+ this.droppedSinceLastWarning++;
58
+ this.totalDropped++;
59
+ this.maybeLogDropWarning();
60
+ } else {
61
+ this.approxQueueSize++;
62
+ }
63
+ super.onEnd(span);
64
+ }
65
+
66
+ override async forceFlush(): Promise<void> {
67
+ await super.forceFlush();
68
+ this.approxQueueSize = 0;
69
+ }
70
+
71
+ override async shutdown(): Promise<void> {
72
+ if (this.totalDropped > 0) {
73
+ this.log.warn(`BatchSpanProcessor shutting down with ${this.totalDropped} total spans dropped`, {
74
+ totalDropped: this.totalDropped,
75
+ });
76
+ }
77
+ await super.shutdown();
78
+ }
79
+
80
+ private shouldDropShortSpan(span: ReadableSpan): boolean {
81
+ return (
82
+ this.minTraceDurationMs > 0 &&
83
+ span.status.code !== SpanStatusCode.ERROR &&
84
+ hrTimeToMilliseconds(span.duration) < this.minTraceDurationMs
85
+ );
86
+ }
87
+
88
+ private maybeLogDropWarning(): void {
89
+ const now = Date.now();
90
+ if (now - this.lastWarningTime >= DROP_WARNING_INTERVAL_MS) {
91
+ this.log.warn(
92
+ `BatchSpanProcessor dropping spans: queue full (maxQueueSize=${this.maxQueueSize}). ` +
93
+ `${this.droppedSinceLastWarning} dropped since last warning, ${this.totalDropped} total.`,
94
+ { droppedSinceLastWarning: this.droppedSinceLastWarning, totalDropped: this.totalDropped },
95
+ );
96
+ this.droppedSinceLastWarning = 0;
97
+ this.lastWarningTime = now;
98
+ }
99
+ }
100
+ }
package/src/otel.ts CHANGED
@@ -28,12 +28,13 @@ import {
28
28
  type PeriodicExportingMetricReaderOptions,
29
29
  View,
30
30
  } from '@opentelemetry/sdk-metrics';
31
- import { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
31
+ import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
32
32
  import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
33
33
 
34
34
  import type { TelemetryClientConfig } from './config.js';
35
35
  import { toMetricOptions } from './metric-utils.js';
36
36
  import type { MetricDefinition } from './metrics.js';
37
+ import { MonitoredBatchSpanProcessor } from './monitored_batch_span_processor.js';
37
38
  import { NodejsMetricsMonitor } from './nodejs_metrics_monitor.js';
38
39
  import { OtelFilterMetricExporter, PublicOtelFilterMetricExporter } from './otel_filter_metric_exporter.js';
39
40
  import { registerOtelLoggerProvider } from './otel_logger_provider.js';
@@ -95,6 +96,11 @@ export class OpenTelemetryClient implements TelemetryClient {
95
96
  private meters: Map<string, WrappedMeter> = new Map<string, WrappedMeter>();
96
97
  private tracers: Map<string, Tracer> = new Map<string, Tracer>();
97
98
 
99
+ /** Memoized shutdown promise. The telemetry client is shared between the aztec-node and an embedded prover-node,
100
+ * so stop() can be invoked more than once; the providers throw "shutdown may only be called once" and
101
+ * "invalid attempt to force flush after shutdown" if that happens. Guarding here makes stop()/flush() idempotent. */
102
+ private stopPromise: Promise<void> | undefined;
103
+
98
104
  protected constructor(
99
105
  private resource: IResource,
100
106
  private meterProvider: MeterProvider,
@@ -168,6 +174,10 @@ export class OpenTelemetryClient implements TelemetryClient {
168
174
  }
169
175
 
170
176
  public async flush() {
177
+ // Flushing after the providers have been shut down throws "invalid attempt to force flush after shutdown".
178
+ if (this.stopPromise) {
179
+ return;
180
+ }
171
181
  await Promise.all([
172
182
  this.meterProvider.forceFlush(),
173
183
  this.loggerProvider?.forceFlush(),
@@ -175,7 +185,11 @@ export class OpenTelemetryClient implements TelemetryClient {
175
185
  ]);
176
186
  }
177
187
 
178
- public async stop() {
188
+ public stop() {
189
+ return (this.stopPromise ??= this.doStop());
190
+ }
191
+
192
+ private async doStop() {
179
193
  this.nodejsMetricsMonitor?.stop();
180
194
 
181
195
  const flushAndShutdown = async (provider?: { forceFlush: () => Promise<void>; shutdown: () => Promise<void> }) => {
@@ -241,6 +255,23 @@ export class OpenTelemetryClient implements TelemetryClient {
241
255
  true,
242
256
  ),
243
257
  }),
258
+ // Pending-to-mined delay routinely exceeds the 1-minute ceiling of the generic `ms`
259
+ // view below under load, so it would saturate at 60s. Give this one metric wider
260
+ // buckets (1s to 10min). This must precede the generic `ms` view: when multiple views
261
+ // match an instrument, the SDK keeps the first-registered compatible storage, so the
262
+ // first view in this list wins the bucket boundaries.
263
+ new View({
264
+ instrumentType: InstrumentType.HISTOGRAM,
265
+ instrumentName: 'aztec.mempool.tx_mined_delay',
266
+ instrumentUnit: 'ms',
267
+ aggregation: new ExplicitBucketHistogramAggregation(
268
+ [
269
+ 1_000, 2_500, 5_000, 7_500, 10_000, 15_000, 30_000, 45_000, 60_000, 90_000, 120_000, 180_000, 300_000,
270
+ 600_000,
271
+ ],
272
+ true,
273
+ ),
274
+ }),
244
275
  new View({
245
276
  instrumentType: InstrumentType.HISTOGRAM,
246
277
  instrumentUnit: 'ms',
@@ -334,6 +365,36 @@ export class OpenTelemetryClient implements TelemetryClient {
334
365
  true,
335
366
  ),
336
367
  }),
368
+ // L1 gas prices in gwei: priority fees ~0.01-10, base fees ~1-500, spikes to 1000+
369
+ new View({
370
+ instrumentType: InstrumentType.HISTOGRAM,
371
+ instrumentUnit: 'gwei',
372
+ aggregation: new ExplicitBucketHistogramAggregation(
373
+ [0.1, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1_000],
374
+ true,
375
+ ),
376
+ }),
377
+ // L1 gas consumption: tx gas 100k-30M, calldata/blob gas varies
378
+ new View({
379
+ instrumentType: InstrumentType.HISTOGRAM,
380
+ instrumentUnit: 'gas',
381
+ aggregation: new ExplicitBucketHistogramAggregation(
382
+ [
383
+ 10_000, 50_000, 100_000, 250_000, 500_000, 1_000_000, 2_000_000, 5_000_000, 10_000_000, 15_000_000,
384
+ 30_000_000,
385
+ ],
386
+ true,
387
+ ),
388
+ }),
389
+ // L1 tx total fee in ETH: typically 0.001 - 1 ETH
390
+ new View({
391
+ instrumentType: InstrumentType.HISTOGRAM,
392
+ instrumentUnit: 'eth',
393
+ aggregation: new ExplicitBucketHistogramAggregation(
394
+ [0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10],
395
+ true,
396
+ ),
397
+ }),
337
398
  ],
338
399
  });
339
400
  }
@@ -343,7 +404,12 @@ export class OpenTelemetryClient implements TelemetryClient {
343
404
  const tracerProvider = new NodeTracerProvider({
344
405
  resource,
345
406
  spanProcessors: config.tracesCollectorUrl
346
- ? [new BatchSpanProcessor(new OTLPTraceExporter({ url: config.tracesCollectorUrl.href }))]
407
+ ? [
408
+ new MonitoredBatchSpanProcessor(new OTLPTraceExporter({ url: config.tracesCollectorUrl.href }), log, {
409
+ maxQueueSize: config.otelBspMaxQueueSize,
410
+ minTraceDurationMs: config.otelMinTraceDurationMs,
411
+ }),
412
+ ]
347
413
  : [],
348
414
  });
349
415