Skip to content
Merged
Show file tree
Hide file tree
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
30 changes: 29 additions & 1 deletion telemetry/ui/src/components/routes/app/AppView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { AppStateView } from './StateMachine';
import { createContext, useEffect, useState } from 'react';
import { Status, useLocationParams } from '../../../utils';
import { GraphView } from './GraphView';
import type { HoveredAction } from './hoverHighlight';
import { useSearchParams } from 'react-router-dom';

export const REFRESH_INTERVAL = 500;
Expand Down Expand Up @@ -117,6 +118,9 @@ export type HighlightState = {
currentSelectedIndex?: SequenceLocation;
setCurrentHoverIndex: (index: SequenceLocation | undefined) => void;
currentHoverIndex?: SequenceLocation;
// Graph hover. Separate from currentHoverIndex because one action maps to many sequences.
setCurrentHoverAction: (action: HoveredAction | undefined) => void;
currentHoverAction?: HoveredAction;
currentEditingAnnotationContext?: AnnotationEditingContext;
setCurrentEditingAnnotationContext: (
annotationContext: AnnotationEditingContext | undefined
Expand Down Expand Up @@ -145,6 +149,8 @@ export const AppContext = createContext<HighlightState>({
currentSelectedIndex: undefined,
setCurrentHoverIndex: () => {},
currentHoverIndex: undefined,
setCurrentHoverAction: () => {},
currentHoverAction: undefined,
currentEditingAnnotationContext: undefined,
setCurrentEditingAnnotationContext: () => {},
createAnnotation: () => {
Expand Down Expand Up @@ -222,6 +228,20 @@ export const AppView = (props: {
const { projectId } = props;
// const [currentActionIndex, setCurrentActionIndex] = useState<number | undefined>(undefined);
const [hoverIndex, setHoverIndex] = useState<SequenceLocation | undefined>(undefined);
const [hoveredAction, setHoveredAction] = useState<HoveredAction | undefined>(undefined);
// The two hover sources are exclusive: a row hover is one sequence, a graph hover is an action.
const setCurrentHoverIndex = (index: SequenceLocation | undefined) => {
setHoverIndex(index);
if (index !== undefined) {
setHoveredAction(undefined);
}
};
const setCurrentHoverAction = (action: HoveredAction | undefined) => {
setHoveredAction(action);
if (action !== undefined) {
setHoverIndex(undefined);
}
};
const [autoRefresh, setAutoRefresh] = useState(props.defaultAutoRefresh || false);
const shouldQuery = projectId !== undefined && appID !== undefined;
const [minimizedTable, setMinimizedTable] = useState(false);
Expand Down Expand Up @@ -471,8 +491,10 @@ export const AppView = (props: {
setInspectViewOpen(loc !== undefined);
},
currentSelectedIndex: currentSequenceLocation,
setCurrentHoverIndex: setHoverIndex,
setCurrentHoverIndex: setCurrentHoverIndex,
currentHoverIndex: hoverIndex,
setCurrentHoverAction: setCurrentHoverAction,
currentHoverAction: hoveredAction,
currentEditingAnnotationContext: currentEditingAnnotationContext,
setCurrentEditingAnnotationContext: setCurrentEditingAnnotationContext,
// TODO -- handle span ID
Expand Down Expand Up @@ -544,6 +566,8 @@ export const AppView = (props: {
// highlightedActions={previousActions}
highlightedActions={undefined}
hoverAction={hoverAction}
appId={appID}
partitionKey={partitionKey}
/>
</div>
)}
Expand All @@ -558,6 +582,10 @@ export const AppView = (props: {
highlightedActions={undefined}
hoverAction={hoverAction}
currentActionLocation={currentSequenceLocation}
graphAppId={currentFocusStepsData !== undefined ? currentFocusAppID : appID}
graphPartitionKey={
currentFocusStepsData !== undefined ? currentFocusPartitionKey : partitionKey
}
displayGraphAsTab={displayGraphAsTabs} // in this case we want the graph as a tab
setMinimized={(min: boolean) => setInspectViewOpen(!min)}
isMinimized={!inspectViewOpen}
Expand Down
64 changes: 56 additions & 8 deletions telemetry/ui/src/components/routes/app/GraphView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import { ActionModel, ApplicationModel, Step } from '../../../api';

import dagre from 'dagre';
import React, { createContext, useLayoutEffect, useMemo, useRef, useState } from 'react';
import React, { createContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import ReactFlow, {
BaseEdge,
Controls,
Expand All @@ -35,7 +35,7 @@ import ReactFlow, {
} from 'reactflow';

import 'reactflow/dist/style.css';
import { backgroundColorsForIndex } from './AppView';
import { AppContext, backgroundColorsForIndex } from './AppView';
import { getActionStatus } from '../../../utils';
import { getSmartEdge } from '@tisoap/react-flow-smart-edge';

Expand Down Expand Up @@ -79,10 +79,14 @@ type EdgeType = {
};

const ActionNode = (props: { data: NodeData }) => {
const { setCurrentHoverAction } = React.useContext(AppContext);
const {
highlightedActions: previousActions,
hoverAction,
currentAction
currentAction,
hoveredActionName,
appId,
partitionKey
} = React.useContext(NodeStateProvider);
const highlightedActions = [currentAction, ...(previousActions || [])].reverse();
const name = props.data.label;
Expand All @@ -98,7 +102,8 @@ const ActionNode = (props: { data: NodeData }) => {
: shouldHighlight
? 'bg-gray-100'
: '';
const opacity = hoverAction?.step_start_log.action === name ? 'opacity-50' : '';
const opacity =
hoverAction?.step_start_log.action === name || hoveredActionName === name ? 'opacity-50' : '';
const additionalClasses = isCurrentAction
? 'border-dwlightblue/50 text-white border-2'
: shouldHighlight
Expand All @@ -109,6 +114,14 @@ const ActionNode = (props: { data: NodeData }) => {
<Handle type="target" position={Position.Top} />
<div
className={`${bgColor} ${opacity} ${additionalClasses} text-xl font-sans p-4 rounded-md border`}
onMouseEnter={() =>
setCurrentHoverAction({
actionName: name,
appId,
partitionKey
})
}
onMouseLeave={() => setCurrentHoverAction(undefined)}
>
{name}
</div>
Expand Down Expand Up @@ -305,27 +318,48 @@ const edgeTypes = {

type NodeState = {
highlightedActions: Step[] | undefined; // one for each highlighted action, in order from most recent to least recent
hoverAction: Step | undefined; // the action currently being hovered over
hoverAction: Step | undefined; // the action currently being hovered over in the telemetry list
currentAction: Step | undefined; // the action currently being viewed
hoveredActionName: string | undefined; // graph-node hover, already scoped to this application
appId: string;
partitionKey: string | null;
};
const NodeStateProvider = createContext<NodeState>({
highlightedActions: undefined,
hoverAction: undefined,
currentAction: undefined
currentAction: undefined,
hoveredActionName: undefined,
appId: '',
partitionKey: null
});

export const _Graph = (props: {
stateMachine: ApplicationModel;
currentAction: Step | undefined;
previousActions: Step[] | undefined;
hoverAction: Step | undefined;
appId: string;
partitionKey: string | null;
}) => {
const [showInputs, setShowInputs] = useState(true);

const [nodes, setNodes] = useState<NodeType[]>([]);
const [edges, setEdges] = useState<EdgeType[]>([]);

const { fitView } = useReactFlow();
const { currentHoverAction, setCurrentHoverAction } = React.useContext(AppContext);
const hoveredActionName =
currentHoverAction?.appId === props.appId &&
currentHoverAction.partitionKey === props.partitionKey
? currentHoverAction.actionName
: undefined;
const setCurrentHoverActionRef = useRef(setCurrentHoverAction);
setCurrentHoverActionRef.current = setCurrentHoverAction;
useEffect(() => {
return () => {
setCurrentHoverActionRef.current(undefined);
};
}, []);

// Keyed on the rendered structure rather than object identity: refetches and focus
// switches that don't change the graph must not trigger a full relayout.
Expand Down Expand Up @@ -357,9 +391,19 @@ export const _Graph = (props: {
() => ({
highlightedActions: props.previousActions,
hoverAction: props.hoverAction,
currentAction: props.currentAction
currentAction: props.currentAction,
hoveredActionName,
appId: props.appId,
partitionKey: props.partitionKey
}),
[props.previousActions, props.hoverAction, props.currentAction]
[
props.previousActions,
props.hoverAction,
props.currentAction,
hoveredActionName,
props.appId,
props.partitionKey
]
);

return (
Expand Down Expand Up @@ -392,6 +436,8 @@ export const GraphView = (props: {
currentAction: Step | undefined;
highlightedActions: Step[] | undefined;
hoverAction: Step | undefined;
appId: string;
partitionKey: string | null;
}) => {
const parentRef = useRef<HTMLDivElement | null>(null);
const childRef = useRef<HTMLDivElement | null>(null);
Expand All @@ -405,6 +451,8 @@ export const GraphView = (props: {
currentAction={props.currentAction}
previousActions={props.highlightedActions}
hoverAction={props.hoverAction}
appId={props.appId}
partitionKey={props.partitionKey}
/>
</ReactFlowProvider>
</div>
Expand Down
19 changes: 16 additions & 3 deletions telemetry/ui/src/components/routes/app/InsightsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '.
import React, { useContext, useState } from 'react';
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline';
import { AppContext } from './AppView';
import { isTelemetryRowHovered } from './hoverHighlight';
import { Chip } from '../../common/chip';
import { modelCosts } from '../../common/modelCost';

Expand Down Expand Up @@ -370,8 +371,13 @@ const InsightSubTable = (props: {
return acc;
}, new Map<number, Step>());

const { currentSelectedIndex, setCurrentSelectedIndex, currentHoverIndex, setCurrentHoverIndex } =
useContext(AppContext);
const {
currentSelectedIndex,
setCurrentSelectedIndex,
currentHoverIndex,
currentHoverAction,
setCurrentHoverIndex
} = useContext(AppContext);

return (
<>
Expand Down Expand Up @@ -408,7 +414,14 @@ const InsightSubTable = (props: {
const span = spansBySpanID.get(attribute.span_id || '');
const step = stepsByStepID.get(span?.begin_entry.action_sequence_id || 0);
const insightCasted = props.insight as InsightWithIndividualValues;
const isHovered = currentHoverIndex === span?.begin_entry.action_sequence_id;
const isHovered = isTelemetryRowHovered({
currentHoverIndex,
currentHoverAction,
sequenceId: span?.begin_entry.action_sequence_id,
actionName: span ? step?.step_start_log.action : undefined,
appId: props.appID,
partitionKey: props.partitionKey
});
const isCurrentSelected = currentSelectedIndex === span?.begin_entry.action_sequence_id;
return (
<TableRow
Expand Down
4 changes: 4 additions & 0 deletions telemetry/ui/src/components/routes/app/StateMachine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export const AppStateView = (props: {
highlightedActions: Step[] | undefined;
hoverAction: Step | undefined;
currentActionLocation: SequenceLocation | undefined;
graphAppId: string;
graphPartitionKey: string | null;
displayGraphAsTab: boolean;
setMinimized: (minimized: boolean) => void;
isMinimized: boolean;
Expand Down Expand Up @@ -108,6 +110,8 @@ export const AppStateView = (props: {
currentAction={currentStep}
highlightedActions={props.highlightedActions}
hoverAction={props.hoverAction}
appId={props.graphAppId}
partitionKey={props.graphPartitionKey}
/>
)}
{tab === 'insights' && (
Expand Down
49 changes: 34 additions & 15 deletions telemetry/ui/src/components/routes/app/StepList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
REFRESH_INTERVAL,
SequenceLocation
} from './AppView';
import { isTelemetryRowHovered } from './hoverHighlight';
import { Status, getActionStatus } from '../../../utils';
import { Chip } from '../../common/chip';
import { useContext, useEffect, useRef, useState } from 'react';
Expand Down Expand Up @@ -214,15 +215,20 @@ const ActionTableRow = (props: {
setCurrentEditingAnnotationContext,
setTab,
currentHoverIndex,
currentHoverAction,
setCurrentHoverIndex,
currentSelectedIndex,
setCurrentSelectedIndex
} = useContext(AppContext);

const isHovered =
currentHoverIndex?.sequenceId === sequenceID &&
currentHoverIndex?.appId === props.appID &&
currentHoverIndex?.partitionKey === props.partitionKey;
const isHovered = isTelemetryRowHovered({
currentHoverIndex,
currentHoverAction,
sequenceId: sequenceID,
actionName: props.step.step_start_log.action,
appId: props.appID,
partitionKey: props.partitionKey
});
// const spanCount = props.step.spans.length;
const childCount = props.links.length;
const shouldBeHighlighted =
Expand Down Expand Up @@ -478,13 +484,22 @@ const LinkSubTable = (props: {
latestTimeSeen: Date;
depth: number;
}) => {
const { currentHoverIndex, setCurrentHoverIndex, currentSelectedIndex, setCurrentSelectedIndex } =
useContext(AppContext);
const {
currentHoverIndex,
currentHoverAction,
setCurrentHoverIndex,
currentSelectedIndex,
setCurrentSelectedIndex
} = useContext(AppContext);
const sequenceID = props.step.step_start_log.sequence_id;
const isHovered =
currentHoverIndex?.appId === props.appID &&
currentHoverIndex?.partitionKey === props.partitionKey &&
currentHoverIndex?.sequenceId === sequenceID;
const isHovered = isTelemetryRowHovered({
currentHoverIndex,
currentHoverAction,
sequenceId: sequenceID,
actionName: props.step.step_start_log.action,
appId: props.appID,
partitionKey: props.partitionKey
});
const shouldBeHighlighted =
currentSelectedIndex !== undefined &&
currentSelectedIndex.appId === props.appID &&
Expand Down Expand Up @@ -781,7 +796,7 @@ const StepSubTable = (props: {
displayAnnotations: boolean;
depth: number;
}) => {
const { currentHoverIndex, currentSelectedIndex } = useContext(AppContext);
const { currentHoverIndex, currentHoverAction, currentSelectedIndex } = useContext(AppContext);
const attributesBySpanID = props.attributes.reduce((acc, attr) => {
const existing = acc.get(attr.span_id) || [];
existing.push(attr);
Expand All @@ -796,10 +811,14 @@ const StepSubTable = (props: {
// return acc;
// }, new Map<string | null, Array<InitializeStreamModel | FirstItemStreamModel | EndStreamModel>>());
const sequenceID = props.step.step_start_log.sequence_id;
const isHovered =
currentHoverIndex?.sequenceId === sequenceID &&
currentHoverIndex?.appId === props.appID &&
currentHoverIndex?.partitionKey === props.partitionKey;
const isHovered = isTelemetryRowHovered({
currentHoverIndex,
currentHoverAction,
sequenceId: sequenceID,
actionName: props.step.step_start_log.action,
appId: props.appID,
partitionKey: props.partitionKey
});
// const spanCount = props.step.spans.length;
const shouldBeHighlighted =
currentSelectedIndex !== undefined &&
Expand Down
Loading
Loading