Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2ee33f0
feat(trace): Add pinnable attribute column to trace waterfall
nsdeschenes Jul 3, 2026
c76a7c2
perf(trace): Skip requesting pinned attributes already in the trace r…
nsdeschenes Jul 3, 2026
793dffa
fix(trace): Key native pinned attributes by their drawer name
nsdeschenes Jul 3, 2026
24d4cff
fix(trace): Close gap between pinned column and the divider
nsdeschenes Jul 3, 2026
e8bd5d1
fix(trace): Add right border to pinned attribute column header
nsdeschenes Jul 6, 2026
4444b69
fix(trace): Draw pinned column left border full height
nsdeschenes Jul 6, 2026
2a808da
feat(trace): Horizontally scroll the pinned attribute column as one unit
nsdeschenes Jul 6, 2026
746c2ef
fix(trace): Make pinned column text uniform and bold the header name
nsdeschenes Jul 6, 2026
ba63343
fix(trace): Account for pinned column width in tree horizontal scroll
nsdeschenes Jul 6, 2026
652daa4
feat(trace): Show a pin indicator on the pinned attribute in the drawer
nsdeschenes Jul 6, 2026
29167af
feat(trace): Move pinned attribute indicator next to the attribute name
nsdeschenes Jul 6, 2026
76b2c10
fix(trace): Vertically center the pinned attribute pin icon
nsdeschenes Jul 6, 2026
8a02883
fix(trace): Align pinned column header with cells across scrollbar width
nsdeschenes Jul 6, 2026
8efb80f
fix(trace): Render pinned column cell on collapsed rows
nsdeschenes Jul 6, 2026
8044d44
fix(trace): Strip pinned attribute param from header breadcrumb links
nsdeschenes Jul 6, 2026
bcfe03c
chore(trace): Drop unused exports on pinned attribute helpers
nsdeschenes Jul 6, 2026
c16b708
fix(trace): Remove pinned column wheel listener on unmount
nsdeschenes Jul 6, 2026
ee0907b
fix(trace): Match pinned column background to row highlight states
nsdeschenes Jul 6, 2026
f9083ad
fix(trace): Continue row highlight border across pinned column
nsdeschenes Jul 6, 2026
dc3ba16
fix(trace): Hide pinned attribute header while loading
nsdeschenes Jul 6, 2026
847c596
fix(trace): Rename pin column action to pin attribute
nsdeschenes Jul 6, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ interface AttributesTreeProps<
columnCount?: number;
config?: AttributesTreeRowConfig;
getAdjustedAttributeKey?: (attribute: TraceItemResponseAttribute) => string;
// If provided, renders the returned node immediately after the attribute key
// (e.g. an icon indicating the attribute's state). Return null for no suffix.
getAttributeKeySuffix?: (content: AttributesTreeContent) => React.ReactNode;
getCustomActions?: (content: AttributesTreeContent) => MenuItemProps[];
}

Expand All @@ -102,6 +105,7 @@ interface AttributesTreeRowProps<
attributeKey: string;
content: AttributesTreeContent;
config?: AttributesTreeRowConfig;
getAttributeKeySuffix?: (content: AttributesTreeContent) => React.ReactNode;
getCustomActions?: (content: AttributesTreeContent) => MenuItemProps[];
isLast?: boolean;
spacerCount?: number;
Expand Down Expand Up @@ -172,6 +176,7 @@ function getAttributesTreeRows<RendererExtra extends RenderFunctionBaggage>({
isLast = false,
config = {},
getCustomActions,
getAttributeKeySuffix,
}: AttributesTreeRowProps<RendererExtra> &
AttributesFieldRender<RendererExtra> & {
uniqueKey: string;
Expand All @@ -189,6 +194,7 @@ function getAttributesTreeRows<RendererExtra extends RenderFunctionBaggage>({
config,
rendererExtra,
getCustomActions,
getAttributeKeySuffix,
});
return rows.concat(branchRows);
},
Expand All @@ -206,6 +212,7 @@ function getAttributesTreeRows<RendererExtra extends RenderFunctionBaggage>({
isLast={isLast}
config={config}
getCustomActions={getCustomActions}
getAttributeKeySuffix={getAttributeKeySuffix}
/>,
...subtreeRows,
];
Expand All @@ -223,6 +230,7 @@ function AttributesTreeColumns<RendererExtra extends RenderFunctionBaggage>({
config = {},
getCustomActions,
getAdjustedAttributeKey,
getAttributeKeySuffix,
}: AttributesTreeColumnsProps<RendererExtra>) {
const assembledColumns = useMemo(() => {
if (!attributes) {
Expand Down Expand Up @@ -253,6 +261,7 @@ function AttributesTreeColumns<RendererExtra extends RenderFunctionBaggage>({
rendererExtra: renderExtra,
config,
getCustomActions,
getAttributeKeySuffix,
})
);

Expand Down Expand Up @@ -299,6 +308,7 @@ function AttributesTreeColumns<RendererExtra extends RenderFunctionBaggage>({
config,
getCustomActions,
getAdjustedAttributeKey,
getAttributeKeySuffix,
]);

return <Fragment>{assembledColumns}</Fragment>;
Expand Down Expand Up @@ -328,12 +338,14 @@ function AttributesTreeRow<RendererExtra extends RenderFunctionBaggage>({
isLast = false,
config = {},
getCustomActions,
getAttributeKeySuffix,
...props
}: AttributesTreeRowProps<RendererExtra>) {
const theme = useTheme();
const originalAttribute = content.originalAttribute;
const hasErrors = false; // No error handling in this simplified version
const hasStem = !isLast && isEmptyObject(content.subtree);
const keySuffix = getAttributeKeySuffix?.(content);

if (!originalAttribute) {
return (
Expand Down Expand Up @@ -372,6 +384,7 @@ function AttributesTreeRow<RendererExtra extends RenderFunctionBaggage>({
data-test-id={`tree-key-${content.originalAttribute?.original_attribute_key}`}
>
{attributeKey}
{keySuffix}
</TreeKey>
</TreeKeyTrunk>
<TreeValueTrunk>
Expand Down
21 changes: 14 additions & 7 deletions static/app/views/performance/newTraceDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ import {
import {TraceStateProvider} from './traceState/traceStateProvider';
import {ErrorsOnlyWarnings} from './traceTypeWarnings/errorsOnlyWarnings';
import {TraceMetaDataHeader} from './traceHeader';
import {
getTraceAdditionalAttributes,
useTracePinnedAttribute,
} from './tracePinnedAttribute';
import {useInitialTraceMetricData} from './useInitialTraceMetricData';
import {useTraceEventView} from './useTraceEventView';
import {useTraceQueryParams} from './useTraceQueryParams';
Expand Down Expand Up @@ -137,16 +141,19 @@ function TraceViewImplInner({traceSlug}: {traceSlug: string}) {
metaMetricsCount === undefined ? metricsData : {count: metaMetricsCount};
const hideTraceWaterfallIfEmpty = (logsData?.length ?? 0) > 0;

const {pinnedAttribute} = useTracePinnedAttribute();
// Request the pinned attribute only when the trace endpoint does not already
// return it. Sorted for a stable react-query key so toggling unrelated state
// never triggers a refetch.
const additionalAttributes = useMemo(
() => getTraceAdditionalAttributes(pinnedAttribute),
[pinnedAttribute]
);

const trace = useTrace({
traceSlug,
timestamp: queryParams.timestamp,
additionalAttributes: [
'thread.id',
'tags[performance.timeOrigin,number]',
'gen_ai.operation.type',
'http.response.status_code',
'span.status',
],
additionalAttributes,
});
const tree = useTraceTree({traceSlug, trace, replay: null});

Expand Down
Loading
Loading