diff --git a/telemetry/ui/src/components/routes/app/AppView.tsx b/telemetry/ui/src/components/routes/app/AppView.tsx index 692d6802e..246a5c663 100644 --- a/telemetry/ui/src/components/routes/app/AppView.tsx +++ b/telemetry/ui/src/components/routes/app/AppView.tsx @@ -117,6 +117,8 @@ export type HighlightState = { currentSelectedIndex?: SequenceLocation; setCurrentHoverIndex: (index: SequenceLocation | undefined) => void; currentHoverIndex?: SequenceLocation; + setCurrentHoverAction: (action: string | undefined) => void; + currentHoverAction?: string; currentEditingAnnotationContext?: AnnotationEditingContext; setCurrentEditingAnnotationContext: ( annotationContext: AnnotationEditingContext | undefined @@ -145,6 +147,8 @@ export const AppContext = createContext({ currentSelectedIndex: undefined, setCurrentHoverIndex: () => {}, currentHoverIndex: undefined, + setCurrentHoverAction: () => {}, + currentHoverAction: undefined, currentEditingAnnotationContext: undefined, setCurrentEditingAnnotationContext: () => {}, createAnnotation: () => { @@ -222,6 +226,7 @@ export const AppView = (props: { const { projectId } = props; // const [currentActionIndex, setCurrentActionIndex] = useState(undefined); const [hoverIndex, setHoverIndex] = useState(undefined); + const [hoverActionName, setHoverActionName] = useState(undefined); const [autoRefresh, setAutoRefresh] = useState(props.defaultAutoRefresh || false); const shouldQuery = projectId !== undefined && appID !== undefined; const [minimizedTable, setMinimizedTable] = useState(false); @@ -473,6 +478,8 @@ export const AppView = (props: { currentSelectedIndex: currentSequenceLocation, setCurrentHoverIndex: setHoverIndex, currentHoverIndex: hoverIndex, + setCurrentHoverAction: setHoverActionName, + currentHoverAction: hoverActionName, currentEditingAnnotationContext: currentEditingAnnotationContext, setCurrentEditingAnnotationContext: setCurrentEditingAnnotationContext, // TODO -- handle span ID @@ -503,15 +510,13 @@ export const AppView = (props: { return response; }, refreshAnnotationData: refetchAnnotationsData - }} - > + }}>
+ className={`w-full ${fullScreen ? 'h-full' : props.orientation === 'stacked_vertical' ? 'h-full' : 'h-1/2'}`}> { + const { setCurrentHoverAction, currentHoverAction } = React.useContext(AppContext); const { highlightedActions: previousActions, hoverAction, @@ -98,7 +99,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 || currentHoverAction === name ? 'opacity-50' : ''; const additionalClasses = isCurrentAction ? 'border-dwlightblue/50 text-white border-2' : shouldHighlight @@ -109,7 +111,8 @@ const ActionNode = (props: { data: NodeData }) => {
+ onMouseEnter={() => setCurrentHoverAction(name)} + onMouseLeave={() => setCurrentHoverAction(undefined)}> {name}
diff --git a/telemetry/ui/src/components/routes/app/InsightsView.tsx b/telemetry/ui/src/components/routes/app/InsightsView.tsx index 48da7ba27..3eef013bc 100644 --- a/telemetry/ui/src/components/routes/app/InsightsView.tsx +++ b/telemetry/ui/src/components/routes/app/InsightsView.tsx @@ -114,8 +114,7 @@ const Cost: React.FC = ({ currency = 'USD', totalCost, costDetails })
setShowDetails(false)} onMouseEnter={() => setShowDetails((prev) => !prev)} - className="cursor-pointer" - > + className="cursor-pointer"> {formattedCost}
{costDetails && showDetails && ( @@ -370,8 +369,13 @@ const InsightSubTable = (props: { return acc; }, new Map()); - const { currentSelectedIndex, setCurrentSelectedIndex, currentHoverIndex, setCurrentHoverIndex } = - useContext(AppContext); + const { + currentSelectedIndex, + setCurrentSelectedIndex, + currentHoverIndex, + currentHoverAction, + setCurrentHoverIndex + } = useContext(AppContext); return ( <> @@ -381,8 +385,7 @@ const InsightSubTable = (props: { if (canExpand) { setIsExpanded(!isExpanded); } - }} - > + }}>
@@ -408,7 +411,11 @@ 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 = + (currentHoverIndex?.sequenceId === span?.begin_entry.action_sequence_id && + currentHoverIndex?.appId === props.appID && + currentHoverIndex?.partitionKey === props.partitionKey) || + currentHoverAction === step?.step_start_log.action; const isCurrentSelected = currentSelectedIndex === span?.begin_entry.action_sequence_id; return ( + }}> {step && ( @@ -511,15 +517,13 @@ export const InsightsView = (props: { variety of attributes, including those populated by{' '} + href={'https://www.traceloop.com/docs/openllmetry/tracing/without-sdk'}> opentelemetry instrumentation. {' '} -- E.G. LLM call data. To instrument, and start collecting, see{' '} + href={'https://burr.apache.org/concepts/additional-visibility/#quickstart'}> see docs. diff --git a/telemetry/ui/src/components/routes/app/StepList.tsx b/telemetry/ui/src/components/routes/app/StepList.tsx index bd97d2c28..18a14d821 100644 --- a/telemetry/ui/src/components/routes/app/StepList.tsx +++ b/telemetry/ui/src/components/routes/app/StepList.tsx @@ -177,8 +177,7 @@ const CommonTableRow = (props: { }); } e.stopPropagation(); - }} - > + }}> {props.children} ); @@ -215,14 +214,16 @@ const ActionTableRow = (props: { setTab, currentHoverIndex, setCurrentHoverIndex, + currentHoverAction, currentSelectedIndex, setCurrentSelectedIndex } = useContext(AppContext); const isHovered = - currentHoverIndex?.sequenceId === sequenceID && - currentHoverIndex?.appId === props.appID && - currentHoverIndex?.partitionKey === props.partitionKey; + (currentHoverIndex?.sequenceId === sequenceID && + currentHoverIndex?.appId === props.appID && + currentHoverIndex?.partitionKey === props.partitionKey) || + currentHoverAction === props.step.step_start_log.action; // const spanCount = props.step.spans.length; const childCount = props.links.length; const shouldBeHighlighted = @@ -253,8 +254,7 @@ const ActionTableRow = (props: { setCurrentHoverIndex={setCurrentHoverIndex} setCurrentSelectedIndex={setCurrentSelectedIndex} appID={props.appID} - partitionKey={props.partitionKey} - > + partitionKey={props.partitionKey}>
@@ -272,8 +272,7 @@ const ActionTableRow = (props: { />
+ className={`${props.minimized ? 'w-32' : 'w-72 max-w-72'} flex flex-row justify-start gap-1 items-center`}> { - const { currentHoverIndex, setCurrentHoverIndex, currentSelectedIndex, setCurrentSelectedIndex } = - useContext(AppContext); + const { + currentHoverIndex, + setCurrentHoverIndex, + currentHoverAction, + 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; + (currentHoverIndex?.appId === props.appID && + currentHoverIndex?.partitionKey === props.partitionKey && + currentHoverIndex?.sequenceId === sequenceID) || + currentHoverAction === props.step.step_start_log.action; const shouldBeHighlighted = currentSelectedIndex !== undefined && currentSelectedIndex.appId === props.appID && @@ -523,8 +528,7 @@ const LinkSubTable = (props: { currentSelectedIndex={currentSelectedIndex} step={props.step} setCurrentHoverIndex={setCurrentHoverIndex} - setCurrentSelectedIndex={setCurrentSelectedIndex} - > + setCurrentSelectedIndex={setCurrentSelectedIndex}> @@ -532,8 +536,7 @@ const LinkSubTable = (props: { + className={`${normalText} w-48 min-w-48 max-w-48 truncate pl-9`}>
{ @@ -541,8 +544,7 @@ const LinkSubTable = (props: { `/project/${props.projectId}/${subApp.child.partition_key || 'null'}/${subApp.child.app_id}` ); e.stopPropagation(); - }} - > + }}> {subApp.child.app_id}
@@ -669,11 +671,9 @@ const StepSubTableRow = (props: { currentSelectedIndex={currentSelectedIndex} step={props.step} setCurrentHoverIndex={setCurrentHoverIndex} - setCurrentSelectedIndex={setCurrentSelectedIndex} - > + setCurrentSelectedIndex={setCurrentSelectedIndex}> + className={` ${lightText} w-10 min-w-10 ${props.displaySpanID ? '' : 'text-opacity-0'}`}> {spanIDUniqueToAction} @@ -682,14 +682,12 @@ const StepSubTableRow = (props: { <> + className={`${normalText} ${props.minimized ? 'w-32 min-w-32' : 'w-72 max-w-72'} flex flex-col`}>
{[...Array(depth).keys()].map((i) => ( + className={`${i === depth - 1 ? 'opacity-0' : 'opacity-0'} text-lg text-gray-600 w-4 flex-shrink-0`}> ))} { e.stopPropagation(); - }} - > + }}> { - 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); @@ -797,9 +794,10 @@ const StepSubTable = (props: { // }, new Map>()); const sequenceID = props.step.step_start_log.sequence_id; const isHovered = - currentHoverIndex?.sequenceId === sequenceID && - currentHoverIndex?.appId === props.appID && - currentHoverIndex?.partitionKey === props.partitionKey; + (currentHoverIndex?.sequenceId === sequenceID && + currentHoverIndex?.appId === props.appID && + currentHoverIndex?.partitionKey === props.partitionKey) || + currentHoverAction === props.step.step_start_log.action; // const spanCount = props.step.spans.length; const shouldBeHighlighted = currentSelectedIndex !== undefined && @@ -1142,13 +1140,11 @@ const WaterfallPiece: React.FC<{ onClick={(e) => { props.setSubActionExpanded?.(!props.isSubActionExpanded); e.stopPropagation(); - }} - > + }}>
setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - > + onMouseLeave={() => setIsHovered(false)}> @@ -1165,8 +1161,7 @@ const WaterfallPiece: React.FC<{ style={{ left: `calc(${leftPositionPercentage}% - 20px)`, width: `calc(${widthPercentage}% + 40px)` // 20px buffer on each side - }} - >
+ }}>
{
+ }}> {hoverItem}
} @@ -1838,8 +1832,7 @@ const ParentLink = (props: {
+ to={`/project/${props.projectId}/${props.parentPointer.partition_key}/${props.parentPointer.app_id}`}> {props.parentPointer.app_id} @