@@ -7,9 +7,11 @@ import {t} from 'sentry/locale';
7
7
import type { Event , Project } from 'sentry/types' ;
8
8
import { useRelativeDateTime } from 'sentry/utils/profiling/hooks/useRelativeDateTime' ;
9
9
import { useApiQuery } from 'sentry/utils/queryClient' ;
10
+ import { MutableSearch } from 'sentry/utils/tokenizeSearch' ;
10
11
import { useLocation } from 'sentry/utils/useLocation' ;
11
12
import useOrganization from 'sentry/utils/useOrganization' ;
12
13
import { spanDetailsRouteWithQuery } from 'sentry/views/performance/transactionSummary/transactionSpans/spanDetails/utils' ;
14
+ import { useSpanMetrics } from 'sentry/views/starfish/queries/useSpanMetrics' ;
13
15
14
16
import { EventRegressionTable } from './eventRegressionTable' ;
15
17
@@ -26,6 +28,7 @@ interface SpanDiff {
26
28
27
29
interface UseFetchAdvancedAnalysisProps {
28
30
breakpoint : string ;
31
+ enabled : boolean ;
29
32
end : string ;
30
33
projectId : string ;
31
34
start : string ;
@@ -38,6 +41,7 @@ function useFetchAdvancedAnalysis({
38
41
end,
39
42
breakpoint,
40
43
projectId,
44
+ enabled,
41
45
} : UseFetchAdvancedAnalysisProps ) {
42
46
const organization = useOrganization ( ) ;
43
47
return useApiQuery < SpanDiff [ ] > (
@@ -57,6 +61,7 @@ function useFetchAdvancedAnalysis({
57
61
{
58
62
staleTime : 60000 ,
59
63
retry : false ,
64
+ enabled,
60
65
}
61
66
) ;
62
67
}
@@ -74,6 +79,9 @@ interface AggregateSpanDiffProps {
74
79
function AggregateSpanDiff ( { event, project} : AggregateSpanDiffProps ) {
75
80
const location = useLocation ( ) ;
76
81
const organization = useOrganization ( ) ;
82
+ const isSpansOnly = organization . features . includes (
83
+ 'statistical-detectors-rca-spans-only'
84
+ ) ;
77
85
78
86
const [ causeType , setCauseType ] = useState < 'duration' | 'throughput' > ( 'duration' ) ;
79
87
@@ -85,17 +93,83 @@ function AggregateSpanDiff({event, project}: AggregateSpanDiffProps) {
85
93
relativeDays : 7 ,
86
94
retentionDays : 30 ,
87
95
} ) ;
88
- const { data, isLoading, isError} = useFetchAdvancedAnalysis ( {
96
+
97
+ const {
98
+ data : rcaData ,
99
+ isLoading : isRcaLoading ,
100
+ isError : isRcaError ,
101
+ } = useFetchAdvancedAnalysis ( {
89
102
transaction,
90
103
start : ( start as Date ) . toISOString ( ) ,
91
104
end : ( end as Date ) . toISOString ( ) ,
92
105
breakpoint : breakpointTimestamp ,
93
106
projectId : project . id ,
107
+ enabled : ! isSpansOnly ,
108
+ } ) ;
109
+
110
+ // Initialize the search query with has:span.group because only
111
+ // specific operations have their span.group recorded in the span
112
+ // metrics dataset
113
+ const search = new MutableSearch ( 'has:span.group' ) ;
114
+ search . addFilterValue ( 'transaction' , transaction ) ;
115
+
116
+ const {
117
+ data : spansData ,
118
+ isLoading : isSpansDataLoading ,
119
+ isError : isSpansDataError ,
120
+ } = useSpanMetrics ( {
121
+ search,
122
+ fields : [
123
+ 'span.op' ,
124
+ 'any(span.description)' ,
125
+ 'span.group' ,
126
+ `regression_score(span.self_time,${ breakpoint } )` ,
127
+ `avg_by_timestamp(span.self_time,less,${ breakpoint } )` ,
128
+ `avg_by_timestamp(span.self_time,greater,${ breakpoint } )` ,
129
+ `epm_by_timestamp(less,${ breakpoint } )` ,
130
+ `epm_by_timestamp(greater,${ breakpoint } )` ,
131
+ ] ,
132
+ sorts : [ { field : `regression_score(span.self_time,${ breakpoint } )` , kind : 'desc' } ] ,
133
+ limit : 10 ,
134
+ enabled : isSpansOnly ,
135
+ referrer : 'api.performance.transactions.statistical-detector-root-cause-analysis' ,
94
136
} ) ;
95
137
96
138
const tableData = useMemo ( ( ) => {
139
+ if ( isSpansOnly ) {
140
+ return spansData ?. map ( row => {
141
+ const commonProps = {
142
+ operation : row [ 'span.op' ] ,
143
+ group : row [ 'span.group' ] ,
144
+ description : row [ 'any(span.description)' ] || undefined ,
145
+ } ;
146
+
147
+ if ( causeType === 'throughput' ) {
148
+ const throughputBefore = row [ `epm_by_timestamp(less,${ breakpoint } )` ] ;
149
+ const throughputAfter = row [ `epm_by_timestamp(greater,${ breakpoint } )` ] ;
150
+ return {
151
+ ...commonProps ,
152
+ throughputBefore,
153
+ throughputAfter,
154
+ percentageChange : throughputAfter / throughputBefore - 1 ,
155
+ } ;
156
+ }
157
+
158
+ const durationBefore =
159
+ row [ `avg_by_timestamp(span.self_time,less,${ breakpoint } )` ] / 1e3 ;
160
+ const durationAfter =
161
+ row [ `avg_by_timestamp(span.self_time,greater,${ breakpoint } )` ] / 1e3 ;
162
+ return {
163
+ ...commonProps ,
164
+ durationBefore,
165
+ durationAfter,
166
+ percentageChange : durationAfter / durationBefore - 1 ,
167
+ } ;
168
+ } ) ;
169
+ }
170
+
97
171
return (
98
- data ?. map ( row => {
172
+ rcaData ?. map ( row => {
99
173
if ( causeType === 'throughput' ) {
100
174
return {
101
175
operation : row . span_op ,
@@ -106,6 +180,7 @@ function AggregateSpanDiff({event, project}: AggregateSpanDiffProps) {
106
180
percentageChange : row . spm_after / row . spm_before - 1 ,
107
181
} ;
108
182
}
183
+
109
184
return {
110
185
operation : row . span_op ,
111
186
group : row . span_group ,
@@ -116,7 +191,7 @@ function AggregateSpanDiff({event, project}: AggregateSpanDiffProps) {
116
191
} ;
117
192
} ) || [ ]
118
193
) ;
119
- } , [ data , causeType ] ) ;
194
+ } , [ isSpansOnly , rcaData , spansData , causeType , breakpoint ] ) ;
120
195
121
196
const tableOptions = useMemo ( ( ) => {
122
197
return {
@@ -153,7 +228,7 @@ function AggregateSpanDiff({event, project}: AggregateSpanDiffProps) {
153
228
onChange = { setCauseType }
154
229
>
155
230
< SegmentedControl . Item key = "duration" >
156
- { t ( 'Duration (P95)' ) }
231
+ { isSpansOnly ? t ( 'Average Duration' ) : t ( 'Duration (P95)' ) }
157
232
</ SegmentedControl . Item >
158
233
< SegmentedControl . Item key = "throughput" >
159
234
{ t ( 'Throughput' ) }
@@ -165,9 +240,8 @@ function AggregateSpanDiff({event, project}: AggregateSpanDiffProps) {
165
240
causeType = { causeType }
166
241
columns = { ADDITIONAL_COLUMNS }
167
242
data = { tableData }
168
- isLoading = { isLoading }
169
- isError = { isError }
170
- // renderers={renderers}
243
+ isLoading = { isSpansOnly ? isSpansDataLoading : isRcaLoading }
244
+ isError = { isSpansOnly ? isSpansDataError : isRcaError }
171
245
options = { tableOptions }
172
246
/>
173
247
</ EventDataSection >
0 commit comments