1
- import { Fragment , useCallback , useMemo } from 'react' ;
2
- import { useTheme } from '@emotion/react' ;
1
+ import { Fragment , useMemo } from 'react' ;
3
2
import styled from '@emotion/styled' ;
4
3
5
4
import Feature from 'sentry/components/acl/feature' ;
@@ -13,29 +12,22 @@ import {t} from 'sentry/locale';
13
12
import { defined } from 'sentry/utils' ;
14
13
import { trackAnalytics } from 'sentry/utils/analytics' ;
15
14
import { parseFunction , prettifyParsedFunction } from 'sentry/utils/discover/fields' ;
16
- import { isTimeSeriesOther } from 'sentry/utils/timeSeries/isTimeSeriesOther' ;
17
- import { markDelayedData } from 'sentry/utils/timeSeries/markDelayedData' ;
18
15
import useOrganization from 'sentry/utils/useOrganization' ;
19
16
import usePageFilters from 'sentry/utils/usePageFilters' ;
20
- import usePrevious from 'sentry/utils/usePrevious' ;
21
17
import useProjects from 'sentry/utils/useProjects' ;
22
18
import { Dataset } from 'sentry/views/alerts/rules/metric/types' ;
23
19
import { determineSeriesSampleCountAndIsSampled } from 'sentry/views/alerts/rules/metric/utils/determineSeriesSampleCount' ;
24
- import { Area } from 'sentry/views/dashboards/widgets/timeSeriesWidget/plottables/area' ;
25
- import { Bars } from 'sentry/views/dashboards/widgets/timeSeriesWidget/plottables/bars' ;
26
- import { Line } from 'sentry/views/dashboards/widgets/timeSeriesWidget/plottables/line' ;
27
- import { TimeSeriesWidgetVisualization } from 'sentry/views/dashboards/widgets/timeSeriesWidget/timeSeriesWidgetVisualization' ;
28
20
import { Widget } from 'sentry/views/dashboards/widgets/widget/widget' ;
21
+ import { ChartVisualization } from 'sentry/views/explore/components/chart/chartVisualization' ;
22
+ import type { ChartInfo } from 'sentry/views/explore/components/chart/types' ;
29
23
import { Mode } from 'sentry/views/explore/contexts/pageParamsContext/mode' ;
30
24
import { determineDefaultChartType } from 'sentry/views/explore/contexts/pageParamsContext/visualizes' ;
31
25
import { useChartInterval } from 'sentry/views/explore/hooks/useChartInterval' ;
32
26
import { useAddCompareQueryToDashboard } from 'sentry/views/explore/multiQueryMode/hooks/useAddCompareQueryToDashboard' ;
33
- import { DEFAULT_TOP_EVENTS } from 'sentry/views/explore/multiQueryMode/hooks/useMultiQueryTimeseries' ;
34
27
import {
35
28
type ReadableExploreQueryParts ,
36
29
useUpdateQueryAtIndex ,
37
30
} from 'sentry/views/explore/multiQueryMode/locationUtils' ;
38
- import { INGESTION_DELAY } from 'sentry/views/explore/settings' ;
39
31
import { EXPLORE_CHART_TYPE_OPTIONS } from 'sentry/views/explore/spans/charts' ;
40
32
import { ConfidenceFooter } from 'sentry/views/explore/spans/charts/confidenceFooter' ;
41
33
import { combineConfidenceForSeries } from 'sentry/views/explore/utils' ;
@@ -45,7 +37,6 @@ import {getAlertsUrl} from 'sentry/views/insights/common/utils/getAlertsUrl';
45
37
46
38
const CHART_HEIGHT = 260 ;
47
39
interface MultiQueryChartProps {
48
- canUsePreviousResults : boolean ;
49
40
index : number ;
50
41
mode : Mode ;
51
42
query : ReadableExploreQueryParts ;
@@ -57,21 +48,10 @@ export function MultiQueryModeChart({
57
48
query : queryParts ,
58
49
mode,
59
50
timeseriesResult,
60
- canUsePreviousResults,
61
51
} : MultiQueryChartProps ) {
62
- const theme = useTheme ( ) ;
63
-
64
52
const yAxes = queryParts . yAxes ;
65
53
const isTopN = mode === Mode . AGGREGATE ;
66
54
67
- const [ confidence , numSeries ] = useMemo ( ( ) => {
68
- const series = yAxes . flatMap ( yAxis => timeseriesResult . data [ yAxis ] ) . filter ( defined ) ;
69
- return [
70
- combineConfidenceForSeries ( series ) ,
71
- Math . min ( series . length , DEFAULT_TOP_EVENTS ) ,
72
- ] ;
73
- } , [ timeseriesResult . data , yAxes ] ) ;
74
-
75
55
const [ interval , setInterval , intervalOptions ] = useChartInterval ( ) ;
76
56
77
57
const formattedYAxes = yAxes . map ( yaxis => {
@@ -81,74 +61,27 @@ export function MultiQueryModeChart({
81
61
82
62
const updateChartType = useUpdateQueryAtIndex ( index ) ;
83
63
84
- const previousTimeseriesResult = usePrevious ( timeseriesResult ) ;
85
-
86
- const getSeries = useCallback ( ( ) => {
87
- const shouldUsePreviousResults =
88
- timeseriesResult . isPending &&
89
- canUsePreviousResults &&
90
- yAxes . every ( yAxis => previousTimeseriesResult . data . hasOwnProperty ( yAxis ) ) ;
91
-
92
- const data = yAxes . flatMap ( ( yAxis , i ) => {
93
- const series = shouldUsePreviousResults
94
- ? previousTimeseriesResult . data [ yAxis ]
95
- : timeseriesResult . data [ yAxis ] ;
96
- return ( series ?? [ ] ) . map ( s => {
97
- // We replace the series name with the formatted series name here
98
- // when possible as it's cleaner to read.
99
- //
100
- // We can't do this in top N mode as the series name uses the row
101
- // values instead of the aggregate function.
102
- if ( s . yAxis === yAxis ) {
103
- return {
104
- ...s ,
105
- seriesName : formattedYAxes [ i ] ?? yAxis ,
106
- } ;
107
- }
108
- return s ;
109
- } ) ;
110
- } ) ;
111
- return {
112
- data,
113
- error : shouldUsePreviousResults
114
- ? previousTimeseriesResult . error
115
- : timeseriesResult . error ,
116
- loading : shouldUsePreviousResults
117
- ? previousTimeseriesResult . isPending
118
- : timeseriesResult . isPending ,
119
- } ;
120
- } , [
121
- timeseriesResult . isPending ,
122
- timeseriesResult . error ,
123
- timeseriesResult . data ,
124
- canUsePreviousResults ,
125
- yAxes ,
126
- previousTimeseriesResult . error ,
127
- previousTimeseriesResult . isPending ,
128
- previousTimeseriesResult . data ,
129
- formattedYAxes ,
130
- ] ) ;
131
-
132
- const { data, error, loading} = getSeries ( ) ;
133
- const { sampleCount, isSampled, dataScanned} = determineSeriesSampleCountAndIsSampled (
134
- data ,
135
- isTopN
136
- ) ;
137
-
138
64
const chartType = queryParts . chartType ?? determineDefaultChartType ( yAxes ) ;
139
65
140
66
const visualizationType =
141
67
chartType === ChartType . LINE ? 'line' : chartType === ChartType . AREA ? 'area' : 'bar' ;
142
68
143
- const chartInfo = {
144
- chartIcon : < IconGraph type = { visualizationType } /> ,
145
- chartType,
146
- yAxes,
147
- formattedYAxes,
148
- data,
149
- error,
150
- loading,
151
- } ;
69
+ const chartInfo : ChartInfo = useMemo ( ( ) => {
70
+ const series = yAxes . flatMap ( yAxis => timeseriesResult . data [ yAxis ] ?? [ ] ) ;
71
+ const samplingMeta = determineSeriesSampleCountAndIsSampled ( series , isTopN ) ;
72
+
73
+ return {
74
+ chartType,
75
+ confidence : combineConfidenceForSeries ( series ) ,
76
+ series,
77
+ timeseriesResult,
78
+ yAxis : yAxes [ 0 ] ! ,
79
+ dataScanned : samplingMeta . dataScanned ,
80
+ isSampled : samplingMeta . isSampled ,
81
+ sampleCount : samplingMeta . sampleCount ,
82
+ samplingMode : undefined ,
83
+ } ;
84
+ } , [ chartType , isTopN , timeseriesResult , yAxes ] ) ;
152
85
153
86
const organization = useOrganization ( ) ;
154
87
const { addToDashboard} = useAddCompareQueryToDashboard ( queryParts ) ;
@@ -161,29 +94,6 @@ export function MultiQueryModeChart({
161
94
</ Fragment >
162
95
) ;
163
96
164
- if ( chartInfo . loading ) {
165
- return (
166
- < Widget
167
- key = { index }
168
- height = { CHART_HEIGHT }
169
- Title = { Title }
170
- Visualization = { < TimeSeriesWidgetVisualization . LoadingPlaceholder /> }
171
- revealActions = "always"
172
- />
173
- ) ;
174
- }
175
- if ( chartInfo . error ) {
176
- return (
177
- < Widget
178
- key = { index }
179
- height = { CHART_HEIGHT }
180
- Title = { Title }
181
- Visualization = { < Widget . WidgetError error = { chartInfo . error } /> }
182
- revealActions = "always"
183
- />
184
- ) ;
185
- }
186
-
187
97
const items : MenuItemProps [ ] = [ ] ;
188
98
189
99
const project =
@@ -242,13 +152,6 @@ export function MultiQueryModeChart({
242
152
} ,
243
153
} ) ;
244
154
245
- const DataPlottableConstructor =
246
- chartInfo . chartType === ChartType . LINE
247
- ? Line
248
- : chartInfo . chartType === ChartType . AREA
249
- ? Area
250
- : Bars ;
251
-
252
155
return (
253
156
< Widget
254
157
key = { index }
@@ -261,12 +164,12 @@ export function MultiQueryModeChart({
261
164
>
262
165
< CompactSelect
263
166
triggerProps = { {
264
- icon : chartInfo . chartIcon ,
167
+ icon : < IconGraph type = { visualizationType } /> ,
265
168
borderless : true ,
266
169
showChevron : false ,
267
170
size : 'xs' ,
268
171
} }
269
- value = { chartInfo . chartType }
172
+ value = { chartType }
270
173
menuTitle = { t ( 'Type' ) }
271
174
options = { EXPLORE_CHART_TYPE_OPTIONS }
272
175
onChange = { option => {
@@ -306,26 +209,15 @@ export function MultiQueryModeChart({
306
209
) ,
307
210
] }
308
211
revealActions = "always"
309
- Visualization = {
310
- < TimeSeriesWidgetVisualization
311
- plottables = { chartInfo . data . map ( timeSeries => {
312
- return new DataPlottableConstructor (
313
- markDelayedData ( timeSeries , INGESTION_DELAY ) ,
314
- {
315
- color : isTimeSeriesOther ( timeSeries ) ? theme . chartOther : undefined ,
316
- stack : 'all' ,
317
- }
318
- ) ;
319
- } ) }
320
- />
321
- }
212
+ Visualization = { < ChartVisualization chartInfo = { chartInfo } /> }
322
213
Footer = {
323
214
< ConfidenceFooter
324
- sampleCount = { sampleCount }
325
- isSampled = { isSampled }
326
- confidence = { confidence }
327
- topEvents = { isTopN ? numSeries : undefined }
328
- dataScanned = { dataScanned }
215
+ sampleCount = { chartInfo . sampleCount }
216
+ isLoading = { chartInfo . timeseriesResult ?. isPending || false }
217
+ isSampled = { chartInfo . isSampled }
218
+ confidence = { chartInfo . confidence }
219
+ topEvents = { isTopN ? chartInfo . series . length : undefined }
220
+ dataScanned = { chartInfo . dataScanned }
329
221
/>
330
222
}
331
223
/>
0 commit comments