Skip to content

Commit

Permalink
feat: show trace details on hover (SigNoz#4241)
Browse files Browse the repository at this point in the history
* feat: show trace details on hover

* feat: handle sider anchor styles in dark and light mode
  • Loading branch information
YounixM authored Dec 18, 2023
1 parent ce8fdd5 commit 7526888
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 90 deletions.
16 changes: 16 additions & 0 deletions frontend/src/container/GantChart/GantChart.styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.span-container {
.spanDetails {
position: absolute;
height: 50px;
padding: 8px;
min-width: 150px;
background: lightcyan;
color: black;
bottom: 24px;
left: 0;

display: flex;
justify-content: center;
align-items: center;
}
}
96 changes: 96 additions & 0 deletions frontend/src/container/GantChart/Span/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import '../GantChart.styles.scss';

import { Popover, Typography } from 'antd';
import { convertTimeToRelevantUnit } from 'container/TraceDetail/utils';
import dayjs from 'dayjs';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { useEffect } from 'react';
import { toFixed } from 'utils/toFixed';

import { SpanBorder, SpanLine, SpanText, SpanWrapper } from './styles';

interface SpanLengthProps {
globalStart: number;
startTime: number;
name: string;
width: string;
leftOffset: string;
bgColor: string;
inMsCount: number;
}

function Span(props: SpanLengthProps): JSX.Element {
const {
width,
leftOffset,
bgColor,
inMsCount,
startTime,
name,
globalStart,
} = props;
const isDarkMode = useIsDarkMode();
const { time, timeUnitName } = convertTimeToRelevantUnit(inMsCount);

useEffect(() => {
document.documentElement.scrollTop = document.documentElement.clientHeight;
document.documentElement.scrollLeft = document.documentElement.clientWidth;
}, []);

const getContent = (): JSX.Element => {
const timeStamp = dayjs(startTime).format('h:mm:ss:SSS A');
const startTimeInMs = startTime - globalStart;
return (
<div>
<Typography.Text style={{ marginBottom: '8px' }}>
{' '}
Duration : {inMsCount}
</Typography.Text>
<br />
<Typography.Text style={{ marginBottom: '8px' }}>
Start Time: {startTimeInMs}ms [{timeStamp}]{' '}
</Typography.Text>
</div>
);
};

return (
<SpanWrapper className="span-container">
<SpanLine
className="spanLine"
isDarkMode={isDarkMode}
bgColor={bgColor}
leftOffset={leftOffset}
width={width}
/>

<div>
<Popover
style={{
left: `${leftOffset}%`,
}}
title={name}
content={getContent()}
trigger="hover"
placement="left"
autoAdjustOverflow
>
<SpanBorder
className="spanTrack"
isDarkMode={isDarkMode}
bgColor={bgColor}
leftOffset={leftOffset}
width={width}
/>
</Popover>
</div>

<SpanText isDarkMode={isDarkMode} leftOffset={leftOffset}>{`${toFixed(
time,
2,
)} ${timeUnitName}`}</SpanText>
</SpanWrapper>
);
}

export default Span;
40 changes: 0 additions & 40 deletions frontend/src/container/GantChart/SpanLength/index.tsx

This file was deleted.

7 changes: 5 additions & 2 deletions frontend/src/container/GantChart/Trace/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { ITraceTree } from 'types/api/trace/getTraceItem';

import { ITraceMetaData } from '..';
import SpanLength from '../SpanLength';
import Span from '../Span';
import SpanName from '../SpanName';
import { getMetaDataFromSpanTree, getTopLeftFromBody } from '../utils';
import {
Expand Down Expand Up @@ -169,7 +169,10 @@ function Trace(props: TraceProps): JSX.Element {
</StyledRow>
</StyledCol>
<Col flex="1">
<SpanLength
<Span
globalStart={globalStart}
startTime={startTime}
name={name}
leftOffset={nodeLeftOffset.toString()}
width={width.toString()}
bgColor={serviceColour}
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/container/GantChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ function GanttChart(props: GanttChartProps): JSX.Element {
onClick={handleCollapse}
title={isExpandAll ? 'Collapse All' : 'Expand All'}
>
{isExpandAll ? <MinusSquareOutlined /> : <PlusSquareOutlined />}
{isExpandAll ? (
<MinusSquareOutlined style={{ fontSize: '16px', color: '#08c' }} />
) : (
<PlusSquareOutlined style={{ fontSize: '16px', color: '#08c' }} />
)}
</CollapseButton>
<CardWrapper>
<Trace
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/container/GantChart/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const Wrapper = styled.ul`
border-left: 1px solid #434343;
padding-left: 1rem;
width: 100%;
margin: 0px;
}
ul li {
Expand Down Expand Up @@ -44,6 +45,4 @@ export const CardContainer = styled.li`
export const CollapseButton = styled.div`
position: absolute;
top: 0;
left: 0;
font-size: 1.2rem;
`;
46 changes: 21 additions & 25 deletions frontend/src/container/TraceDetail/SelectedSpanDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Button, Modal, Tabs, Tooltip, Typography } from 'antd';
import { Button, Modal, Tabs, Typography } from 'antd';
import Editor from 'components/Editor';
import { StyledSpace } from 'components/Styled';
import { QueryParams } from 'constants/query';
import ROUTES from 'constants/routes';
import { useIsDarkMode } from 'hooks/useDarkMode';
import createQueryParams from 'lib/createQueryParams';
import history from 'lib/history';
import { useMemo, useState } from 'react';
import { useState } from 'react';
import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import { AppState } from 'store/reducers';
Expand All @@ -15,13 +15,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';

import { getTraceToLogsQuery } from './config';
import Events from './Events';
import {
CardContainer,
CustomSubText,
CustomText,
CustomTitle,
styles,
} from './styles';
import { CardContainer, CustomSubText, styles } from './styles';
import Tags from './Tags';

function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {
Expand All @@ -35,11 +29,6 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {

const isDarkMode = useIsDarkMode();

const OverLayComponentName = useMemo(() => tree?.name, [tree?.name]);
const OverLayComponentServiceName = useMemo(() => tree?.serviceName, [
tree?.serviceName,
]);

const [isOpen, setIsOpen] = useState(false);

const [text, setText] = useState<ModalText>({
Expand Down Expand Up @@ -102,20 +91,27 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {
styledclass={[styles.selectedSpanDetailsContainer, styles.overflow]}
direction="vertical"
>
<Typography.Text strong> Details for selected Span </Typography.Text>
<Typography.Text
strong
style={{
marginTop: '16px',
}}
>
{' '}
Details for selected Span{' '}
</Typography.Text>

<Typography.Text style={{ fontWeight: 700 }}>Service</Typography.Text>

<CustomTitle>Service</CustomTitle>
<Typography>{tree.serviceName}</Typography>

<Tooltip overlay={OverLayComponentServiceName}>
<CustomText ellipsis>{tree.serviceName}</CustomText>
</Tooltip>
<Typography.Text style={{ fontWeight: 700 }}>Operation</Typography.Text>

<CustomTitle>Operation</CustomTitle>
<Tooltip overlay={OverLayComponentName}>
<CustomText ellipsis>{tree.name}</CustomText>
</Tooltip>
<Typography>{tree.name}</Typography>

<Button onClick={onLogsHandler}>Go to Related logs</Button>
<Button size="small" style={{ marginTop: '8px' }} onClick={onLogsHandler}>
Go to Related logs
</Button>
</StyledSpace>

<Modal
Expand All @@ -136,7 +132,7 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {
)}
</Modal>

<Tabs defaultActiveKey="1" items={items} />
<Tabs style={{ padding: '8px' }} defaultActiveKey="1" items={items} />
</CardContainer>
);
}
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/container/TraceDetail/TraceDetails.styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.span-details-sider {
&.dark {
.ant-layout-sider-trigger {
background-color: black !important;
}
}

&.light {
.ant-layout-sider-trigger {
background-color: white !important;
}
}
}
55 changes: 37 additions & 18 deletions frontend/src/container/TraceDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import './TraceDetails.styles.scss';

import { FilterOutlined } from '@ant-design/icons';
import { Button, Col, Typography } from 'antd';
import Sider from 'antd/es/layout/Sider';
import cx from 'classnames';
import {
StyledCol,
StyledDiv,
Expand All @@ -14,6 +18,7 @@ import { getNodeById } from 'container/GantChart/utils';
import Timeline from 'container/Timeline';
import TraceFlameGraph from 'container/TraceFlameGraph';
import dayjs from 'dayjs';
import { useIsDarkMode } from 'hooks/useDarkMode';
import useUrlQuery from 'hooks/useUrlQuery';
import { spanServiceNameToColorMapping } from 'lib/getRandomColor';
import history from 'lib/history';
Expand Down Expand Up @@ -100,11 +105,6 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element {
[activeSelectedId, treesData],
);

// const onSearchHandler = (value: string) => {
// setSearchSpanString(value);
// setTreeData(spanToTreeUtil(response[0].events));
// };

const onFocusSelectedSpanHandler = (): void => {
const treeNode = getNodeById(activeSelectedId, tree);

Expand All @@ -126,6 +126,9 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element {
);

const isGlobalTimeVisible = tree && traceMetaData.globalStart;
const [collapsed, setCollapsed] = useState(false);

const isDarkMode = useIsDarkMode();

return (
<StyledRow styledclass={[Flex({ flex: 1 })]}>
Expand Down Expand Up @@ -234,22 +237,38 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element {
</GanttChartWrapper>
</StyledDiv>
</StyledCol>

<Col>
<StyledDivider styledclass={[styles.verticalSeparator]} type="vertical" />
</Col>
<StyledCol md={5} sm={5} styledclass={[styles.selectedSpanDetailContainer]}>
<SelectedSpanDetails
firstSpanStartTime={firstSpanStartTime}
tree={[
...(getSelectedNode.spanTree ? getSelectedNode.spanTree : []),
...(getSelectedNode.missingSpanTree
? getSelectedNode.missingSpanTree
: []),
]
.filter(Boolean)
.find((tree) => tree)}
/>
</StyledCol>

<Sider
className={cx('span-details-sider', isDarkMode ? 'dark' : 'light')}
style={{ background: isDarkMode ? '#000' : '#fff' }}
theme={isDarkMode ? 'dark' : 'light'}
collapsible
collapsed={collapsed}
reverseArrow
width={300}
collapsedWidth={40}
onCollapse={(value): void => setCollapsed(value)}
>
{!collapsed && (
<StyledCol styledclass={[styles.selectedSpanDetailContainer]}>
<SelectedSpanDetails
firstSpanStartTime={firstSpanStartTime}
tree={[
...(getSelectedNode.spanTree ? getSelectedNode.spanTree : []),
...(getSelectedNode.missingSpanTree
? getSelectedNode.missingSpanTree
: []),
]
.filter(Boolean)
.find((tree) => tree)}
/>
</StyledCol>
)}
</Sider>
</StyledRow>
);
}
Expand Down
Loading

0 comments on commit 7526888

Please sign in to comment.