|
@@ -1,12 +1,11 @@
|
|
|
-import {Fragment} from 'react';
|
|
|
import {useTheme} from '@emotion/react';
|
|
|
|
|
|
-import {Series} from 'sentry/types/echarts';
|
|
|
+import {EChartClickHandler, EChartHighlightHandler, Series} from 'sentry/types/echarts';
|
|
|
import {P95_COLOR} from 'sentry/views/starfish/colours';
|
|
|
import Chart from 'sentry/views/starfish/components/chart';
|
|
|
import {useSpanMetrics} from 'sentry/views/starfish/queries/useSpanMetrics';
|
|
|
import {useSpanMetricsSeries} from 'sentry/views/starfish/queries/useSpanMetricsSeries';
|
|
|
-import {useSpanSamples} from 'sentry/views/starfish/queries/useSpanSamples';
|
|
|
+import {SpanSample, useSpanSamples} from 'sentry/views/starfish/queries/useSpanSamples';
|
|
|
import {SpanMetricsFields} from 'sentry/views/starfish/types';
|
|
|
import {DataTitles} from 'sentry/views/starfish/views/spans/types';
|
|
|
|
|
@@ -16,10 +15,22 @@ type Props = {
|
|
|
groupId: string;
|
|
|
transactionMethod: string;
|
|
|
transactionName: string;
|
|
|
+ highlightedSpanId?: string;
|
|
|
+ onClickSample?: (sample: SpanSample) => void;
|
|
|
+ onMouseLeaveSample?: () => void;
|
|
|
+ onMouseOverSample?: (sample: SpanSample) => void;
|
|
|
spanDescription?: string;
|
|
|
};
|
|
|
|
|
|
-function DurationChart({groupId, transactionName, transactionMethod}: Props) {
|
|
|
+function DurationChart({
|
|
|
+ groupId,
|
|
|
+ transactionName,
|
|
|
+ onClickSample,
|
|
|
+ onMouseLeaveSample,
|
|
|
+ onMouseOverSample,
|
|
|
+ highlightedSpanId,
|
|
|
+ transactionMethod,
|
|
|
+}: Props) {
|
|
|
const theme = useTheme();
|
|
|
|
|
|
const getSampleSymbol = (duration: number, p95: number) => {
|
|
@@ -79,7 +90,12 @@ function DurationChart({groupId, transactionName, transactionMethod}: Props) {
|
|
|
};
|
|
|
|
|
|
const sampledSpanDataSeries: Series[] = spans.map(
|
|
|
- ({timestamp, 'span.self_time': duration, 'transaction.id': transaction_id}) => ({
|
|
|
+ ({
|
|
|
+ timestamp,
|
|
|
+ 'span.self_time': duration,
|
|
|
+ 'transaction.id': transaction_id,
|
|
|
+ span_id,
|
|
|
+ }) => ({
|
|
|
data: [
|
|
|
{
|
|
|
name: timestamp,
|
|
@@ -88,17 +104,56 @@ function DurationChart({groupId, transactionName, transactionMethod}: Props) {
|
|
|
],
|
|
|
symbol: getSampleSymbol(duration, p95).symbol,
|
|
|
color: getSampleSymbol(duration, p95).color,
|
|
|
- symbolSize: 10,
|
|
|
+ symbolSize: span_id === highlightedSpanId ? 15 : 10,
|
|
|
seriesName: transaction_id,
|
|
|
})
|
|
|
);
|
|
|
|
|
|
+ const getSample = (timestamp: string, duration: number) => {
|
|
|
+ return spans.find(s => s.timestamp === timestamp && s['span.self_time'] === duration);
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleChartClick: EChartClickHandler = e => {
|
|
|
+ const isSpanSample = e?.componentSubType === 'scatter';
|
|
|
+ if (isSpanSample && onClickSample) {
|
|
|
+ const [timestamp, duration] = e.value as [string, number];
|
|
|
+ const sample = getSample(timestamp, duration);
|
|
|
+ if (sample) {
|
|
|
+ onClickSample(sample);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleChartHighlight: EChartHighlightHandler = e => {
|
|
|
+ const {seriesIndex} = e.batch[0];
|
|
|
+ const isSpanSample = seriesIndex > 1;
|
|
|
+ if (isSpanSample && onMouseOverSample) {
|
|
|
+ const spanSampleData = sampledSpanDataSeries?.[seriesIndex - 2]?.data[0];
|
|
|
+ const {name: timestamp, value: duration} = spanSampleData;
|
|
|
+ const sample = getSample(timestamp as string, duration);
|
|
|
+ if (sample) {
|
|
|
+ onMouseOverSample(sample);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!isSpanSample && onMouseLeaveSample) {
|
|
|
+ onMouseLeaveSample();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleMouseLeave = () => {
|
|
|
+ if (onMouseLeaveSample) {
|
|
|
+ onMouseLeaveSample();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
- <Fragment>
|
|
|
+ <div onMouseLeave={handleMouseLeave}>
|
|
|
<h5>{DataTitles.p95}</h5>
|
|
|
<Chart
|
|
|
statsPeriod="24h"
|
|
|
height={140}
|
|
|
+ onClick={handleChartClick}
|
|
|
+ onHighlight={handleChartHighlight}
|
|
|
data={[spanMetricsSeriesData?.[`p95(${SPAN_SELF_TIME})`], baselineP95Series]}
|
|
|
start=""
|
|
|
end=""
|
|
@@ -113,7 +168,7 @@ function DurationChart({groupId, transactionName, transactionMethod}: Props) {
|
|
|
isLineChart
|
|
|
definedAxisTicks={4}
|
|
|
/>
|
|
|
- </Fragment>
|
|
|
+ </div>
|
|
|
);
|
|
|
}
|
|
|
|