Skip to content

Commit

Permalink
a lot of progress
Browse files Browse the repository at this point in the history
  • Loading branch information
tssweeney committed Mar 4, 2025
1 parent d5241bb commit 37cc17e
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,24 +95,28 @@ export const TraceNavigatorInner: FC<TraceViewProps> = props => {
<h2 className="truncate text-sm font-semibold">Trace View</h2>
<div className="flex items-center gap-3">
{traceViews.map(view => {
const isDisabled = !!(view.maxTraces && traceCount > view.maxTraces);
const tooltipContent = isDisabled
const isDisabled = !!(
view.maxTraces && traceCount > view.maxTraces
);
const tooltipContent = isDisabled
? `${view.label} view is disabled (maximum ${view.maxTraces} traces)`
: view.label;

return (
<Tooltip key={view.id} content= {tooltipContent} trigger={<Button
variant={traceViewId === view.id ? 'primary' : 'ghost'}
onClick={() => setTraceViewId(view.id)}
icon={view.icon}
size="small"
className="!p-3"
disabled={isDisabled}>
<span className="sr-only">{view.label}</span>
</Button>}>


</Tooltip>
<Tooltip
key={view.id}
content={tooltipContent}
trigger={
<Button
variant={traceViewId === view.id ? 'primary' : 'ghost'}
onClick={() => setTraceViewId(view.id)}
icon={view.icon}
size="small"
className="!p-3"
disabled={isDisabled}>
<span className="sr-only">{view.label}</span>
</Button>
}></Tooltip>
);
})}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
getSortedPeerPathCallIds,
locateNodeForCallId,
} from '../../TraceViews/CodeView';
import {buildCodeMap} from '../../TraceViews/utils';
import {createScrubber} from './BaseScrubber';

export const TimelineScrubber = createScrubber({
Expand Down Expand Up @@ -34,6 +39,25 @@ export const PeerScrubber = createScrubber({
},
});

export const CodePathScrubber = createScrubber({
label: 'Code Path',
description:
'Navigate through all calls with the same code path as the selected call',
getNodes: ({traceTreeFlat, selectedCallId}) => {
if (!selectedCallId) {
return [];
}
const currentNode = traceTreeFlat[selectedCallId];
if (!currentNode) {
return [];
}

const codeMap = buildCodeMap(traceTreeFlat);
const codeNode = locateNodeForCallId(codeMap, selectedCallId);
return getSortedPeerPathCallIds(codeNode, traceTreeFlat);
},
});

export const SiblingScrubber = createScrubber({
label: 'Siblings',
description:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@ import React from 'react';

import {BaseScrubberProps} from './components/BaseScrubber';
import {
CodePathScrubber,
PeerScrubber,
SiblingScrubber,
StackScrubber,
TimelineScrubber,
} from './components/scrubbers';
import {Container} from './styles';

export type ScrubberOption = 'timeline' | 'peer' | 'sibling' | 'stack';
export type ScrubberOption =
| 'timeline'
| 'peer'
| 'sibling'
| 'stack'
| 'codePath';

const TraceScrubber: React.FC<
BaseScrubberProps & {
Expand All @@ -26,6 +32,7 @@ const TraceScrubber: React.FC<
<Container>
{showScrubber('timeline') && <TimelineScrubber {...props} />}
{showScrubber('peer') && <PeerScrubber {...props} />}
{showScrubber('codePath') && <CodePathScrubber {...props} />}
{showScrubber('sibling') && <SiblingScrubber {...props} />}
{showScrubber('stack') && <StackScrubber {...props} />}
</Container>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, {useEffect, useMemo, useState} from 'react';
import React, {useMemo} from 'react';
import styled from 'styled-components';

import {TreeView} from './TreeView';
import {TraceViewProps} from './types';
import {TraceTreeFlat, TraceViewProps} from './types';
import {buildCodeMap, CodeMapNode} from './utils';
import {formatDuration} from './utils';

Expand Down Expand Up @@ -96,18 +96,13 @@ const RecursionBlock = styled.div`

interface CodeMapNodeProps extends TraceViewProps {
node: CodeMapNode;
selectedOpName?: string;
onCallSelect: (callId: string) => void;
onOpSelect: (opName: string) => void;
level?: number;
}

const CodeMapNodeComponent: React.FC<CodeMapNodeProps> = ({
node,
selectedCallId,
selectedOpName,
onCallSelect,
onOpSelect,
traceTreeFlat,
stack,
level = 0,
Expand Down Expand Up @@ -159,7 +154,6 @@ const CodeMapNodeComponent: React.FC<CodeMapNodeProps> = ({

const handleClick = (e: React.MouseEvent) => {
e.preventDefault();
onOpSelect(node.opName);

// Select the first call in this operation if we have any calls
if (node.callIds.length > 0) {
Expand Down Expand Up @@ -208,9 +202,7 @@ const CodeMapNodeComponent: React.FC<CodeMapNodeProps> = ({
key={child.opName}
node={child}
selectedCallId={selectedCallId}
selectedOpName={selectedOpName}
onCallSelect={onCallSelect}
onOpSelect={onOpSelect}
traceTreeFlat={traceTreeFlat}
stack={stack}
level={level + 1}
Expand All @@ -225,62 +217,56 @@ const CodeMapNodeComponent: React.FC<CodeMapNodeProps> = ({
);
};

export const locateNodeForCallId = (
codeMap: CodeMapNode[],
selectedCallId: string
) => {
const findOpByCallId = (nodes: CodeMapNode[]): CodeMapNode | null => {
for (const node of nodes) {
if (node.callIds.includes(selectedCallId)) {
return node;
}
const found = findOpByCallId(node.children);
if (found) {
return found;
}
}
return null;
};
return findOpByCallId(codeMap);
};

export const getSortedPeerPathCallIds = (
selectedCodeNode: CodeMapNode | null,
traceTreeFlat: TraceTreeFlat
) => {
return (selectedCodeNode?.callIds ?? []).sort(
(a, b) =>
Date.parse(traceTreeFlat[a].call.started_at) -
Date.parse(traceTreeFlat[b].call.started_at)
);
};

export const CodeView: React.FC<TraceViewProps> = ({
traceTreeFlat,
selectedCallId,
onCallSelect,
stack,
}) => {
const codeMap = useMemo(() => buildCodeMap(traceTreeFlat), [traceTreeFlat]);
const [selectedOpName, setSelectedOpName] = useState<string>();

// Find the selected operation's calls and update when selectedCallId changes
const selectedOp = useMemo(() => {
const selectedCodeNode = useMemo(() => {
// First try to find the op containing the selected call
if (selectedCallId) {
const findOpByCallId = (nodes: CodeMapNode[]): CodeMapNode | null => {
for (const node of nodes) {
if (node.callIds.includes(selectedCallId)) {
return node;
}
const found = findOpByCallId(node.children);
if (found) {
return found;
}
}
return null;
};
const opWithCall = findOpByCallId(codeMap);
if (opWithCall) {
return opWithCall;
}
}

// Fall back to currently selected op
if (!selectedOpName) {
if (!selectedCallId) {
return null;
}
const findOp = (nodes: CodeMapNode[]): CodeMapNode | null => {
for (const node of nodes) {
if (node.opName === selectedOpName) {
return node;
}
const found = findOp(node.children);
if (found) {
return found;
}
}
return null;
};
return findOp(codeMap);
}, [codeMap, selectedCallId, selectedOpName]);
return locateNodeForCallId(codeMap, selectedCallId);
}, [codeMap, selectedCallId]);

// Update selectedOpName when we find the operation containing selectedCallId
useEffect(() => {
if (selectedOp && selectedOp.opName !== selectedOpName) {
setSelectedOpName(selectedOp.opName);
}
}, [selectedOp, selectedOpName]);
const selectedPeerPathCallIds = useMemo(() => {
return getSortedPeerPathCallIds(selectedCodeNode, traceTreeFlat);
}, [selectedCodeNode, traceTreeFlat]);

return (
<Container>
Expand All @@ -290,29 +276,27 @@ export const CodeView: React.FC<TraceViewProps> = ({
key={node.opName}
node={node}
selectedCallId={selectedCallId}
selectedOpName={selectedOpName}
onCallSelect={onCallSelect}
onOpSelect={setSelectedOpName}
traceTreeFlat={traceTreeFlat}
stack={stack}
/>
))}
</TreePanel>

<CallPanel>
{selectedOp ? (
{selectedCodeNode ? (
<>
<CallPanelHeader>
<span>Calls for {selectedOp.opName}</span>
<span>{selectedOp.callIds.length} calls</span>
<span>Calls for {selectedCodeNode.opName}</span>
<span>{selectedPeerPathCallIds.length} calls</span>
</CallPanelHeader>

<div className="flex-1 overflow-hidden">
<TreeView
traceTreeFlat={traceTreeFlat}
selectedCallId={selectedCallId}
onCallSelect={onCallSelect}
filterCallIds={selectedOp.callIds}
filterCallIds={selectedPeerPathCallIds}
stack={stack}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,29 @@ export const traceViews: TraceViewRegistry = [
label: 'Tree',
icon: 'layout-tabs',
component: TreeView,
allowedScrubbers: ['timeline', 'peer', 'sibling', 'stack'],
},
{
id: 'code',
label: 'Code',
icon: 'code-alt',
component: CodeView,
allowedScrubbers: ['peer'],
allowedScrubbers: ['codePath'],
},
{
id: 'flamegraph',
label: 'Flame',
icon: 'chart-horizontal-bars',
component: FlameGraphView,
maxTraces: 500,
allowedScrubbers: ['timeline', 'peer', 'sibling', 'stack'],
},
{
id: 'graph',
label: 'Graph',
icon: 'chart-scatterplot',
component: GraphView,
maxTraces: 50,
allowedScrubbers: ['timeline', 'peer', 'sibling', 'stack'],
},
];

0 comments on commit 37cc17e

Please sign in to comment.