Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 93 additions & 3 deletions web/components/cross-run-trace-analysis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,50 @@ function toggleInList<T>(items: T[], item: T): T[] {
: [...items, item];
}

#PAUL
function suppressLeadingTrailingZeroes(
values: Array<number | null>,
minConsecutiveZeroes = 2,
): Array<number | null> {
const result = [...values];

let leadingZeroCount = 0;
for (const value of result) {
if (value === 0) {
leadingZeroCount += 1;
} else {
break;
}
}

let trailingZeroCount = 0;
for (let index = result.length - 1; index >= 0; index -= 1) {
if (result[index] === 0) {
trailingZeroCount += 1;
} else {
break;
}
}

if (leadingZeroCount >= minConsecutiveZeroes) {
for (let index = 0; index < leadingZeroCount; index += 1) {
result[index] = null;
}
}

if (trailingZeroCount >= minConsecutiveZeroes) {
for (
let index = result.length - trailingZeroCount;
index < result.length;
index += 1
) {
result[index] = null;
}
}

return result;
}

export function CrossRunTraceAnalysis() {
const [runs, setRuns] = useState<V2Run[]>([]);
const [catalogLoading, setCatalogLoading] = useState(true);
Expand All @@ -264,6 +308,7 @@ export function CrossRunTraceAnalysis() {
const [selectedParameterKeys, setSelectedParameterKeys] = useState<string[] | null>(null);
const [selectedRunIds, setSelectedRunIds] = useState<number[] | null>(null);
const [axisMode, setAxisMode] = useState<AxisMode>("absolute");
const [suppressEdgeZeroes, setSuppressEdgeZeroes] = useState(false); #PAUL
const [traceResult, setTraceResult] = useState<TraceLoadResult>({
requestKey: "",
traces: [],
Expand Down Expand Up @@ -1003,6 +1048,44 @@ export function CrossRunTraceAnalysis() {
{positionedTraces.length.toLocaleString()} runs · {selectedParameters.length.toLocaleString()} parameters
</p>
</div>

<div className="flex w-full flex-col gap-3 sm:w-auto sm:flex-row sm:items-end">
<label className="flex items-center gap-2 rounded-md border border-[hsl(var(--border))] px-3 py-2 text-xs">
<input
type="checkbox"
checked={suppressEdgeZeroes}
onChange={(event) => setSuppressEdgeZeroes(event.target.checked)}
className="h-4 w-4 rounded border-[hsl(var(--border))]"
/>
<span>Suppress start/end zeroes</span>
</label>

<div className="w-full sm:w-auto">
<span className="mb-1.5 block text-xs font-medium">Time axis</span>
<div className="grid w-full grid-cols-3 overflow-hidden rounded-md border border-[hsl(var(--border))] sm:inline-flex sm:w-auto">
{AXIS_MODES.map((mode) => {
const Icon = mode.icon;
return (
<button
key={mode.id}
type="button"
aria-pressed={axisMode === mode.id}
onClick={() => setAxisMode(mode.id)}
className={cn(
"inline-flex min-w-0 items-center justify-center gap-1.5 px-1.5 py-2 text-xs font-medium transition-colors sm:px-3",
axisMode === mode.id
? "bg-[hsl(var(--primary))] text-[hsl(var(--primary-foreground))]"
: "bg-[hsl(var(--background))] text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))]",
)}
>
<Icon className="hidden h-3.5 w-3.5 sm:block" /> {mode.label}
</button>
);
})}
</div>
</div>
</div>

<div className="w-full sm:w-auto">
<span className="mb-1.5 block text-xs font-medium">Time axis</span>
<div className="grid w-full grid-cols-3 overflow-hidden rounded-md border border-[hsl(var(--border))] sm:inline-flex sm:w-auto">
Expand Down Expand Up @@ -1067,6 +1150,15 @@ export function CrossRunTraceAnalysis() {
);
const plotData = panelPositionedTraces.map((positioned) => {
const { trace, run, offsetSeconds, color } = positioned;

const rawYValues = trace.samples.map((sample) =>
finiteValue(sample.values[parameter.key]),
);

const yValues = suppressEdgeZeroes
? suppressLeadingTrailingZeroes(rawYValues, 2)
: rawYValues;

return {
x: trace.samples.map((sample) => {
if (axisMode === "absolute") return sample.timestamp;
Expand All @@ -1075,9 +1167,7 @@ export function CrossRunTraceAnalysis() {
}
return sample.relative_seconds;
}),
y: trace.samples.map((sample) =>
finiteValue(sample.values[parameter.key]),
),
y: yValues,
text: trace.samples.map((sample) => {
const compressedHours =
(offsetSeconds + sample.relative_seconds) / 3_600;
Expand Down