feat: new trace detail page code enhancemenets and cleanup

This commit is contained in:
Pranshu Chittora 2022-03-09 10:43:02 +05:30
parent 314f95a914
commit c3ebbfa8ca
No known key found for this signature in database
GPG Key ID: 3A9E57A016CC0626
16 changed files with 341 additions and 208 deletions

View File

@ -1,4 +1,6 @@
import { Col, ColProps, Row, RowProps } from 'antd';
import * as AntD from 'antd';
import { TextProps } from 'antd/lib/typography/Text';
import { TitleProps } from 'antd/lib/typography/Title';
import React from 'react';
import styled, {
css,
@ -10,15 +12,47 @@ import styled, {
import { IStyledClass } from './types';
const styledClass = (props: IStyledClass): FlattenSimpleInterpolation =>
props.styledClass;
props.styledclass;
interface IStyledCol extends ColProps, IStyledClass {}
const StyledCol = styled(Col)<IStyledCol>`
interface IStyledCol extends AntD.ColProps, IStyledClass {}
const StyledCol = styled(AntD.Col)<IStyledCol>`
${styledClass}
`;
interface IStyledRow extends RowProps, IStyledClass {}
const StyledRow = styled(Row)<IStyledRow>`
interface IStyledRow extends AntD.RowProps, IStyledClass {}
const StyledRow = styled(AntD.Row)<IStyledRow>`
${styledClass}
`;
interface IStyledDivider extends AntD.DividerProps, IStyledClass {}
const StyledDivider = styled(AntD.Divider)<IStyledDivider>`
${styledClass}
`;
interface IStyledSpace extends AntD.SpaceProps, IStyledClass {}
const StyledSpace = styled(AntD.Space)<IStyledSpace>`
${styledClass}
`;
interface IStyledTabs extends AntD.TabsProps, IStyledClass {}
const StyledTabs = styled(AntD.Divider)<IStyledTabs>`
${styledClass}
`;
interface IStyledButton extends AntD.ButtonProps, IStyledClass {}
const StyledButton = styled(AntD.Button)<IStyledButton>`
${styledClass}
`;
const { Text } = AntD.Typography;
interface IStyledTypographyText extends TextProps, IStyledClass {}
const StyledTypographyText = styled(Text)<IStyledTypographyText>`
${styledClass}
`;
const { Title } = AntD.Typography;
interface IStyledTypographyTitle extends TitleProps, IStyledClass {}
const StyledTypographyTitle = styled(Title)<IStyledTypographyTitle>`
${styledClass}
`;
@ -29,4 +63,17 @@ const StyledDiv = styled.div<IStyledDiv>`
${styledClass}
`;
export { StyledCol, StyledDiv, StyledRow };
const StyledTypography = {
Text: StyledTypographyText,
Title: StyledTypographyTitle,
};
export {
StyledButton,
StyledCol,
StyledDiv,
StyledDivider,
StyledRow,
StyledSpace,
StyledTabs,
StyledTypography,
};

View File

@ -1,5 +1,5 @@
import { FlattenSimpleInterpolation } from 'styled-components';
export interface IStyledClass {
styledClass: FlattenSimpleInterpolation[];
styledclass?: FlattenSimpleInterpolation[];
}

View File

@ -1,22 +1,24 @@
import React, { useRef, useState, useEffect } from 'react';
import { CaretDownFilled, CaretRightFilled } from '@ant-design/icons';
import { Col } from 'antd';
import { StyledCol, StyledRow } from 'components/Styled';
import { IIntervalUnit } from 'container/TraceDetail/utils';
import useThemeMode from 'hooks/useThemeMode';
import { SPAN_DETAILS_LEFT_COL_WIDTH } from 'pages/TraceDetail/constants';
import React, { useEffect, useRef, useState } from 'react';
import { pushDStree } from 'store/actions';
import { ITraceMetaData } from '..';
import SpanLength from '../SpanLength';
import SpanName from '../SpanName';
import { getMetaDataFromSpanTree, getTopLeftFromBody } from '../utils';
import {
CardComponent,
CardContainer,
CaretContainer,
Wrapper,
HoverCard,
styles,
Wrapper,
} from './styles';
import { CaretDownFilled, CaretRightFilled } from '@ant-design/icons';
import SpanLength from '../SpanLength';
import SpanName from '../SpanName';
import { pushDStree } from 'store/actions';
import { getMetaDataFromSpanTree, getTopLeftFromBody } from '../utils';
import { ITraceMetaData } from '..';
import { Col, Row } from 'antd';
import { SPAN_DETAILS_LEFT_COL_WIDTH } from 'pages/TraceDetail/constants'
import { IIntervalUnit, resolveTimeFromInterval } from 'container/TraceDetail/utils';
import useThemeMode from 'hooks/useThemeMode';
const Trace = (props: TraceProps): JSX.Element => {
const {
@ -38,7 +40,7 @@ const Trace = (props: TraceProps): JSX.Element => {
intervalUnit,
} = props;
const { isDarkMode } = useThemeMode()
const { isDarkMode } = useThemeMode();
const [isOpen, setOpen] = useState<boolean>(activeSpanPath[level] === id);
const localTreeExpandInteraction = useRef<boolean | 0>(0); // Boolean is for the state of the expansion whereas the number i.e. 0 is for skipping the user interaction.
@ -47,20 +49,18 @@ const Trace = (props: TraceProps): JSX.Element => {
if (localTreeExpandInteraction.current !== 0) {
setOpen(localTreeExpandInteraction.current);
localTreeExpandInteraction.current = 0;
} else if (!isOpen) {
setOpen(activeSpanPath[level] === id);
}
else if (!isOpen) {
setOpen(activeSpanPath[level] === id)
}
}, [activeSpanPath, isOpen])
}, [activeSpanPath, isOpen]);
useEffect(() => {
if (isExpandAll) {
setOpen(isExpandAll)
setOpen(isExpandAll);
} else {
setOpen(activeSpanPath[level] === id);
}
else {
setOpen(activeSpanPath[level] === id)
}
}, [isExpandAll])
}, [isExpandAll]);
const isOnlyChild = props.children.length === 1;
const [top, setTop] = useState<number>(0);
@ -69,9 +69,13 @@ const Trace = (props: TraceProps): JSX.Element => {
React.useEffect(() => {
if (activeSelectedId === id) {
ref.current?.scrollIntoView({ block: 'nearest', behavior: 'auto', inline: 'nearest' });
ref.current?.scrollIntoView({
block: 'nearest',
behavior: 'auto',
inline: 'nearest',
});
}
}, [activeSelectedId])
}, [activeSelectedId]);
const onMouseEnterHandler = () => {
setActiveHoverId(props.id);
@ -87,18 +91,21 @@ const Trace = (props: TraceProps): JSX.Element => {
const onClick = () => {
setActiveSelectedId(id);
}
};
const onClickTreeExpansion = (event) => {
event.stopPropagation()
setOpen((state) => { localTreeExpandInteraction.current = !isOpen; return !state });
}
event.stopPropagation();
setOpen((state) => {
localTreeExpandInteraction.current = !isOpen;
return !state;
});
};
const { totalSpans } = getMetaDataFromSpanTree(props);
const inMsCount = value;
const nodeLeftOffset = ((startTime - globalStart) * 1e2) / globalSpread;
const width = (value * 1e2) / (globalSpread * 1e6);
const panelWidth = SPAN_DETAILS_LEFT_COL_WIDTH - (level * (16 + 1)) - 16;
const panelWidth = SPAN_DETAILS_LEFT_COL_WIDTH - level * (16 + 1) - 48;
return (
<>
@ -115,17 +122,12 @@ const Trace = (props: TraceProps): JSX.Element => {
isDarkMode={isDarkMode}
/>
<CardContainer
onClick={onClick}
>
<Col flex={`${panelWidth}px`} style={{ overflow: 'hidden' }}>
<Row style={{ flexWrap: 'nowrap' }}>
<CardContainer onClick={onClick}>
<StyledCol flex={`${panelWidth}px`} styledclass={[styles.overFlowHidden]}>
<StyledRow styledclass={[styles.flexNoWrap]}>
<Col>
{totalSpans !== 1 && (
<CardComponent
isDarkMode={isDarkMode}
onClick={onClickTreeExpansion}
>
<CardComponent isDarkMode={isDarkMode} onClick={onClickTreeExpansion}>
{totalSpans}
<CaretContainer>
{isOpen ? <CaretDownFilled /> : <CaretRightFilled />}
@ -136,15 +138,15 @@ const Trace = (props: TraceProps): JSX.Element => {
<Col>
<SpanName name={name} serviceName={serviceName} />
</Col>
</Row>
</Col>
<Col flex={'1'} >
</StyledRow>
</StyledCol>
<Col flex={'1'}>
<SpanLength
leftOffset={nodeLeftOffset.toString()}
width={width.toString()}
bgColor={serviceColour}
id={id}
inMsCount={(inMsCount / 1e6)}
inMsCount={inMsCount / 1e6}
intervalUnit={intervalUnit}
/>
</Col>

View File

@ -75,3 +75,16 @@ export const HoverCard = styled.div<HoverCardProps>`
height: 3rem;
opacity: 0.5;
`;
const flexNoWrap = css`
flex-wrap: nowrap;
`;
const overFlowHidden = css`
overflow: hidden;
`;
export const styles = {
flexNoWrap,
overFlowHidden,
};

View File

@ -1,11 +1,12 @@
import { MinusSquareOutlined, PlusSquareOutlined } from '@ant-design/icons';
import { IIntervalUnit } from 'container/TraceDetail/utils';
import React, { useEffect, useState } from 'react';
import Trace from './Trace';
import { MinusSquareOutlined, PlusSquareOutlined } from '@ant-design/icons'
import { Wrapper, CardWrapper, CardContainer, CollapseButton } from './styles';
import { getSpanPath } from './utils';
import { IIntervalUnit } from 'container/TraceDetail/utils'
import { ITraceTree } from 'types/api/trace/getTraceItem';
import { CardContainer, CardWrapper, CollapseButton, Wrapper } from './styles';
import Trace from './Trace';
import { getSpanPath } from './utils';
const GanttChart = (props: GanttChartProps): JSX.Element => {
const {
data,
@ -15,7 +16,7 @@ const GanttChart = (props: GanttChartProps): JSX.Element => {
activeSelectedId,
setActiveSelectedId,
spanId,
intervalUnit
intervalUnit,
} = props;
const { globalStart, spread: globalSpread } = traceMetaData;
@ -24,11 +25,11 @@ const GanttChart = (props: GanttChartProps): JSX.Element => {
const [activeSpanPath, setActiveSpanPath] = useState<string[]>([]);
useEffect(() => {
setActiveSpanPath(getSpanPath(data, spanId))
setActiveSpanPath(getSpanPath(data, spanId));
}, [spanId]);
useEffect(() => {
setActiveSpanPath(getSpanPath(data, activeSelectedId))
setActiveSpanPath(getSpanPath(data, activeSelectedId));
}, [activeSelectedId]);
const handleCollapse = () => {
@ -38,7 +39,10 @@ const GanttChart = (props: GanttChartProps): JSX.Element => {
<>
<Wrapper>
<CardContainer>
<CollapseButton onClick={handleCollapse} style={{ fontSize: '1.2rem' }} title={isExpandAll ? 'Collapse All' : "Expand All"}>
<CollapseButton
onClick={handleCollapse}
title={isExpandAll ? 'Collapse All' : 'Expand All'}
>
{isExpandAll ? <MinusSquareOutlined /> : <PlusSquareOutlined />}
</CollapseButton>
<CardWrapper>
@ -81,7 +85,7 @@ export interface GanttChartProps {
setActiveHoverId: React.Dispatch<React.SetStateAction<string>>;
setActiveSelectedId: React.Dispatch<React.SetStateAction<string>>;
spanId: string;
intervalUnit: IIntervalUnit
intervalUnit: IIntervalUnit;
}
export default GanttChart;

View File

@ -44,4 +44,5 @@ export const CollapseButton = styled.div`
position: absolute;
top: 0;
left: 0;
font-size: 1.2rem;
`;

View File

@ -1,15 +1,12 @@
import React, { useState, useMemo } from 'react';
import { isEqual } from 'lodash-es';
import styles from './style.module.css';
import { useMeasure } from 'react-use';
import { toFixed } from 'utils/toFixed';
import {
INTERVAL_UNITS,
resolveTimeFromInterval,
} from 'container/TraceDetail/utils';
import { StyledDiv } from 'components/Styled';
import { INTERVAL_UNITS } from 'container/TraceDetail/utils';
import useThemeMode from 'hooks/useThemeMode';
import React, { useMemo, useState } from 'react';
import { useMeasure } from 'react-use';
import { styles, Svg, TimelineInterval } from './styles';
import { Interval } from './types';
import { getIntervalSpread, getIntervals } from './utils';
import { getIntervals, getIntervalSpread } from './utils';
interface TimelineProps {
traceMetaData: object;
globalTraceMetadata: object;
@ -21,7 +18,7 @@ const Timeline = ({
globalTraceMetadata,
intervalUnit,
setIntervalUnit,
}: TimelineProps) => {
}: TimelineProps): JSX.Element => {
const [ref, { width }] = useMeasure<HTMLDivElement>();
const { isDarkMode } = useThemeMode();
@ -61,12 +58,10 @@ const Timeline = ({
}, [traceMetaData, globalTraceMetadata]);
return (
<div ref={ref} style={{ flex: 1, overflow: 'inherit' }}>
<svg
style={{ overflow: 'inherit' }}
<StyledDiv ref={ref} styledclass={[styles.timelineContainer]}>
<Svg
viewBox={`0 0 ${width} ${Timeline_Height}`}
xmlns="http://www.w3.org/2000/svg"
className={styles['svg-container']}
>
<line
x1={Timeline_H_Spacing}
@ -78,13 +73,12 @@ const Timeline = ({
/>
{intervals &&
intervals.map((interval, index) => (
<g
<TimelineInterval
transform={`translate(${
Timeline_H_Spacing +
(interval.percentage * (width - 2 * Timeline_H_Spacing)) / 100
},0)`}
className={styles['timeline-tick']}
key={interval.label + interval.percentage + index}
key={`${interval.label + interval.percentage + index}`}
>
<text y={13} fill={isDarkMode ? 'white' : 'black'}>
{interval.label}
@ -95,10 +89,10 @@ const Timeline = ({
stroke={isDarkMode ? 'white' : 'black'}
strokeWidth="1"
/>
</g>
</TimelineInterval>
))}
</svg>
</div>
</Svg>
</StyledDiv>
);
};

View File

@ -1,8 +0,0 @@
.svg-container {
overflow: visible;
position: absolute;
}
.timeline-tick {
text-anchor: middle;
font-size: 0.6rem;
}

View File

@ -0,0 +1,19 @@
import styled, { css } from 'styled-components';
const timelineContainer = css`
flex: 1;
overflow: visible;
`;
export const styles = {
timelineContainer,
};
export const Svg = styled.svg`
overflow: visible !important;
position: absolute;
`;
export const TimelineInterval = styled.g`
text-anchor: middle;
font-size: 0.6rem;
`;

View File

@ -1,23 +1,24 @@
import { Button, Modal, Collapse } from 'antd';
import { Collapse, Modal } from 'antd';
import { StyledButton } from 'components/Styled';
import useThemeMode from 'hooks/useThemeMode';
import React, { useRef, useState } from 'react';
import React, { useState } from 'react';
import { ITraceTree } from 'types/api/trace/getTraceItem';
import { CustomSubText, CustomSubTitle } from './styles';
import { CustomSubText, CustomSubTitle, styles } from './styles';
// import Editor from 'components/Editor';
const { Panel } = Collapse;
const ErrorTag = ({ event }: ErrorTagProps) => {
const ErrorTag = ({ event }: ErrorTagProps): JSX.Element => {
const [isOpen, setIsOpen] = useState(false);
const { isDarkMode } = useThemeMode();
// const useTextRef = useRef('');
const [text, setText] = useState({
text: '',
subText: '',
});
const onToggleHandler = (state: boolean) => {
const onToggleHandler = (state: boolean): void => {
setIsOpen(state);
};
@ -28,6 +29,7 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
return (
<Collapse
key={`${name}${JSON.stringify(attributeMap)}`}
defaultActiveKey={[name || attributeMap.event]}
expandIconPosition="right"
>
@ -46,24 +48,21 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
{value}
<br />
{isEllipsed && (
<Button
style={{ padding: 0, margin: 0 }}
onClick={() => {
<StyledButton
styledclass={[styles.removeMargin, styles.removePadding]}
onClick={(): void => {
onToggleHandler(true);
setText({
subText: value,
text: event,
});
// useTextRef.current = value;
}}
type="link"
>
View full log event message
</Button>
</StyledButton>
)}
</CustomSubText>
</>
);
})}
@ -72,7 +71,7 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
);
})}
<Modal
onCancel={() => onToggleHandler(false)}
onCancel={(): void => onToggleHandler(false)}
title="Log Message"
visible={isOpen}
destroyOnClose

View File

@ -1,15 +1,18 @@
import { Space, Tabs, Typography } from 'antd';
import { StyledSpace, StyledTabs } from 'components/Styled';
import useThemeMode from 'hooks/useThemeMode';
import React from 'react';
import { ITraceTree } from 'types/api/trace/getTraceItem';
import ErrorTag from './ErrorTag';
import {
CardContainer,
CustomSubText,
CustomSubTitle,
CustomText,
CustomTitle,
styles,
} from './styles';
import ErrorTag from './ErrorTag';
import useThemeMode from 'hooks/useThemeMode';
const { TabPane } = Tabs;
@ -24,7 +27,11 @@ const SelectedSpanDetails = (props: SelectedSpanDetailsProps): JSX.Element => {
return (
<CardContainer>
<Space direction="vertical" style={{ marginLeft: '0.5rem' }}>
<StyledSpace
styledclass={[styles.selectedSpanDetailsContainer]}
direction="vertical"
style={{ marginLeft: '0.5rem' }}
>
<strong> Details for selected Span </strong>
<Space direction="vertical" size={2}>
<CustomTitle>Service</CustomTitle>
@ -34,13 +41,16 @@ const SelectedSpanDetails = (props: SelectedSpanDetailsProps): JSX.Element => {
<CustomTitle>Operation</CustomTitle>
<CustomText>{name}</CustomText>
</Space>
</Space>
<Tabs defaultActiveKey="1" style={{ marginTop: '1rem' }}>
</StyledSpace>
<StyledTabs
styledclass={[styles.spanEventsTabsContainer]}
defaultActiveKey="1"
>
<TabPane tab="Tags" key="1">
{tags.length !== 0 ? (
tags.map((tags) => {
return (
<React.Fragment>
<React.Fragment key={JSON.stringify(tags)}>
{tags.value && (
<>
<CustomSubTitle>{tags.key}</CustomSubTitle>
@ -63,7 +73,7 @@ const SelectedSpanDetails = (props: SelectedSpanDetailsProps): JSX.Element => {
<Typography>No events data in selected span</Typography>
)}
</TabPane>
</Tabs>
</StyledTabs>
</CardContainer>
);
};

View File

@ -1,5 +1,5 @@
import { Typography } from 'antd';
import styled from 'styled-components';
import styled, { css } from 'styled-components';
const { Text, Title, Paragraph } = Typography;
export const CustomTitle = styled(Title)`
@ -44,3 +44,24 @@ export const CardContainer = styled.div`
flex: 1;
overflow-y: auto;
`;
const removeMargin = css`
margin: 0;
`;
const removePadding = css`
padding: 0;
`;
const selectedSpanDetailsContainer = css`
margin-left: 0.5rem;
`;
const spanEventsTabsContainer = css`
margin-top: 1rem;
`;
export const styles = {
removeMargin,
removePadding,
selectedSpanDetailsContainer,
spanEventsTabsContainer,
};

View File

@ -1,6 +1,13 @@
import { FilterOutlined } from '@ant-design/icons';
import { Button, Col, Divider, Row, Space, Typography } from 'antd';
import { StyledCol, StyledDiv, StyledRow } from 'components/Styled';
import { Button, Col } from 'antd';
import {
StyledCol,
StyledDiv,
StyledDivider,
StyledRow,
StyledSpace,
StyledTypography,
} from 'components/Styled';
import * as StyledStyles from 'components/Styled/styles';
import GanttChart from 'container/GantChart';
import { getNodeById } from 'container/GantChart/utils';
@ -43,7 +50,7 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
return getSpanTreeMetadata(getSortedData(treeData), spanServiceColors);
}, [treeData]);
const [globalTraceMetadata, _setGlobalTraceMetadata] = useState<object>({
const [globalTraceMetadata, _setGlobalTraceMetadata] = useState({
...traceMetaData,
});
@ -60,7 +67,7 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
return getNodeById(activeSelectedId, treeData);
}, [activeSelectedId, treeData]);
const onSearchHandler = (value: string) => {
const onSearchHandler = (value: string): void => {
setSearchSpanString(value);
setTreeData(spanToTreeUtil(response[0].events));
};
@ -71,37 +78,25 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
}
};
const onResetHandler = () => {
const onResetHandler = (): void => {
setTreeData(spanToTreeUtil(response[0].events));
};
return (
<StyledRow styledClass={[StyledStyles.Flex({ flex: 1 })]}>
<StyledCol
flex={'auto'}
styledClass={[
StyledStyles.Flex({ flexDirection: 'column' }),
StyledStyles.Display({ display: 'flex' }),
]}
>
<StyledRow
styledClass={[
StyledStyles.Spacing({
margin: '0 1rem 0 0',
}),
]}
>
<Col
<StyledRow styledclass={[StyledStyles.Flex({ flex: 1 })]}>
<StyledCol flex={'auto'} styledclass={styles.leftContainer}>
<StyledRow styledclass={styles.flameAndTimelineContainer}>
<StyledCol
styledclass={styles.traceMetaDataContainer}
flex={`${SPAN_DETAILS_LEFT_COL_WIDTH}px`}
style={{ alignItems: 'center', display: 'flex', flexDirection: 'column' }}
>
<Typography.Title level={5} style={{ margin: 0 }}>
<StyledTypography.Title styledclass={[styles.removeMargin]} level={5}>
Trace Details
</Typography.Title>
<Typography.Text style={{ margin: 0 }}>
</StyledTypography.Title>
<StyledTypography.Text styledclass={[styles.removeMargin]}>
{traceMetaData.totalSpans} Span
</Typography.Text>
</Col>
</StyledTypography.Text>
</StyledCol>
<Col flex={'auto'}>
<TraceFlameGraph
treeData={tree}
@ -114,8 +109,8 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
/>
</Col>
</StyledRow>
<Row style={{ marginTop: '2rem' }}>
<Col
<StyledRow styledclass={[styles.traceDateAndTimelineContainer]}>
<StyledCol
flex={`${SPAN_DETAILS_LEFT_COL_WIDTH}px`}
style={{
display: 'flex',
@ -124,16 +119,8 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
}}
>
{dayjs(traceMetaData.globalStart / 1e6).format('hh:mm:ssa MM/DD')}
</Col>
<StyledCol
flex="auto"
style={{ overflow: 'visible' }}
styledClass={[
StyledStyles.Spacing({
margin: '0 1rem 0 0',
}),
]}
>
</StyledCol>
<StyledCol flex="auto" styledclass={[styles.timelineContainer]}>
<Timeline
globalTraceMetadata={globalTraceMetadata}
traceMetaData={traceMetaData}
@ -141,10 +128,10 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
setIntervalUnit={setIntervalUnit}
/>
</StyledCol>
<Divider style={{ height: '100%', margin: '0' }} />
</Row>
<StyledDivider styledclass={[styles.verticalSeparator]} />
</StyledRow>
<StyledRow
styledClass={[
styledclass={[
styles.traceDetailContentSpacing,
StyledStyles.Spacing({
margin: '1.5rem 1rem 0.5rem',
@ -160,40 +147,17 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
/> */}
</Col>
<Col flex={'auto'}>
<Space
style={{
float: 'right',
}}
>
<StyledSpace styledclass={[styles.floatRight]}>
<Button onClick={onFocusSelectedSpanHandler} icon={<FilterOutlined />}>
Focus on selected span
</Button>
<Button type="default" onClick={onResetHandler}>
Reset Focus
</Button>
</Space>
</StyledSpace>
</Col>
</StyledRow>
<StyledDiv
styledClass={[
styles.traceDetailContentSpacing,
StyledStyles.Spacing({
margin: '1.5rem 1rem 0.5rem',
}),
StyledStyles.Flex({
flexDirection: 'column',
}),
StyledStyles.Display({
display: 'flex',
}),
]}
style={{
position: 'relative',
flex: 1,
overflowY: 'auto',
overflowX: 'hidden',
}}
>
<StyledDiv styledclass={[styles.ganttChartContainer]}>
<GanttChart
traceMetaData={traceMetaData}
data={tree}
@ -207,20 +171,11 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
</StyledDiv>
</StyledCol>
<Col>
<Divider style={{ height: '100%', margin: '0' }} type="vertical" />
<StyledDivider styledclass={[styles.verticalSeparator]} type="vertical" />
</Col>
<Col
md={5}
sm={5}
style={{
height: '100%',
position: 'relative',
display: 'flex',
flexDirection: 'column',
}}
>
<StyledCol md={5} sm={5} styledclass={[styles.selectedSpanDetailContainer]}>
<SelectedSpanDetails tree={getSelectedNode} />
</Col>
</StyledCol>
</StyledRow>
);
};

View File

@ -1,5 +1,79 @@
import * as StyledStyles from 'components/Styled/styles';
import { css } from 'styled-components';
export const traceDetailContentSpacing = StyledStyles.Spacing({
margin: '0 1rem 0 0',
});
/**
* Styles for the left container. Containers flamegraph, timeline and gantt chart
*/
export const leftContainer = [
css`
display: flex;
flex-direction: column;
`,
];
/**
* Styles for the top container. Contains TotalSpans, FlameGraph and Timeline.
*/
export const flameAndTimelineContainer = [
css`
margin: 0 1rem 0 0;
`,
];
export const traceMetaDataContainer = [
css`
display: flex;
flex-direction: column;
align-items: center;
`,
];
export const traceDateAndTimelineContainer = css`
margin-top: 2rem;
`;
export const traceDateTimeContainer = css`
display: flex;
aligh-items: center;
justify-content: center;
`;
export const timelineContainer = css`
overflow: visible;
margin: 0 1rem 0 0;
`;
export const ganttChartContainer = css`
margin: 1.5rem 1rem 0.5rem;
display: flex;
flex-direction: column;
position: relative;
flex: 1;
overflow-y: auto;
overflow-x: hidden;
`;
export const selectedSpanDetailContainer = css`
height: 100%;
position: relative;
display: flex;
flex-direction: column;
`;
/**
* Generic / Common styles
*/
export const verticalSeparator = css`
height: 100%;
margin: 0;
`;
export const traceDetailContentSpacing = css`
margin: 0 1rem 0 0;
`;
export const floatRight = css`
float: right;
`;
export const removeMargin = css`
margin: 0;
`;

View File

@ -1,17 +1,18 @@
import React, { useState, useLayoutEffect, useMemo } from 'react';
import Color from 'color';
import { pushDStree } from 'store/actions';
import {
SpanItemContainer,
TraceFlameGraphContainer,
TOTAL_SPAN_HEIGHT,
} from './styles';
import {
IIntervalUnit,
resolveTimeFromInterval,
} from 'container/TraceDetail/utils';
import { toFixed } from 'utils/toFixed';
import useThemeMode from 'hooks/useThemeMode';
import React, { useLayoutEffect, useMemo, useState } from 'react';
import { pushDStree } from 'store/actions';
import { toFixed } from 'utils/toFixed';
import {
SpanItemContainer,
TOTAL_SPAN_HEIGHT,
TraceFlameGraphContainer,
} from './styles';
const SpanItem = ({
topOffset = 0, // top offset in px
@ -33,7 +34,7 @@ const SpanItem = ({
onSpanHover: Function;
hoveredSpanId: string;
selectedSpanId: string;
}) => {
}): JSX.Element => {
const { serviceColour } = spanData;
const [isSelected, setIsSelected] = useState<boolean>(false);
const [isLocalHover, setIsLocalHover] = useState<boolean>(false);
@ -48,14 +49,14 @@ const SpanItem = ({
}
}, [hoveredSpanId, selectedSpanId]);
const handleHover = (hoverState: boolean) => {
const handleHover = (hoverState: boolean): void => {
setIsLocalHover(hoverState);
if (hoverState) onSpanHover(spanData.id);
else onSpanHover(null);
};
const handleClick = () => {
const handleClick = (): void => {
onSpanSelect(spanData.id);
};
@ -96,7 +97,7 @@ const TraceFlameGraph = (props: {
hoveredSpanId: string;
selectedSpanId: string;
intervalUnit: IIntervalUnit;
}) => {
}): null | JSX.Element => {
if (!props.treeData || props.treeData.id === 'empty' || !props.traceMetaData) {
return null;
}
@ -125,7 +126,7 @@ const TraceFlameGraph = (props: {
onSpanSelect: Function;
hoveredSpanId: string;
selectedSpanId: string;
}) => {
}): null | JSX.Element => {
if (!spanData) {
return null;
}

View File

@ -4,5 +4,6 @@ export * from './global';
export * from './metrics';
export * from './MetricsActions';
export * from './serviceMap';
export * from './traces';
export * from './types';
export * from './usage';