chore(style): expose invalidation fallback telemetry

This commit is contained in:
ldm0
2026-08-28 15:18:42 +08:00
committed by Donough Liu
parent 9720a46768
commit bf125e00f6
3 changed files with 138 additions and 5 deletions
+23 -4
View File
@@ -19,10 +19,11 @@ use super::{
target_result::{
StyleInvalidationCleanupClassConstraint, StyleInvalidationDiagnosticTargetResult,
StyleInvalidationDiagnosticTargetResultSummaryTraceCountsSink,
StyleInvalidationRetainedCleanupPlanSink, StyleInvalidationRetainedCleanupRoots,
StyleInvalidationRetainedCleanupRootsSink, StyleInvalidationRetainedCleanupSink,
StyleInvalidationRetainedTargetResults, StyleInvalidationRetainedTargetResultsSink,
StyleInvalidationRetainedTargetResultsTrace, retained_target_results_for_source_results,
StyleInvalidationFallbackTelemetry, StyleInvalidationRetainedCleanupPlanSink,
StyleInvalidationRetainedCleanupRoots, StyleInvalidationRetainedCleanupRootsSink,
StyleInvalidationRetainedCleanupSink, StyleInvalidationRetainedTargetResults,
StyleInvalidationRetainedTargetResultsSink, StyleInvalidationRetainedTargetResultsTrace,
retained_target_results_for_source_results,
},
};
@@ -389,6 +390,11 @@ impl FinalizedStyleInvalidationResult {
) -> &StyleInvalidationDiagnosticTargetResultSummary {
self.cleanup.trace.diagnostic_target_result_summary()
}
#[cfg(test)]
pub(super) fn fallback_telemetry(&self) -> StyleInvalidationFallbackTelemetry {
self.cleanup.trace.fallback_telemetry()
}
}
impl StyleInvalidationFinalCleanup {
@@ -564,6 +570,7 @@ impl StyleInvalidationFinalCleanup {
fn trace_drain_attempt(&self, summary: &StyleInvalidationDrainSummary) {
let mut drain_fields = StyleInvalidationDrainTraceFields::default();
summary.record_trace_fields_into(&mut drain_fields);
let fallback_telemetry = self.trace.fallback_telemetry();
let mut diagnostic_target_result_counts =
StyleInvalidationDrainDiagnosticTargetResultCounts::default();
self.trace
@@ -591,6 +598,14 @@ impl StyleInvalidationFinalCleanup {
source_scope_fallback_roots = ?drain_fields.source_scope_fallback_roots,
clear_shadow_cascade_data_for_cleanup_target =
self.effects.clears_shadow_cascade_data_for_cleanup_target(),
exact_target_result_count = fallback_telemetry.exact_target_result_count(),
inexact_target_result_count = fallback_telemetry.inexact_target_result_count(),
fallback_target_result_count =
fallback_telemetry.fallback_target_result_count(),
fallback_reason_hit_count = fallback_telemetry.fallback_reason_hit_count(),
fallback_reason_target_counts = ?fallback_telemetry.fallback_reason_target_counts(),
source_result_affected_root_count =
fallback_telemetry.source_result_affected_root_count(),
retained_source_unavailable_target_count =
diagnostic_target_result_counts.retained_source_unavailable_target_count,
missing_fallback_roots_target_count =
@@ -693,6 +708,10 @@ impl StyleInvalidationCleanupTrace {
self.retained_target_results.diagnostic_target_results()
}
fn fallback_telemetry(&self) -> StyleInvalidationFallbackTelemetry {
self.retained_target_results.fallback_telemetry()
}
fn record_diagnostic_target_result_counts_into(
&self,
sink: &mut impl StyleInvalidationDiagnosticTargetResultSummaryTraceCountsSink,
@@ -1,4 +1,4 @@
use indexmap::IndexSet;
use indexmap::{IndexMap, IndexSet};
use moli_selector::{
MoliInvalidationResult, MoliInvalidationSourceResultsSink, StyloSourceAffectedRootsCleanup,
StyloSourceAffectedRootsCleanupSink,
@@ -102,6 +102,20 @@ pub(super) struct StyleInvalidationDiagnosticTargetResult {
affected_root_count: usize,
}
/// Aggregate fallback telemetry for one invalidation drain.
///
/// This is derived from retained diagnostic target results only when style
/// invalidation tracing is enabled (and in tests). Normal rendering does not
/// retain the target results or maintain counters alongside mutations.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub(super) struct StyleInvalidationFallbackTelemetry {
exact_target_result_count: usize,
inexact_target_result_count: usize,
fallback_target_result_count: usize,
source_result_affected_root_count: usize,
fallback_reason_target_counts: IndexMap<StyloSourceInvalidationFallbackReason, usize>,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub(super) struct StyleInvalidationDiagnosticTargetResultSummary {
diagnostic_target_result_count: usize,
@@ -302,6 +316,70 @@ impl StyleInvalidationDiagnosticTargetResult {
}
}
impl StyleInvalidationFallbackTelemetry {
fn from_target_results(results: &[StyleInvalidationDiagnosticTargetResult]) -> Self {
let mut telemetry = Self::default();
for result in results {
if result.exact {
telemetry.exact_target_result_count += 1;
} else {
telemetry.inexact_target_result_count += 1;
}
if !result.fallback_reasons.is_empty() {
telemetry.fallback_target_result_count += 1;
}
telemetry.source_result_affected_root_count += result.affected_root_count;
// A source result stores reasons in an IndexSet, so each reason is
// counted at most once per source target. Selector duplication
// therefore cannot inflate the fallback hit rate.
for reason in &result.fallback_reasons {
*telemetry
.fallback_reason_target_counts
.entry(*reason)
.or_default() += 1;
}
}
telemetry
}
pub(super) fn exact_target_result_count(&self) -> usize {
self.exact_target_result_count
}
pub(super) fn inexact_target_result_count(&self) -> usize {
self.inexact_target_result_count
}
pub(super) fn fallback_target_result_count(&self) -> usize {
self.fallback_target_result_count
}
pub(super) fn source_result_affected_root_count(&self) -> usize {
self.source_result_affected_root_count
}
pub(super) fn fallback_reason_hit_count(&self) -> usize {
self.fallback_reason_target_counts.values().sum()
}
pub(super) fn fallback_reason_target_counts(
&self,
) -> &IndexMap<StyloSourceInvalidationFallbackReason, usize> {
&self.fallback_reason_target_counts
}
#[cfg(test)]
pub(super) fn fallback_reason_target_count(
&self,
reason: StyloSourceInvalidationFallbackReason,
) -> usize {
self.fallback_reason_target_counts
.get(&reason)
.copied()
.unwrap_or_default()
}
}
impl StyleDiagnosticSourceTargetAvailability {
fn with_fallback_roots(fallback_roots: Option<StyleSourceFallbackRootAvailability>) -> Self {
Self {
@@ -381,6 +459,10 @@ impl StyleInvalidationRetainedTargetResultsTrace {
&self.diagnostic_target_results
}
pub(super) fn fallback_telemetry(&self) -> StyleInvalidationFallbackTelemetry {
StyleInvalidationFallbackTelemetry::from_target_results(&self.diagnostic_target_results)
}
pub(super) fn record_diagnostic_target_result_counts_into(
&self,
sink: &mut impl StyleInvalidationDiagnosticTargetResultSummaryTraceCountsSink,
@@ -700,6 +700,17 @@ fn finalized_cleanup_preserves_mixed_subtree_sources() {
StyleInvalidationCleanupClass::UnknownOrFallback
);
assert_eq!(application.affected_root_count(), 3);
let telemetry = application.fallback_telemetry();
assert_eq!(telemetry.exact_target_result_count(), 2);
assert_eq!(telemetry.inexact_target_result_count(), 1);
assert_eq!(telemetry.fallback_target_result_count(), 1);
assert_eq!(telemetry.source_result_affected_root_count(), 2);
assert_eq!(
telemetry.fallback_reason_target_count(
StyloSourceInvalidationFallbackReason::UnsupportedDependency,
),
1
);
assert!(matches!(
application.cleanup_target(),
StyleInvalidationCleanupTarget::MixedSubtreeRoots(groups)
@@ -1412,6 +1423,27 @@ fn fallback_only_source_emits_each_target_result_fallback_reason() {
.fallback_reasons()
.contains(&StyloSourceInvalidationFallbackReason::UnsupportedStateDependency)
);
let telemetry = application.fallback_telemetry();
assert_eq!(telemetry.exact_target_result_count(), 0);
assert_eq!(telemetry.inexact_target_result_count(), 1);
assert_eq!(telemetry.fallback_target_result_count(), 1);
assert_eq!(telemetry.source_result_affected_root_count(), 1);
assert_eq!(
telemetry.fallback_reason_target_count(
StyloSourceInvalidationFallbackReason::UnsupportedDependency,
),
1
);
assert_eq!(
telemetry.fallback_reason_target_count(
StyloSourceInvalidationFallbackReason::UnsupportedStateDependency,
),
1
);
assert_eq!(
telemetry.fallback_reason_target_count(StyloSourceInvalidationFallbackReason::FullSelector),
0
);
}
#[test]
fn structural_boundary_fallback_target_queries_dedupe_duplicate_targets() {