diff --git a/crates/blockchain/src/coverage.rs b/crates/blockchain/src/coverage.rs index 2019e41b..2cd019f3 100644 --- a/crates/blockchain/src/coverage.rs +++ b/crates/blockchain/src/coverage.rs @@ -56,15 +56,27 @@ fn cov_add(seen: &mut [bool], has_subnet: &mut [bool], bits: &AggregationBits) { } fn cov_record(section: &str, seen: &[bool], has_subnet: &[bool]) { - // TODO(#398): emit a per-subnet breakdown (subnet=subnet_N) alongside the - // subnet=combined total. `has_subnet` already tracks which subnets are - // covered, but we only report the aggregate count here; the per-subnet - // label is reserved in the metric definition and not yet populated. metrics::set_attestation_aggregate_coverage_validators( section, "combined", seen.iter().filter(|&&b| b).count() as i64, ); + let cc = has_subnet.len(); + if cc > 0 { + let mut subnet_counts = vec![0i64; cc]; + for (vid, &was_seen) in seen.iter().enumerate() { + if was_seen { + subnet_counts[vid % cc] += 1; + } + } + for (i, &count) in subnet_counts.iter().enumerate() { + metrics::set_attestation_aggregate_coverage_validators( + section, + &format!("subnet_{i}"), + count, + ); + } + } metrics::set_attestation_aggregate_coverage_subnets( section, has_subnet.iter().filter(|&&b| b).count() as i64, diff --git a/crates/blockchain/src/metrics.rs b/crates/blockchain/src/metrics.rs index 8e0c6d5e..259afb16 100644 --- a/crates/blockchain/src/metrics.rs +++ b/crates/blockchain/src/metrics.rs @@ -128,9 +128,8 @@ static LEAN_ATTESTATION_AGGREGATE_COVERAGE_VALIDATORS: std::sync::LazyLocksubnet=combined (per-subnet breakdown reserved, not yet populated) | +| `lean_attestation_aggregate_coverage_validators` | Gauge | Validator coverage in attestation aggregate reports | Per round, per section (see note above) | section=timely,late,block,combined,agg_start_new,proposal_combined
subnet=combined,subnet_0,subnet_1,…,subnet_N-1 | | `lean_attestation_aggregate_coverage_subnets` | Gauge | Number of covered subnets in attestation aggregate reports | Per round, per section (see note above) | section=timely,late,block,combined,agg_start_new,proposal_combined | | `lean_attestation_aggregate_coverage_diff_validators` | Gauge | Validators in the symmetric difference between block-included aggregates and locally-aggregated timely aggregates for the same slot | On block import, when the head carries the round's votes (see note above) | direction=block_only,timely_only |