Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(transactions): Sync cursor hover between minimap and CPU chart #46814

Merged
merged 10 commits into from
Apr 4, 2023
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