Skip to content

Commit cf3ecdd

Browse files
committed
perf(webapp): stop shipping raw span events in the run trace loader payload
The trace tree only renders the derived timelineEvents, so the raw span events (with full properties) were serialized into the loader response as dead weight on event-heavy traces. Raw events now stay server-side, and timeline events no longer carry the raw event properties (the field was never in the TimelineSpanEvent type and nothing rendered it).
1 parent 7b4443a commit cf3ecdd

6 files changed

Lines changed: 29 additions & 7 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: improvement
4+
---
5+
6+
Shrinks the run trace page loader payload by keeping raw span events server-side and makes large trace trees render more efficiently. Also adds an optional `TRACE_VIEW_EMERGENCY_SPAN_CAP` env var that clamps trace summary span limits on both event store paths.

apps/webapp/app/presenters/v3/RunPresenter.server.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,16 @@ export class RunPresenter {
255255
linkedRunIdBySpanId[n.id] = n.runId;
256256
}
257257

258+
// Raw span events are only needed server-side (to derive timelineEvents);
259+
// keep them out of the serialized loader payload.
260+
const { events: spanEvents, ...data } = n.data;
261+
258262
return {
259263
...n,
260264
data: {
261-
...n.data,
265+
...data,
262266
timelineEvents: createTimelineSpanEventsFromSpanEvents(
263-
n.data.events,
267+
spanEvents,
264268
user?.admin ?? false,
265269
treeRootStartTimeMs
266270
),

apps/webapp/app/utils/timelineSpanEvents.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ export function createTimelineSpanEventsFromSpanEvents(
117117
offset,
118118
timestamp,
119119
duration,
120-
properties: spanEvent.properties,
121120
helpText: getHelpTextForEvent(name),
122121
markerVariant,
123122
lineVariant: "light" as const,

apps/webapp/app/v3/mollifier/syntheticTrace.server.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,14 @@ export function buildSyntheticTraceForBufferedRun(run: SyntheticRun) {
4444
const offset = millisecondsToNanoseconds(
4545
n.data.startTime.getTime() - treeRootStartTimeMs
4646
);
47+
// Mirror RunPresenter: raw span events stay server-side, only
48+
// timelineEvents ship to the client.
49+
const { events: spanEvents, ...data } = n.data;
4750
return {
4851
...n,
4952
data: {
50-
...n.data,
51-
timelineEvents: createTimelineSpanEventsFromSpanEvents(n.data.events, false, treeRootStartTimeMs),
53+
...data,
54+
timelineEvents: createTimelineSpanEventsFromSpanEvents(spanEvents, false, treeRootStartTimeMs),
5255
duration: n.data.isPartial ? null : n.data.duration,
5356
offset,
5457
isRoot: n.id === spanId,

apps/webapp/test/mollifierSyntheticTrace.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,10 @@ describe("buildSyntheticTraceForBufferedRun", () => {
141141
expect(trace.queuedDuration).toBeUndefined();
142142
});
143143

144-
it("synthesises an empty events list (no timeline events from the buffer)", () => {
144+
it("synthesises an empty timeline and keeps raw span events out of the payload", () => {
145145
const trace = buildSyntheticTraceForBufferedRun(makeSyntheticRun());
146-
expect(trace.events[0].data.events).toEqual([]);
146+
// Raw span events stay server-side (mirrors RunPresenter's payload diet).
147+
expect(trace.events[0].data).not.toHaveProperty("events");
147148
expect(trace.events[0].data.timelineEvents).toEqual([]);
148149
});
149150
});

apps/webapp/test/timelineSpanEvents.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,15 @@ describe("createTimelineSpanEventsFromSpanEvents", () => {
181181
);
182182
});
183183

184+
test("should not attach raw span event properties to timeline events", () => {
185+
const result = createTimelineSpanEventsFromSpanEvents(sampleSpanEvents, true);
186+
187+
expect(result.length).toBeGreaterThan(0);
188+
for (const event of result) {
189+
expect(event).not.toHaveProperty("properties");
190+
}
191+
});
192+
184193
test("should preserve duration from span events", () => {
185194
const result = createTimelineSpanEventsFromSpanEvents(sampleSpanEvents, true);
186195

0 commit comments

Comments
 (0)