Skip to content

Commit b2a7ee0

Browse files
committed
ui: bigtrace select the traces of an experiment
The backend can now fan a query out over one arm of an experiment. This puts that in the user's hands and carries it everywhere the rest of the trace selection already goes. The trace grid's header gains an Experiment Filter. Searching asks /v1/experiments (one capped page, debounced, never for an empty box — matching the whole catalog is a round-trip nobody can use), and each result offers both arms: id first, then the name, which routinely runs past a hundred characters and so is clamped everywhere with the whole of it in the tooltip. An arm the caller can't query is prefixed "(Not available in Telemetry datasets)" and stays selectable — the backend denies at execution, not the UI. Picking one replaces the button with the arm toggle, the chosen arm, and a way to clear it; switching arm or clearing refetches the grid, so what it lists stays what a run would process. From there it travels as any other part of the selection: shipped as the top-level experiment_filter on /execute_* and /trace_metadata, persisted with the tab, copied by Clone, restored from the submit-time snapshot when a query is reopened from History, captured by and applied from a preset (which a preset states as ids and arm alone), compared when the launcher works out which preset a tab is running, held provisional by Trace Selection's Cancel/Apply, and summarised in the chip strip. Ids are numbers on the wire in both directions and stay numbers throughout, so there is no conversion to keep in step; display names never travel — they are resolved from /v1/experiment_metadata once per id, and only onto the filter that asked for them.
1 parent e705a22 commit b2a7ee0

20 files changed

Lines changed: 1208 additions & 14 deletions

ui/src/assets/bigtrace.scss

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,128 @@ pre.pf-bt-history-item-query--standalone {
10091009
}
10101010
}
10111011

1012+
// A chosen experiment's name can be a sentence; the chip states which arm
1013+
// and as much of it as fits, with the whole of both arms in the tooltip.
1014+
.pf-bt-settings-bar .pf-chip__label {
1015+
overflow: hidden;
1016+
text-overflow: ellipsis;
1017+
white-space: nowrap;
1018+
max-width: 32rem;
1019+
}
1020+
1021+
// Trace-grid header row: column picker left, experiment filter hard right.
1022+
.pf-bt-trace-columns {
1023+
display: flex;
1024+
align-items: center;
1025+
gap: 8px;
1026+
}
1027+
1028+
// Chosen experiment: arm toggle, the active arm, and the way to clear it.
1029+
// The name is free to clamp; the id stays whole.
1030+
.pf-bt-experiment-filter {
1031+
display: flex;
1032+
align-items: center;
1033+
gap: 8px;
1034+
min-width: 0;
1035+
margin-left: auto;
1036+
1037+
&__open {
1038+
margin-left: auto;
1039+
}
1040+
1041+
&__arm {
1042+
overflow: hidden;
1043+
text-overflow: ellipsis;
1044+
white-space: nowrap;
1045+
max-width: 320px;
1046+
}
1047+
}
1048+
1049+
// The popup box itself, so the one thing that can hang off the screen is
1050+
// bounded on the element that hangs. Everything from here down is sized by
1051+
// its content, so the viewport is the only fixed thing to measure against:
1052+
// its width less the 8px per side Popup keeps clear of the edges. Border and
1053+
// padding are inside the number, the box being border-box.
1054+
// Two classes deep to outrank the widget's own `--fit-content`, which unsets
1055+
// max-width to let content decide the size — content still decides, it just
1056+
// can't decide to leave the screen.
1057+
.pf-popup.pf-bt-experiment-popup {
1058+
max-width: calc(100vw - 16px);
1059+
}
1060+
1061+
// Experiment search popup. Own block, like the connection panel — the shared
1062+
// popup content class stays untouched.
1063+
.pf-bt-experiment-picker {
1064+
display: flex;
1065+
flex-direction: column;
1066+
gap: 8px;
1067+
// Follows the window, so a wide screen gets a wide popup; bounded in rem
1068+
// so it also respects the reader's font size, stays usable when narrow,
1069+
// and never runs a name past a comfortable line length.
1070+
width: clamp(30rem, 40vw, 60rem);
1071+
// The floor would otherwise win over a very narrow window; yielding to the
1072+
// box around it is what makes that cap effective, since a width this
1073+
// explicit would happily overflow its container.
1074+
max-width: 100%;
1075+
1076+
&__body {
1077+
display: flex;
1078+
flex-direction: column;
1079+
gap: 2px;
1080+
max-height: 60vh;
1081+
overflow-y: auto;
1082+
}
1083+
1084+
&__note {
1085+
color: var(--pf-color-text-muted);
1086+
padding: 4px 0;
1087+
}
1088+
1089+
// One experiment: both arms, picked as a unit.
1090+
&__row {
1091+
display: flex;
1092+
flex-direction: column;
1093+
gap: 2px;
1094+
padding: 6px 8px;
1095+
border-radius: 4px;
1096+
cursor: pointer;
1097+
1098+
&:hover {
1099+
background: var(--pf-color-background-secondary);
1100+
}
1101+
}
1102+
1103+
&__arm {
1104+
display: flex;
1105+
align-items: baseline;
1106+
gap: 8px;
1107+
min-width: 0;
1108+
}
1109+
1110+
&__label {
1111+
color: var(--pf-color-text-muted);
1112+
font-size: smaller;
1113+
flex: 0 0 72px;
1114+
}
1115+
1116+
&__id {
1117+
font-variant-numeric: tabular-nums;
1118+
flex: 0 0 auto;
1119+
}
1120+
1121+
// Choosing is done by the name, so it wraps rather than truncates; the id
1122+
// and label keep their column while it does.
1123+
&__name {
1124+
flex: 1;
1125+
min-width: 0;
1126+
overflow-wrap: anywhere;
1127+
1128+
&--denied {
1129+
color: var(--pf-color-text-muted);
1130+
}
1131+
}
1132+
}
1133+
10121134
// Query-settings modal (gear in the run toolbar): the settings form without
10131135
// the page chrome — the modal provides the frame and the scrolling.
10141136
.pf-bt-query-settings-modal {

ui/src/bigtrace/pages/bigtrace_settings_bar.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ import type {Filter} from '../../components/widgets/datagrid/model';
2020
import {bigTraceSettingsStorage} from '../settings/bigtrace_settings_storage';
2121
import type {Setting as BigTraceSetting} from '../settings/settings_types';
2222
import type {SettingsBindings} from '../settings/tab_bound_setting';
23+
import {
24+
describeExperimentFilter,
25+
ensureExperimentNames,
26+
summarizeExperimentFilter,
27+
} from './experiment_filter_control';
2328
import {
2429
isTraceSelectionSetting,
2530
openSettings,
@@ -70,6 +75,7 @@ export class BigtraceSettingsBar implements m.ClassComponent<BigtraceSettingsBar
7075
? renderUuidChip(bindings)
7176
: [
7277
renderSettingChips(bindings),
78+
renderExperimentChip(bindings),
7379
renderFilterChips(tab, tabsState, bindings),
7480
],
7581
),
@@ -140,6 +146,23 @@ function renderSettingChip(
140146
});
141147
}
142148

149+
// The experiment/control arm the query runs over. Named once the catalog
150+
// answers; until then the id says which one it is.
151+
function renderExperimentChip(bindings: SettingsBindings): m.Children {
152+
const filter = bindings.getExperimentFilter();
153+
if (filter === undefined) return null;
154+
ensureExperimentNames(bindings);
155+
return m(Chip, {
156+
label: `${filter.isTreatment ? 'Experiment' : 'Control'}: ${summarizeExperimentFilter(filter)}`,
157+
title: describeExperimentFilter(filter),
158+
removable: true,
159+
onRemove: () => {
160+
bindings.setExperimentFilter(undefined);
161+
m.redraw();
162+
},
163+
});
164+
}
165+
143166
function renderFilterChips(
144167
tab: BigTraceEditorTab,
145168
tabsState: QueryTabsState,

ui/src/bigtrace/pages/editor_tab_view.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ function buildTabBindings(
166166
applyModeDefaults(tab, materialize);
167167
tabsState.markDirty();
168168
},
169+
getExperimentFilter: () => tab.experimentFilter,
170+
setExperimentFilter: (filter) => {
171+
tab.experimentFilter = filter;
172+
tabsState.markDirty();
173+
},
169174
getTraceLimit: () => tab.traceLimit,
170175
setTraceLimit: (limit) => {
171176
if (limit > 0) {

0 commit comments

Comments
 (0)