@aztec/telemetry-client 0.0.1-commit.2448fdb → 0.0.1-commit.2606882
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 +7 -2
- package/dest/attributes.d.ts.map +1 -1
- package/dest/attributes.js +3 -1
- package/dest/config.d.ts +3 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +17 -9
- package/dest/lmdb_metrics.d.ts +2 -2
- package/dest/lmdb_metrics.d.ts.map +1 -1
- package/dest/metrics.d.ts +30 -1
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +161 -0
- package/dest/monitored_batch_span_processor.d.ts +29 -0
- package/dest/monitored_batch_span_processor.d.ts.map +1 -0
- package/dest/monitored_batch_span_processor.js +70 -0
- package/dest/otel.d.ts +1 -1
- package/dest/otel.d.ts.map +1 -1
- package/dest/otel.js +62 -3
- package/dest/otel_propagation.d.ts +3 -1
- package/dest/otel_propagation.d.ts.map +1 -1
- package/dest/otel_propagation.js +49 -1
- package/dest/start.d.ts +1 -1
- package/dest/start.d.ts.map +1 -1
- package/dest/start.js +1 -1
- package/dest/telemetry.d.ts +2 -2
- package/dest/telemetry.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 +3 -3
- package/src/attributes.ts +8 -1
- package/src/config.ts +24 -9
- package/src/metrics.ts +167 -0
- package/src/monitored_batch_span_processor.ts +93 -0
- package/src/otel.ts +38 -2
- package/src/otel_propagation.ts +42 -1
- package/src/start.ts +6 -1
- package/src/telemetry.ts +0 -1
- package/src/wrappers/l2_block_stream.ts +1 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"l2_block_stream.d.ts","sourceRoot":"","sources":["../../src/wrappers/l2_block_stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,yBAAyB,EAC9B,KAAK,8BAA8B,EACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,MAAM,EAAa,MAAM,yBAAyB,CAAC;AAEjF,kFAAkF;AAClF,qBAAa,sBAAuB,SAAQ,aAAc,YAAW,SAAS;
|
|
1
|
+
{"version":3,"file":"l2_block_stream.d.ts","sourceRoot":"","sources":["../../src/wrappers/l2_block_stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,yBAAyB,EAC9B,KAAK,8BAA8B,EACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,MAAM,EAAa,MAAM,yBAAyB,CAAC;AAEjF,kFAAkF;AAClF,qBAAa,sBAAuB,SAAQ,aAAc,YAAW,SAAS;aAK1D,MAAM,EAAE,MAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI;IALvB,YACE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,GAAG,cAAc,GAAG,WAAW,GAAG,gBAAgB,CAAC,EACjG,SAAS,EAAE,8BAA8B,EACzC,OAAO,EAAE,yBAAyB,EAClB,MAAM,EAAE,MAAM,EACb,IAAI,GAAE,MAAwB,EAC/C,GAAG,yCAAqC,EACxC,IAAI,GAAE;QACJ,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,WAAW,CAAC;KACxB,EAGP;IAOQ,IAAI,kBAEZ;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/telemetry-client",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.2606882",
|
|
4
4
|
"inherits": [
|
|
5
5
|
"../package.common.json"
|
|
6
6
|
],
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"!*.test.*"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
31
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
30
|
+
"@aztec/foundation": "0.0.1-commit.2606882",
|
|
31
|
+
"@aztec/stdlib": "0.0.1-commit.2606882",
|
|
32
32
|
"@opentelemetry/api": "^1.9.0",
|
|
33
33
|
"@opentelemetry/api-logs": "^0.55.0",
|
|
34
34
|
"@opentelemetry/core": "^1.28.0",
|
package/src/attributes.ts
CHANGED
|
@@ -45,6 +45,8 @@ export const BLOCK_NUMBER = 'aztec.block.number';
|
|
|
45
45
|
export const BLOCK_HASH = 'aztec.block.hash';
|
|
46
46
|
/** The slot number */
|
|
47
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';
|
|
48
50
|
/** The checkpoint number */
|
|
49
51
|
export const CHECKPOINT_NUMBER = 'aztec.checkpoint.number';
|
|
50
52
|
/** The parent's block number */
|
|
@@ -94,7 +96,6 @@ export const VALIDATOR_STATUS = 'aztec.validator_status';
|
|
|
94
96
|
|
|
95
97
|
export const P2P_ID = 'aztec.p2p.id';
|
|
96
98
|
export const P2P_REQ_RESP_PROTOCOL = 'aztec.p2p.req_resp.protocol';
|
|
97
|
-
export const P2P_REQ_RESP_BATCH_REQUESTS_COUNT = 'aztec.p2p.req_resp.batch_requests_count';
|
|
98
99
|
/** The state of a peer (Healthy, Disconnect, Banned) */
|
|
99
100
|
export const P2P_PEER_SCORE_STATE = 'aztec.p2p.peer_score_state';
|
|
100
101
|
export const POOL_NAME = 'aztec.pool.name';
|
|
@@ -151,5 +152,11 @@ 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 */
|
|
152
153
|
export const L1_BLOCK_PROPOSAL_USED_TRACE = 'aztec.l1.block_proposal_used_trace';
|
|
153
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
|
+
|
|
154
161
|
/** The address of an attester (validator) participating in consensus */
|
|
155
162
|
export const ATTESTER_ADDRESS = 'aztec.attester.address';
|
package/src/config.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
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;
|
|
@@ -12,35 +17,35 @@ export interface TelemetryClientConfig {
|
|
|
12
17
|
otelExportTimeoutMs: number;
|
|
13
18
|
otelExcludeMetrics: string[];
|
|
14
19
|
otelIncludeMetrics: string[];
|
|
20
|
+
otelMinTraceDurationMs: number;
|
|
21
|
+
otelBspMaxQueueSize: number;
|
|
15
22
|
}
|
|
16
23
|
|
|
17
24
|
export const telemetryClientConfigMappings: ConfigMappingsType<TelemetryClientConfig> = {
|
|
18
25
|
metricsCollectorUrl: {
|
|
19
26
|
env: 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT',
|
|
20
27
|
description: 'The URL of the telemetry collector for metrics',
|
|
21
|
-
parseEnv: (val: string) =>
|
|
28
|
+
parseEnv: (val: string) => new URL(val),
|
|
22
29
|
},
|
|
23
30
|
tracesCollectorUrl: {
|
|
24
31
|
env: 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT',
|
|
25
32
|
description: 'The URL of the telemetry collector for traces',
|
|
26
|
-
parseEnv: (val: string) =>
|
|
33
|
+
parseEnv: (val: string) => new URL(val),
|
|
27
34
|
},
|
|
28
35
|
logsCollectorUrl: {
|
|
29
36
|
env: 'OTEL_EXPORTER_OTLP_LOGS_ENDPOINT',
|
|
30
37
|
description: 'The URL of the telemetry collector for logs',
|
|
31
|
-
parseEnv: (val: string) =>
|
|
38
|
+
parseEnv: (val: string) => new URL(val),
|
|
32
39
|
},
|
|
33
40
|
otelCollectIntervalMs: {
|
|
34
41
|
env: 'OTEL_COLLECT_INTERVAL_MS',
|
|
35
42
|
description: 'The interval at which to collect metrics',
|
|
36
|
-
|
|
37
|
-
parseEnv: (val: string) => parseInt(val),
|
|
43
|
+
...numberConfigHelper(60000),
|
|
38
44
|
},
|
|
39
45
|
otelExportTimeoutMs: {
|
|
40
46
|
env: 'OTEL_EXPORT_TIMEOUT_MS',
|
|
41
47
|
description: 'The timeout for exporting metrics',
|
|
42
|
-
|
|
43
|
-
parseEnv: (val: string) => parseInt(val),
|
|
48
|
+
...numberConfigHelper(30000),
|
|
44
49
|
},
|
|
45
50
|
otelExcludeMetrics: {
|
|
46
51
|
env: 'OTEL_EXCLUDE_METRICS',
|
|
@@ -54,6 +59,16 @@ export const telemetryClientConfigMappings: ConfigMappingsType<TelemetryClientCo
|
|
|
54
59
|
: [],
|
|
55
60
|
defaultValue: [],
|
|
56
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
|
+
},
|
|
57
72
|
otelIncludeMetrics: {
|
|
58
73
|
env: 'OTEL_INCLUDE_METRICS',
|
|
59
74
|
description: 'A list of metric prefixes to include in export (ignored if OTEL_EXCLUDE_METRICS is set)',
|
|
@@ -70,7 +85,7 @@ export const telemetryClientConfigMappings: ConfigMappingsType<TelemetryClientCo
|
|
|
70
85
|
publicMetricsCollectorUrl: {
|
|
71
86
|
env: 'PUBLIC_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT',
|
|
72
87
|
description: 'A URL to publish a subset of metrics for public consumption',
|
|
73
|
-
parseEnv: (val: string) =>
|
|
88
|
+
parseEnv: (val: string) => new URL(val),
|
|
74
89
|
},
|
|
75
90
|
publicMetricsCollectFrom: {
|
|
76
91
|
env: 'PUBLIC_OTEL_COLLECT_FROM',
|
package/src/metrics.ts
CHANGED
|
@@ -308,6 +308,12 @@ export const ARCHIVER_SYNC_PER_BLOCK: MetricDefinition = {
|
|
|
308
308
|
unit: 'ms',
|
|
309
309
|
valueType: ValueType.INT,
|
|
310
310
|
};
|
|
311
|
+
export const ARCHIVER_SYNC_PER_CHECKPOINT: MetricDefinition = {
|
|
312
|
+
name: 'aztec.archiver.checkpoint.sync_per_item_duration',
|
|
313
|
+
description: 'Duration to sync a checkpoint',
|
|
314
|
+
unit: 'ms',
|
|
315
|
+
valueType: ValueType.INT,
|
|
316
|
+
};
|
|
311
317
|
export const ARCHIVER_SYNC_BLOCK_COUNT: MetricDefinition = {
|
|
312
318
|
name: 'aztec.archiver.block.sync_count',
|
|
313
319
|
description: 'Number of blocks synced from L1',
|
|
@@ -350,6 +356,19 @@ export const ARCHIVER_BLOCK_PROPOSAL_TX_TARGET_COUNT: MetricDefinition = {
|
|
|
350
356
|
valueType: ValueType.INT,
|
|
351
357
|
};
|
|
352
358
|
|
|
359
|
+
export const ARCHIVER_CHECKPOINT_L1_INCLUSION_DELAY: MetricDefinition = {
|
|
360
|
+
name: 'aztec.archiver.checkpoint_l1_inclusion_delay',
|
|
361
|
+
description: 'Seconds into the L2 slot when the checkpoint L1 tx was included',
|
|
362
|
+
unit: 's',
|
|
363
|
+
valueType: ValueType.INT,
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
export const ARCHIVER_CHECKPOINT_PROMOTED_COUNT: MetricDefinition = {
|
|
367
|
+
name: 'aztec.archiver.checkpoint_promoted_count',
|
|
368
|
+
description: 'Number of checkpoints promoted from proposed (blob fetch skipped)',
|
|
369
|
+
valueType: ValueType.INT,
|
|
370
|
+
};
|
|
371
|
+
|
|
353
372
|
export const NODE_RECEIVE_TX_DURATION: MetricDefinition = {
|
|
354
373
|
name: 'aztec.node.receive_tx.duration',
|
|
355
374
|
description: 'The duration of the receiveTx method',
|
|
@@ -381,6 +400,12 @@ export const SEQUENCER_STATE_TRANSITION_BUFFER_DURATION: MetricDefinition = {
|
|
|
381
400
|
unit: 'ms',
|
|
382
401
|
valueType: ValueType.INT,
|
|
383
402
|
};
|
|
403
|
+
export const SEQUENCER_STATE_DURATION: MetricDefinition = {
|
|
404
|
+
name: 'aztec.sequencer.state_duration',
|
|
405
|
+
description: 'Wall-clock time spent in each sequencer state, labelled by the state being left',
|
|
406
|
+
unit: 'ms',
|
|
407
|
+
valueType: ValueType.INT,
|
|
408
|
+
};
|
|
384
409
|
export const SEQUENCER_BLOCK_BUILD_DURATION: MetricDefinition = {
|
|
385
410
|
name: 'aztec.sequencer.block.build_duration',
|
|
386
411
|
description: 'Duration to build a block',
|
|
@@ -398,6 +423,12 @@ export const SEQUENCER_BLOCK_COUNT: MetricDefinition = {
|
|
|
398
423
|
description: 'Number of blocks built by this sequencer',
|
|
399
424
|
valueType: ValueType.INT,
|
|
400
425
|
};
|
|
426
|
+
export const SEQUENCER_BLOCK_INTER_BLOCK_TIME: MetricDefinition = {
|
|
427
|
+
name: 'aztec.sequencer.block.inter_block_time',
|
|
428
|
+
description: 'Wall-clock time elapsed between consecutive blocks being built by this sequencer',
|
|
429
|
+
unit: 'ms',
|
|
430
|
+
valueType: ValueType.INT,
|
|
431
|
+
};
|
|
401
432
|
export const SEQUENCER_CURRENT_SLOT_REWARDS: MetricDefinition = {
|
|
402
433
|
name: 'aztec.sequencer.current_slot_rewards',
|
|
403
434
|
description: 'The rewards earned per filled slot',
|
|
@@ -470,6 +501,25 @@ export const SEQUENCER_CHECKPOINT_BUILD_DURATION: MetricDefinition = {
|
|
|
470
501
|
unit: 'ms',
|
|
471
502
|
valueType: ValueType.INT,
|
|
472
503
|
};
|
|
504
|
+
export const SEQUENCER_CHECKPOINT_START_TO_FIRST_BLOCK_DURATION: MetricDefinition = {
|
|
505
|
+
name: 'aztec.sequencer.checkpoint.start_to_first_block_duration',
|
|
506
|
+
description: 'Time from starting checkpoint work to the first block finishing build',
|
|
507
|
+
unit: 'ms',
|
|
508
|
+
valueType: ValueType.INT,
|
|
509
|
+
};
|
|
510
|
+
export const SEQUENCER_CHECKPOINT_LAST_BLOCK_TO_BROADCAST_DURATION: MetricDefinition = {
|
|
511
|
+
name: 'aztec.sequencer.checkpoint.last_block_to_broadcast_duration',
|
|
512
|
+
description: 'Time from the final block finishing build to the checkpoint proposal being broadcast',
|
|
513
|
+
unit: 'ms',
|
|
514
|
+
valueType: ValueType.INT,
|
|
515
|
+
};
|
|
516
|
+
export const SEQUENCER_PIPELINED_CHECKPOINT_BUILD_START_OFFSET_FROM_SLOT_BOUNDARY: MetricDefinition = {
|
|
517
|
+
name: 'aztec.sequencer.pipelined_checkpoint.build_start_offset_from_slot_boundary',
|
|
518
|
+
description:
|
|
519
|
+
'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.',
|
|
520
|
+
unit: 'ms',
|
|
521
|
+
valueType: ValueType.INT,
|
|
522
|
+
};
|
|
473
523
|
export const SEQUENCER_CHECKPOINT_BLOCK_COUNT: MetricDefinition = {
|
|
474
524
|
name: 'aztec.sequencer.checkpoint.block_count',
|
|
475
525
|
description: 'Number of blocks built in a checkpoint',
|
|
@@ -497,6 +547,21 @@ export const SEQUENCER_CHECKPOINT_SUCCESS_COUNT: MetricDefinition = {
|
|
|
497
547
|
description: 'The number of times checkpoint publishing succeeded',
|
|
498
548
|
valueType: ValueType.INT,
|
|
499
549
|
};
|
|
550
|
+
export const SEQUENCER_PIPELINE_DEPTH: MetricDefinition = {
|
|
551
|
+
name: 'aztec.sequencer.pipeline.depth',
|
|
552
|
+
description: 'Current pipeline depth when builder pipelining is enabled',
|
|
553
|
+
valueType: ValueType.INT,
|
|
554
|
+
};
|
|
555
|
+
export const SEQUENCER_PIPELINE_DISCARDS_COUNT: MetricDefinition = {
|
|
556
|
+
name: 'aztec.sequencer.pipeline.discards_count',
|
|
557
|
+
description: 'The number of times a pipeline was discarded',
|
|
558
|
+
valueType: ValueType.INT,
|
|
559
|
+
};
|
|
560
|
+
export const SEQUENCER_PIPELINE_PARENT_CHECKPOINT_MISMATCH_COUNT: MetricDefinition = {
|
|
561
|
+
name: 'aztec.sequencer.pipeline.parent_checkpoint_mismatch_count',
|
|
562
|
+
description: 'The number of times a pipelined checkpoint was discarded because the parent did not match expectations',
|
|
563
|
+
valueType: ValueType.INT,
|
|
564
|
+
};
|
|
500
565
|
|
|
501
566
|
// Fisherman fee analysis metrics
|
|
502
567
|
export const FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED: MetricDefinition = {
|
|
@@ -664,6 +729,24 @@ export const L1_PUBLISHER_TX_TOTAL_FEE: MetricDefinition = {
|
|
|
664
729
|
unit: 'eth',
|
|
665
730
|
valueType: ValueType.DOUBLE,
|
|
666
731
|
};
|
|
732
|
+
export const PROVER_NODE_ESTIMATED_SUBMISSION_GAS: MetricDefinition = {
|
|
733
|
+
name: 'aztec.prover_node.estimated_submission.gas',
|
|
734
|
+
description: 'Estimated gas for a proof submission tx (proof publishing disabled, not actually sent)',
|
|
735
|
+
unit: 'gas',
|
|
736
|
+
valueType: ValueType.INT,
|
|
737
|
+
};
|
|
738
|
+
export const PROVER_NODE_ESTIMATED_SUBMISSION_GAS_PRICE: MetricDefinition = {
|
|
739
|
+
name: 'aztec.prover_node.estimated_submission.gas_price',
|
|
740
|
+
description: 'Estimated effective gas price for a proof submission tx (proof publishing disabled, not actually sent)',
|
|
741
|
+
unit: 'gwei',
|
|
742
|
+
valueType: ValueType.DOUBLE,
|
|
743
|
+
};
|
|
744
|
+
export const PROVER_NODE_ESTIMATED_SUBMISSION_TOTAL_FEE: MetricDefinition = {
|
|
745
|
+
name: 'aztec.prover_node.estimated_submission.total_fee',
|
|
746
|
+
description: 'Estimated total L1 fee for a proof submission tx (proof publishing disabled, not actually sent)',
|
|
747
|
+
unit: 'eth',
|
|
748
|
+
valueType: ValueType.DOUBLE,
|
|
749
|
+
};
|
|
667
750
|
|
|
668
751
|
export const L1_BLOCK_HEIGHT: MetricDefinition = {
|
|
669
752
|
name: 'aztec.l1.block_height',
|
|
@@ -757,6 +840,12 @@ export const PEER_MANAGER_PEER_COUNT: MetricDefinition = {
|
|
|
757
840
|
unit: 'peers',
|
|
758
841
|
valueType: ValueType.INT,
|
|
759
842
|
};
|
|
843
|
+
export const PEER_MANAGER_HEALTHY_PEER_COUNT: MetricDefinition = {
|
|
844
|
+
name: 'aztec.peer_manager.healthy_peer_count',
|
|
845
|
+
description: 'Number of healthy (non-protected, non-banned) peers',
|
|
846
|
+
unit: 'peers',
|
|
847
|
+
valueType: ValueType.INT,
|
|
848
|
+
};
|
|
760
849
|
export const PEER_MANAGER_LOW_SCORE_DISCONNECTS: MetricDefinition = {
|
|
761
850
|
name: 'aztec.peer_manager.low_score_disconnects',
|
|
762
851
|
description: 'Number of peers disconnected due to low score',
|
|
@@ -886,6 +975,12 @@ export const P2P_GOSSIP_AGG_MESSAGE_VALIDATION_DURATION_AVG: MetricDefinition =
|
|
|
886
975
|
valueType: ValueType.INT,
|
|
887
976
|
};
|
|
888
977
|
|
|
978
|
+
export const P2P_GOSSIP_SLOW_VALIDATION_COUNT: MetricDefinition = {
|
|
979
|
+
name: 'aztec.p2p.gossip.slow_validation_count',
|
|
980
|
+
description: 'Number of gossip validations that exceeded 75% of the mcache eviction window',
|
|
981
|
+
valueType: ValueType.INT,
|
|
982
|
+
};
|
|
983
|
+
|
|
889
984
|
export const PUBLIC_PROCESSOR_TX_DURATION: MetricDefinition = {
|
|
890
985
|
name: 'aztec.public_processor.tx_duration',
|
|
891
986
|
description: 'Duration to process a public transaction',
|
|
@@ -949,6 +1044,17 @@ export const PUBLIC_PROCESSOR_TREE_INSERTION: MetricDefinition = {
|
|
|
949
1044
|
unit: 'ms',
|
|
950
1045
|
valueType: ValueType.INT,
|
|
951
1046
|
};
|
|
1047
|
+
export const PUBLIC_PROCESSOR_SILENTLY_SKIPPED_COUNT: MetricDefinition = {
|
|
1048
|
+
name: 'aztec.public_processor.silently_skipped_count',
|
|
1049
|
+
description: 'Public txs fully processed then skipped (e.g. blob-field limit); not counted as processed or failed',
|
|
1050
|
+
valueType: ValueType.INT,
|
|
1051
|
+
};
|
|
1052
|
+
export const PUBLIC_PROCESSOR_SILENTLY_SKIPPED_DURATION: MetricDefinition = {
|
|
1053
|
+
name: 'aztec.public_processor.silently_skipped_duration',
|
|
1054
|
+
description: 'Wall-clock time spent processing txs that were then silently skipped',
|
|
1055
|
+
unit: 'ms',
|
|
1056
|
+
valueType: ValueType.INT,
|
|
1057
|
+
};
|
|
952
1058
|
|
|
953
1059
|
export const PUBLIC_EXECUTOR_PREFIX = 'aztec.public_executor.';
|
|
954
1060
|
export const PUBLIC_EXECUTOR_SIMULATION_COUNT: MetricDefinition = {
|
|
@@ -1263,6 +1369,19 @@ export const VALIDATOR_RE_EXECUTION_TX_COUNT: MetricDefinition = {
|
|
|
1263
1369
|
unit: 'tx',
|
|
1264
1370
|
valueType: ValueType.INT,
|
|
1265
1371
|
};
|
|
1372
|
+
export const VALIDATOR_CHECKPOINT_PROPOSAL_TO_PIPELINED_STATE_DURATION: MetricDefinition = {
|
|
1373
|
+
name: 'aztec.validator.checkpoint_proposal_to_pipelined_state_duration',
|
|
1374
|
+
description: 'Time from receiving a checkpoint proposal to setting proposed checkpoint state for pipelining',
|
|
1375
|
+
unit: 'ms',
|
|
1376
|
+
valueType: ValueType.INT,
|
|
1377
|
+
};
|
|
1378
|
+
export const VALIDATOR_CHECKPOINT_PROPOSAL_RECEIVE_OFFSET_FROM_NEXT_SLOT_BOUNDARY: MetricDefinition = {
|
|
1379
|
+
name: 'aztec.validator.checkpoint.proposal_receive_offset_from_next_slot_boundary',
|
|
1380
|
+
description:
|
|
1381
|
+
'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.',
|
|
1382
|
+
unit: 'ms',
|
|
1383
|
+
valueType: ValueType.INT,
|
|
1384
|
+
};
|
|
1266
1385
|
|
|
1267
1386
|
export const VALIDATOR_FAILED_REEXECUTION_COUNT: MetricDefinition = {
|
|
1268
1387
|
name: 'aztec.validator.failed_reexecution_count',
|
|
@@ -1518,3 +1637,51 @@ export const IVC_VERIFIER_AGG_DURATION_AVG: MetricDefinition = {
|
|
|
1518
1637
|
unit: 'ms',
|
|
1519
1638
|
valueType: ValueType.DOUBLE,
|
|
1520
1639
|
};
|
|
1640
|
+
|
|
1641
|
+
// HA Signer metrics
|
|
1642
|
+
export const HA_SIGNER_SIGNING_DURATION: MetricDefinition = {
|
|
1643
|
+
name: 'aztec.ha_signer.signing_duration',
|
|
1644
|
+
description: 'End-to-end duration for signing with HA protection (lock + sign + record)',
|
|
1645
|
+
unit: 'ms',
|
|
1646
|
+
valueType: ValueType.INT,
|
|
1647
|
+
};
|
|
1648
|
+
export const HA_SIGNER_SIGNING_SUCCESS_COUNT: MetricDefinition = {
|
|
1649
|
+
name: 'aztec.ha_signer.signing_success_count',
|
|
1650
|
+
description: 'Count of successful signing operations',
|
|
1651
|
+
valueType: ValueType.INT,
|
|
1652
|
+
};
|
|
1653
|
+
export const HA_SIGNER_DUTY_ALREADY_SIGNED_COUNT: MetricDefinition = {
|
|
1654
|
+
name: 'aztec.ha_signer.duty_already_signed_count',
|
|
1655
|
+
description: 'Count of DutyAlreadySignedError (expected in HA; another node signed first)',
|
|
1656
|
+
valueType: ValueType.INT,
|
|
1657
|
+
};
|
|
1658
|
+
export const HA_SIGNER_SLASHING_PROTECTION_COUNT: MetricDefinition = {
|
|
1659
|
+
name: 'aztec.ha_signer.slashing_protection_count',
|
|
1660
|
+
description: 'Count of SlashingProtectionError (attempted to sign different data)',
|
|
1661
|
+
valueType: ValueType.INT,
|
|
1662
|
+
};
|
|
1663
|
+
export const HA_SIGNER_SIGNING_ERROR_COUNT: MetricDefinition = {
|
|
1664
|
+
name: 'aztec.ha_signer.signing_error_count',
|
|
1665
|
+
description: 'Count of signing function failures (lock deleted for retry)',
|
|
1666
|
+
valueType: ValueType.INT,
|
|
1667
|
+
};
|
|
1668
|
+
export const HA_SIGNER_LOCK_ACQUIRED_COUNT: MetricDefinition = {
|
|
1669
|
+
name: 'aztec.ha_signer.lock_acquired_count',
|
|
1670
|
+
description: 'Count of lock acquisitions (new lock acquired vs existing record found)',
|
|
1671
|
+
valueType: ValueType.INT,
|
|
1672
|
+
};
|
|
1673
|
+
export const HA_SIGNER_CLEANUP_STUCK_DUTIES_COUNT: MetricDefinition = {
|
|
1674
|
+
name: 'aztec.ha_signer.cleanup_stuck_duties_count',
|
|
1675
|
+
description: 'Number of stuck duties cleaned up per cleanup run',
|
|
1676
|
+
valueType: ValueType.INT,
|
|
1677
|
+
};
|
|
1678
|
+
export const HA_SIGNER_CLEANUP_OLD_DUTIES_COUNT: MetricDefinition = {
|
|
1679
|
+
name: 'aztec.ha_signer.cleanup_old_duties_count',
|
|
1680
|
+
description: 'Number of old duties cleaned up',
|
|
1681
|
+
valueType: ValueType.INT,
|
|
1682
|
+
};
|
|
1683
|
+
export const HA_SIGNER_CLEANUP_OUTDATED_ROLLUP_DUTIES_COUNT: MetricDefinition = {
|
|
1684
|
+
name: 'aztec.ha_signer.cleanup_outdated_rollup_duties_count',
|
|
1685
|
+
description: 'Number of duties cleaned due to rollup upgrade',
|
|
1686
|
+
valueType: ValueType.INT,
|
|
1687
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
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
|
+
export type MonitoredBatchSpanProcessorConfig = BufferConfig & {
|
|
14
|
+
minTraceDurationMs?: number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Wraps BatchSpanProcessor to emit warnings when spans are dropped due to a full queue.
|
|
19
|
+
* The standard BatchSpanProcessor silently discards spans when its internal queue reaches
|
|
20
|
+
* maxQueueSize, making telemetry data loss invisible to operators.
|
|
21
|
+
*/
|
|
22
|
+
export class MonitoredBatchSpanProcessor extends BatchSpanProcessor {
|
|
23
|
+
private readonly maxQueueSize: number;
|
|
24
|
+
private readonly minTraceDurationMs: number;
|
|
25
|
+
private readonly log: Logger;
|
|
26
|
+
|
|
27
|
+
private approxQueueSize = 0;
|
|
28
|
+
private droppedSinceLastWarning = 0;
|
|
29
|
+
private totalDropped = 0;
|
|
30
|
+
private lastWarningTime = 0;
|
|
31
|
+
|
|
32
|
+
constructor(exporter: SpanExporter, log: Logger, config?: MonitoredBatchSpanProcessorConfig) {
|
|
33
|
+
const maxQueueSize = config?.maxQueueSize ?? 2048;
|
|
34
|
+
super(exporter, { ...config, maxQueueSize });
|
|
35
|
+
this.maxQueueSize = maxQueueSize;
|
|
36
|
+
this.minTraceDurationMs = Math.max(0, config?.minTraceDurationMs ?? DEFAULT_MIN_TRACE_DURATION_MS);
|
|
37
|
+
this.log = log;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override onStart(span: Span, parentContext: Context): void {
|
|
41
|
+
super.onStart(span, parentContext);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override onEnd(span: ReadableSpan): void {
|
|
45
|
+
if (this.shouldDropShortSpan(span)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this.approxQueueSize >= this.maxQueueSize) {
|
|
50
|
+
this.droppedSinceLastWarning++;
|
|
51
|
+
this.totalDropped++;
|
|
52
|
+
this.maybeLogDropWarning();
|
|
53
|
+
} else {
|
|
54
|
+
this.approxQueueSize++;
|
|
55
|
+
}
|
|
56
|
+
super.onEnd(span);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
override async forceFlush(): Promise<void> {
|
|
60
|
+
await super.forceFlush();
|
|
61
|
+
this.approxQueueSize = 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override async shutdown(): Promise<void> {
|
|
65
|
+
if (this.totalDropped > 0) {
|
|
66
|
+
this.log.warn(`BatchSpanProcessor shutting down with ${this.totalDropped} total spans dropped`, {
|
|
67
|
+
totalDropped: this.totalDropped,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
await super.shutdown();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private shouldDropShortSpan(span: ReadableSpan): boolean {
|
|
74
|
+
return (
|
|
75
|
+
this.minTraceDurationMs > 0 &&
|
|
76
|
+
span.status.code !== SpanStatusCode.ERROR &&
|
|
77
|
+
hrTimeToMilliseconds(span.duration) < this.minTraceDurationMs
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private maybeLogDropWarning(): void {
|
|
82
|
+
const now = Date.now();
|
|
83
|
+
if (now - this.lastWarningTime >= DROP_WARNING_INTERVAL_MS) {
|
|
84
|
+
this.log.warn(
|
|
85
|
+
`BatchSpanProcessor dropping spans: queue full (maxQueueSize=${this.maxQueueSize}). ` +
|
|
86
|
+
`${this.droppedSinceLastWarning} dropped since last warning, ${this.totalDropped} total.`,
|
|
87
|
+
{ droppedSinceLastWarning: this.droppedSinceLastWarning, totalDropped: this.totalDropped },
|
|
88
|
+
);
|
|
89
|
+
this.droppedSinceLastWarning = 0;
|
|
90
|
+
this.lastWarningTime = now;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
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 {
|
|
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';
|
|
@@ -334,6 +335,36 @@ export class OpenTelemetryClient implements TelemetryClient {
|
|
|
334
335
|
true,
|
|
335
336
|
),
|
|
336
337
|
}),
|
|
338
|
+
// L1 gas prices in gwei: priority fees ~0.01-10, base fees ~1-500, spikes to 1000+
|
|
339
|
+
new View({
|
|
340
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
341
|
+
instrumentUnit: 'gwei',
|
|
342
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
343
|
+
[0.1, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1_000],
|
|
344
|
+
true,
|
|
345
|
+
),
|
|
346
|
+
}),
|
|
347
|
+
// L1 gas consumption: tx gas 100k-30M, calldata/blob gas varies
|
|
348
|
+
new View({
|
|
349
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
350
|
+
instrumentUnit: 'gas',
|
|
351
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
352
|
+
[
|
|
353
|
+
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,
|
|
354
|
+
30_000_000,
|
|
355
|
+
],
|
|
356
|
+
true,
|
|
357
|
+
),
|
|
358
|
+
}),
|
|
359
|
+
// L1 tx total fee in ETH: typically 0.001 - 1 ETH
|
|
360
|
+
new View({
|
|
361
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
362
|
+
instrumentUnit: 'eth',
|
|
363
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
364
|
+
[0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10],
|
|
365
|
+
true,
|
|
366
|
+
),
|
|
367
|
+
}),
|
|
337
368
|
],
|
|
338
369
|
});
|
|
339
370
|
}
|
|
@@ -343,7 +374,12 @@ export class OpenTelemetryClient implements TelemetryClient {
|
|
|
343
374
|
const tracerProvider = new NodeTracerProvider({
|
|
344
375
|
resource,
|
|
345
376
|
spanProcessors: config.tracesCollectorUrl
|
|
346
|
-
? [
|
|
377
|
+
? [
|
|
378
|
+
new MonitoredBatchSpanProcessor(new OTLPTraceExporter({ url: config.tracesCollectorUrl.href }), log, {
|
|
379
|
+
maxQueueSize: config.otelBspMaxQueueSize,
|
|
380
|
+
minTraceDurationMs: config.otelMinTraceDurationMs,
|
|
381
|
+
}),
|
|
382
|
+
]
|
|
347
383
|
: [],
|
|
348
384
|
});
|
|
349
385
|
|
package/src/otel_propagation.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { DiagnosticsMiddleware } from '@aztec/foundation/json-rpc/server';
|
|
2
|
+
|
|
1
3
|
import { ROOT_CONTEXT, type Span, SpanKind, SpanStatusCode, propagation } from '@opentelemetry/api';
|
|
2
4
|
import type Koa from 'koa';
|
|
3
5
|
|
|
@@ -17,7 +19,7 @@ export function getOtelJsonRpcPropagationMiddleware(
|
|
|
17
19
|
const context = propagation.extract(ROOT_CONTEXT, ctx.request.headers);
|
|
18
20
|
const method = (ctx.request.body as any)?.method;
|
|
19
21
|
return tracer.startActiveSpan(
|
|
20
|
-
`JsonRpcServer.${method ?? '
|
|
22
|
+
`JsonRpcServer.${method ?? 'batch'}`,
|
|
21
23
|
{ kind: SpanKind.SERVER },
|
|
22
24
|
context,
|
|
23
25
|
async (span: Span): Promise<void> => {
|
|
@@ -48,3 +50,42 @@ export function getOtelJsonRpcPropagationMiddleware(
|
|
|
48
50
|
);
|
|
49
51
|
};
|
|
50
52
|
}
|
|
53
|
+
|
|
54
|
+
export function getOtelJsonRpcDiagnosticsMiddleware(): DiagnosticsMiddleware {
|
|
55
|
+
return function otelJsonRpcDiagnostics(ctx, next) {
|
|
56
|
+
const [namespace, method] = splitNamespace(ctx.method);
|
|
57
|
+
const scope = namespace ?? 'UnknownHandler';
|
|
58
|
+
const tracer = getTelemetryClient().getTracer(scope);
|
|
59
|
+
return tracer.startActiveSpan(
|
|
60
|
+
`${scope}.${method}`,
|
|
61
|
+
{ kind: SpanKind.INTERNAL, attributes: { [ATTR_JSONRPC_METHOD]: ctx.method } },
|
|
62
|
+
async span => {
|
|
63
|
+
if (ctx.id !== null) {
|
|
64
|
+
span.setAttribute(ATTR_JSONRPC_REQUEST_ID, ctx.id);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
await next();
|
|
69
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
70
|
+
} catch (err) {
|
|
71
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err instanceof Error ? err.message : String(err) });
|
|
72
|
+
if (typeof err === 'string' || err instanceof Error) {
|
|
73
|
+
span.recordException(err);
|
|
74
|
+
}
|
|
75
|
+
throw err;
|
|
76
|
+
} finally {
|
|
77
|
+
span.end();
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function splitNamespace(fullMethod: string): [namespace: string | undefined, method: string] {
|
|
85
|
+
const idx = fullMethod.indexOf('_');
|
|
86
|
+
if (idx > -1) {
|
|
87
|
+
return [fullMethod.slice(0, idx), fullMethod.slice(idx + 1)];
|
|
88
|
+
} else {
|
|
89
|
+
return [undefined, fullMethod];
|
|
90
|
+
}
|
|
91
|
+
}
|
package/src/start.ts
CHANGED
|
@@ -19,7 +19,12 @@ export async function initTelemetryClient(
|
|
|
19
19
|
return telemetry;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
if (
|
|
22
|
+
if (
|
|
23
|
+
config.metricsCollectorUrl ||
|
|
24
|
+
config.publicMetricsCollectorUrl ||
|
|
25
|
+
config.tracesCollectorUrl ||
|
|
26
|
+
config.logsCollectorUrl
|
|
27
|
+
) {
|
|
23
28
|
log.info(`Using OpenTelemetry client with custom collector`);
|
|
24
29
|
// Lazy load OpenTelemetry to avoid loading heavy deps at startup
|
|
25
30
|
const { OpenTelemetryClient } = await import('./otel.js');
|
package/src/telemetry.ts
CHANGED
|
@@ -11,10 +11,7 @@ import { type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client'
|
|
|
11
11
|
/** Extends an L2BlockStream with a tracer to create a new trace per iteration. */
|
|
12
12
|
export class TraceableL2BlockStream extends L2BlockStream implements Traceable {
|
|
13
13
|
constructor(
|
|
14
|
-
l2BlockSource: Pick<
|
|
15
|
-
L2BlockSource,
|
|
16
|
-
'getBlocks' | 'getBlockHeader' | 'getL2Tips' | 'getCheckpoints' | 'getCheckpointedBlocks'
|
|
17
|
-
>,
|
|
14
|
+
l2BlockSource: Pick<L2BlockSource, 'getBlocks' | 'getBlockData' | 'getL2Tips' | 'getCheckpoints'>,
|
|
18
15
|
localData: L2BlockStreamLocalDataProvider,
|
|
19
16
|
handler: L2BlockStreamEventHandler,
|
|
20
17
|
public readonly tracer: Tracer,
|