@@ -16,6 +16,7 @@ import {
1616 abortExperiment ,
1717 buildExperimentTrackQuery ,
1818 fetchSigNozMetrics ,
19+ fetchTracks ,
1920 retireExperiment ,
2021 type ExperimentDetail ,
2122 type ExperimentStratum ,
@@ -678,17 +679,28 @@ function avgGoodputByTrack(
678679 return out ;
679680}
680681
682+ // deadBadge marks a track that is disabled in the tracks table — most commonly
683+ // culled by a later promotion in the same market — so a flat/absent line reads
684+ // as "torn down", never as a mysteriously silent live track.
685+ const deadBadge : CSSProperties = {
686+ ...mono , fontSize : "0.5rem" , textTransform : "uppercase" , letterSpacing : "0.05em" ,
687+ padding : "0.05rem 0.35rem" , borderRadius : "3px" ,
688+ color : "#ff4060" , background : "#ff40601a" , border : "1px solid #ff406040" ,
689+ } ;
690+
681691// PromotionTrafficCard is one promotion's traffic chart: the promoted track's
682692// line vs the original (control), both scoped to the experiment's target market,
683693// over the shared window. A vertical marker at the promotion time (when it falls
684694// in-window) shows the hand-off. If the promotion is working the promoted line
685695// climbs while the control's share of this market falls.
686- function PromotionTrafficCard ( { point, seriesByTrackCountry, startMs, endMs, logScale } : {
696+ function PromotionTrafficCard ( { point, seriesByTrackCountry, startMs, endMs, logScale, promotedDisabled , originalDisabled } : {
687697 point : PromotedComparisonPoint ;
688698 seriesByTrackCountry : Map < string , Array < { ts : number ; value : number } > > ;
689699 startMs : number ;
690700 endMs : number ;
691701 logScale : boolean ;
702+ promotedDisabled : boolean ;
703+ originalDisabled : boolean ;
692704} ) {
693705 const rows = useMemo (
694706 ( ) => mergeTrafficRows (
@@ -704,8 +716,14 @@ function PromotionTrafficCard({ point, seriesByTrackCountry, startMs, endMs, log
704716
705717 return (
706718 < div style = { { border : "1px solid #ffffff0d" , borderRadius : "var(--radius-sm)" , padding : "0.6rem 0.7rem" } } >
707- < div style = { { ...mono , fontSize : "0.58rem" , color : "var(--text-muted)" , marginBottom : "0.15rem" } } >
708- #{ point . experimentId } · { point . targetCountry } · { point . protocolName || "—" } { point . providerName ? ` · ${ point . providerName } ` : "" }
719+ < div style = { { ...mono , fontSize : "0.58rem" , color : "var(--text-muted)" , marginBottom : "0.15rem" , display : "flex" , alignItems : "center" , gap : "0.4rem" } } >
720+ < span > #{ point . experimentId } · { point . targetCountry } · { point . protocolName || "—" } { point . providerName ? ` · ${ point . providerName } ` : "" } </ span >
721+ { promotedDisabled && (
722+ < span style = { deadBadge } title = "The promoted track is disabled — most commonly culled by a later promotion in this market — so it carries no traffic. The experiment row still reads 'promoted'." > culled</ span >
723+ ) }
724+ { originalDisabled && (
725+ < span style = { { ...deadBadge , color : "#8890a0" , background : "#8890a01a" , border : "1px solid #8890a040" } } title = "The original (control) track is disabled; only the promoted line carries meaning in this window." > original disabled</ span >
726+ ) }
709727 </ div >
710728 < div style = { { ...mono , fontSize : "0.62rem" , marginBottom : "0.35rem" , overflow : "hidden" , textOverflow : "ellipsis" , whiteSpace : "nowrap" } } >
711729 < span style = { { color : CHALLENGER_COLOR } } > { point . promotedTrackName } </ span >
@@ -755,6 +773,31 @@ function PromotedTraffic({ enabled }: { enabled: boolean }) {
755773 const [ provider , setProvider ] = useState ( "" ) ;
756774 const { data, isLoading, error } = usePromotedComparison ( enabled , hours ) ;
757775
776+ // Track liveness from the tracks endpoint (name → disabled), fetched once per
777+ // activation. A promoted track can be culled by a LATER promotion in the same
778+ // market while its experiment row stays 'promoted' forever, so without this
779+ // cross-reference the section charts dead tracks as mysteriously silent live
780+ // ones. A fetch failure leaves the map null: everything renders unbadged and
781+ // unhidden rather than mislabeled.
782+ const [ trackDisabled , setTrackDisabled ] = useState < Map < string , boolean > | null > ( null ) ;
783+ const [ showCulled , setShowCulled ] = useState ( false ) ;
784+ useEffect ( ( ) => {
785+ if ( ! enabled || ! isAuthenticated ) return ;
786+ let cancelled = false ;
787+ fetchTracks ( )
788+ . then ( ( d ) => {
789+ if ( cancelled ) return ;
790+ const m = new Map < string , boolean > ( ) ;
791+ for ( const t of d . tracks ?? [ ] ) m . set ( t . name , t . disabled ) ;
792+ setTrackDisabled ( m ) ;
793+ } )
794+ . catch ( ( ) => { if ( ! cancelled ) setTrackDisabled ( null ) ; } ) ;
795+ return ( ) => { cancelled = true ; } ;
796+ } , [ enabled , isAuthenticated ] ) ;
797+ // Only an explicit disabled=true counts: a track missing from the map (or a
798+ // failed fetch) is treated as live so an endpoint hiccup can't hide real cards.
799+ const isTrackDisabled = useCallback ( ( name : string ) => trackDisabled ?. get ( name ) === true , [ trackDisabled ] ) ;
800+
758801 const allPoints = useMemo ( ( ) => data ?. points ?? [ ] , [ data ] ) ;
759802
760803 // Filter option lists come from all promotions (before country/protocol/provider
@@ -769,7 +812,18 @@ function PromotedTraffic({ enabled }: { enabled: boolean }) {
769812 ( ! provider || p . providerName === provider ) ,
770813 [ country , protocol , provider ] ) ;
771814
772- const promotions = useMemo ( ( ) => allPoints . filter ( matchesFilters ) , [ allPoints , matchesFilters ] ) ;
815+ const filteredPoints = useMemo ( ( ) => allPoints . filter ( matchesFilters ) , [ allPoints , matchesFilters ] ) ;
816+ // Culled promotions (promoted track disabled) are hidden by default: they
817+ // carry no traffic, so their cards are pure noise unless explicitly asked
818+ // for. Hiding them BEFORE byMarket also skips their SigNoz traffic queries.
819+ const culledCount = useMemo (
820+ ( ) => filteredPoints . filter ( ( p ) => isTrackDisabled ( p . promotedTrackName ) ) . length ,
821+ [ filteredPoints , isTrackDisabled ] ,
822+ ) ;
823+ const promotions = useMemo (
824+ ( ) => ( showCulled ? filteredPoints : filteredPoints . filter ( ( p ) => ! isTrackDisabled ( p . promotedTrackName ) ) ) ,
825+ [ filteredPoints , showCulled , isTrackDisabled ] ,
826+ ) ;
773827
774828 const startMs = data ?. windowStart ? Date . parse ( data . windowStart ) : 0 ;
775829 const endMs = data ?. windowEnd ? Date . parse ( data . windowEnd ) : 0 ;
@@ -919,6 +973,17 @@ function PromotedTraffic({ enabled }: { enabled: boolean }) {
919973 { providers . map ( ( p ) => < option key = { p } value = { p } > { p } </ option > ) }
920974 </ select >
921975 </ div >
976+ { culledCount > 0 && (
977+ < button
978+ type = "button"
979+ onClick = { ( ) => setShowCulled ( ( v ) => ! v ) }
980+ style = { chip ( showCulled ) }
981+ aria-pressed = { showCulled }
982+ title = "Promotions whose promoted track has since been disabled (most commonly culled by a later promotion in the same market). They carry no traffic, so their cards are hidden by default."
983+ >
984+ { showCulled ? `hide culled (${ culledCount } )` : `show culled (${ culledCount } )` }
985+ </ button >
986+ ) }
922987 { hasFilters && (
923988 < button type = "button" onClick = { ( ) => { setCountry ( "" ) ; setProtocol ( "" ) ; setProvider ( "" ) ; } } style = { chip ( false ) } > Clear</ button >
924989 ) }
@@ -930,7 +995,8 @@ function PromotedTraffic({ enabled }: { enabled: boolean }) {
930995 < div style = { { ...mono , fontSize : "0.65rem" , color : "var(--text-muted)" } } > Loading promotions…</ div >
931996 ) : promotions . length === 0 ? (
932997 < div style = { { ...mono , fontSize : "0.65rem" , color : "var(--text-muted)" } } >
933- No promoted experiments{ hasFilters ? " for the selected filters" : "" } .
998+ No live promoted experiments{ hasFilters ? " for the selected filters" : "" } .
999+ { ! showCulled && culledCount > 0 ? ` ${ culledCount } culled ${ culledCount === 1 ? "promotion is" : "promotions are" } hidden — use the "show culled" toggle.` : "" }
9341000 </ div >
9351001 ) : (
9361002 < >
@@ -939,11 +1005,22 @@ function PromotedTraffic({ enabled }: { enabled: boolean }) {
9391005 ) }
9401006 < div style = { { display : "grid" , gridTemplateColumns : "repeat(auto-fit, minmax(26rem, 1fr))" , gap : "1rem" } } >
9411007 { promotions . map ( ( p ) => (
942- < PromotionTrafficCard key = { p . experimentId } point = { p } seriesByTrackCountry = { seriesByTrackCountry } startMs = { startMs } endMs = { endMs } logScale = { logScale } />
1008+ < PromotionTrafficCard
1009+ key = { p . experimentId }
1010+ point = { p }
1011+ seriesByTrackCountry = { seriesByTrackCountry }
1012+ startMs = { startMs }
1013+ endMs = { endMs }
1014+ logScale = { logScale }
1015+ promotedDisabled = { isTrackDisabled ( p . promotedTrackName ) }
1016+ originalDisabled = { isTrackDisabled ( p . originalTrackName ) }
1017+ />
9431018 ) ) }
9441019 </ div >
9451020 < div style = { { ...mono , fontSize : "0.55rem" , color : "var(--text-muted)" , marginTop : "0.5rem" } } >
946- { promotions . length } { promotions . length === 1 ? "promotion" : "promotions" } { trafficLoading ? ` · loading ${ metricNoun } …` : "" }
1021+ { promotions . length } { promotions . length === 1 ? "promotion" : "promotions" }
1022+ { ! showCulled && culledCount > 0 ? ` · ${ culledCount } culled hidden` : "" }
1023+ { trafficLoading ? ` · loading ${ metricNoun } …` : "" }
9471024 </ div >
9481025 </ >
9491026 ) }
@@ -956,9 +1033,10 @@ function PromotedTraffic({ enabled }: { enabled: boolean }) {
9561033export default function ExperimentsOverview ( { enabled } : { enabled : boolean } ) {
9571034 const [ view , setView ] = useState < "experiments" | "settings" > ( "experiments" ) ;
9581035 const [ selectedId , setSelectedId ] = useState < number | null > ( null ) ;
959- // Status filter driven by the pipeline strip. Retired experiments are hidden by
960- // default — they're the bulk of terminal history and rarely what you're after.
961- const [ hiddenStatuses , setHiddenStatuses ] = useState < Set < string > > ( ( ) => new Set ( [ "retired" ] ) ) ;
1036+ // Status filter driven by the pipeline strip. Retired and aborted experiments
1037+ // are hidden by default — together they're the bulk of terminal history and
1038+ // rarely what you're after; the strip's counts still show them.
1039+ const [ hiddenStatuses , setHiddenStatuses ] = useState < Set < string > > ( ( ) => new Set ( [ "retired" , "aborted" ] ) ) ;
9621040 const { experiments, pipeline, isLoading, hasLoaded, error, refresh } = useExperiments ( enabled ) ;
9631041 const settings = useExperimentSettings ( enabled ) ;
9641042
0 commit comments