mirror of
https://github.com/lexmount/moli.git
synced 2026-10-03 00:00:44 +00:00
chore(style): expose invalidation fallback telemetry
This commit is contained in:
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user