Skip to content

Commit

Permalink
feat(transactions): Sync cursor hover between minimap and CPU chart (#…
Browse files Browse the repository at this point in the history
…46814)

Synchronizes the cursor between the span tree minimap and the CPU chart.

Closes #46686
  • Loading branch information
narsaynorath authored and schew2381 committed Apr 12, 2023
1 parent ed1ed45 commit 24a2c35
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 28 deletions.
5 changes: 4 additions & 1 deletion static/app/components/events/interfaces/spans/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,10 @@ class TraceViewHeader extends Component<PropType, State> {
)}
</CursorGuideHandler.Consumer>
{hasProfileMeasurementsChart && (
<ProfilingMeasurements profileData={profiles.data} />
<ProfilingMeasurements
profileData={profiles.data}
renderCursorGuide={this.renderCursorGuide}
/>
)}
{this.renderSecondaryHeader(hasProfileMeasurementsChart)}
</Fragment>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react';
import {useTheme} from '@emotion/react';
import styled from '@emotion/styled';
import uniqBy from 'lodash/uniqBy';
Expand All @@ -22,6 +23,8 @@ import {space} from 'sentry/styles/space';
import {SeriesDataUnit} from 'sentry/types/echarts';
import {defined} from 'sentry/utils';

import * as CursorGuideHandler from './cursorGuideHandler';

const NS_PER_MS = 1000000;

function toMilliseconds(nanoseconds: number) {
Expand Down Expand Up @@ -70,11 +73,8 @@ function Chart({data}: ChartProps) {
axisLabel: {show: false},
axisTick: {show: false},
axisPointer: {
lineStyle: {
color: theme.red300,
width: 2,
opacity: 0.5,
},
type: 'none',
triggerOn: 'mousemove',
},
boundaryGap: false,
}}
Expand All @@ -99,11 +99,26 @@ function Chart({data}: ChartProps) {
);
}

// Memoized to prevent re-rendering when the cursor guide is displayed
const MemoizedChart = React.memo(Chart);

type ProfilingMeasurementsProps = {
profileData: Profiling.ProfileInput;
renderCursorGuide?: ({
cursorGuideHeight,
mouseLeft,
showCursorGuide,
}: {
cursorGuideHeight: number;
mouseLeft: number | undefined;
showCursorGuide: boolean;
}) => void;
};

function ProfilingMeasurements({profileData}: ProfilingMeasurementsProps) {
function ProfilingMeasurements({
profileData,
renderCursorGuide,
}: ProfilingMeasurementsProps) {
const theme = useTheme();

if (!('measurements' in profileData) || !defined(profileData.measurements?.cpu_usage)) {
Expand All @@ -113,33 +128,50 @@ function ProfilingMeasurements({profileData}: ProfilingMeasurementsProps) {
const cpuUsageData = profileData.measurements!.cpu_usage!;

return (
<DividerHandlerManager.Consumer>
{dividerHandlerChildrenProps => {
const {dividerPosition} = dividerHandlerChildrenProps;
return (
<MeasurementContainer>
<ChartOpsLabel dividerPosition={dividerPosition}>
<OpsLine>
<OpsNameContainer>
<OpsDot style={{backgroundColor: theme.green200}} />
<OpsName>{t('CPU Usage')}</OpsName>
</OpsNameContainer>
</OpsLine>
</ChartOpsLabel>
<DividerSpacer />
<ChartContainer>
<Chart data={cpuUsageData} />;
</ChartContainer>
</MeasurementContainer>
);
}}
</DividerHandlerManager.Consumer>
<CursorGuideHandler.Consumer>
{({displayCursorGuide, hideCursorGuide, mouseLeft, showCursorGuide}) => (
<DividerHandlerManager.Consumer>
{({dividerPosition}) => (
<MeasurementContainer>
<ChartOpsLabel dividerPosition={dividerPosition}>
<OpsLine>
<OpsNameContainer>
<OpsDot style={{backgroundColor: theme.green200}} />
<OpsName>{t('CPU Usage')}</OpsName>
</OpsNameContainer>
</OpsLine>
</ChartOpsLabel>
<DividerSpacer />
<ChartContainer
onMouseEnter={event => {
displayCursorGuide(event.pageX);
}}
onMouseLeave={() => {
hideCursorGuide();
}}
onMouseMove={event => {
displayCursorGuide(event.pageX);
}}
>
<MemoizedChart data={cpuUsageData} />
{renderCursorGuide?.({
showCursorGuide,
mouseLeft,
cursorGuideHeight: PROFILE_MEASUREMENTS_CHART_HEIGHT,
})}
</ChartContainer>
</MeasurementContainer>
)}
</DividerHandlerManager.Consumer>
)}
</CursorGuideHandler.Consumer>
);
}

export {ProfilingMeasurements};

const ChartContainer = styled('div')`
position: relative;
flex: 1;
border-top: 1px solid ${p => p.theme.border};
`;
Expand Down

0 comments on commit 24a2c35

Please sign in to comment.