11import { useTheme } from '@emotion/react' ;
22import styled from '@emotion/styled' ;
33
4+ import Tag from 'sentry/components/badge/tag' ;
45import { DateTime } from 'sentry/components/dateTime' ;
56import Duration from 'sentry/components/duration' ;
67import type { GridColumnOrder } from 'sentry/components/gridEditable' ;
78import GridEditable from 'sentry/components/gridEditable' ;
9+ import ExternalLink from 'sentry/components/links/externalLink' ;
810import Link from 'sentry/components/links/link' ;
11+ import Placeholder from 'sentry/components/placeholder' ;
912import { Tooltip } from 'sentry/components/tooltip' ;
1013import { t , tct } from 'sentry/locale' ;
1114import { space } from 'sentry/styles/space' ;
1215import { getShortEventId } from 'sentry/utils/events' ;
13- import type { UptimeCheck } from 'sentry/views/alerts/rules/uptime/types' ;
16+ import { MutableSearch } from 'sentry/utils/tokenizeSearch' ;
17+ import type { UptimeCheck , UptimeRule } from 'sentry/views/alerts/rules/uptime/types' ;
18+ import { useEAPSpans } from 'sentry/views/insights/common/queries/useDiscover' ;
1419import {
1520 reasonToText ,
1621 statusToText ,
@@ -19,6 +24,7 @@ import {
1924
2025type Props = {
2126 uptimeChecks : UptimeCheck [ ] ;
27+ uptimeRule : UptimeRule ;
2228} ;
2329
2430/**
@@ -27,7 +33,28 @@ type Props = {
2733 */
2834const EMPTY_TRACE = '00000000000000000000000000000000' ;
2935
30- export function UptimeChecksGrid ( { uptimeChecks} : Props ) {
36+ export function UptimeChecksGrid ( { uptimeRule, uptimeChecks} : Props ) {
37+ const traceIds = uptimeChecks ?. map ( check => check . traceId ) ?? [ ] ;
38+
39+ const { data : spanCounts , isPending : spanCountLoading } = useEAPSpans (
40+ {
41+ limit : 10 ,
42+ enabled : traceIds . length > 0 ,
43+ search : new MutableSearch ( '' ) . addDisjunctionFilterValues ( 'trace' , traceIds ) ,
44+ fields : [ 'trace' , 'count()' ] ,
45+ } ,
46+ 'uptime_checks'
47+ ) ;
48+
49+ const traceSpanCounts = spanCountLoading
50+ ? undefined
51+ : Object . fromEntries (
52+ traceIds . map ( traceId => [
53+ traceId ,
54+ Number ( spanCounts . find ( row => row . trace === traceId ) ?. [ 'count()' ] ?? 0 ) ,
55+ ] )
56+ ) ;
57+
3158 return (
3259 < GridEditable
3360 emptyMessage = { t ( 'No matching uptime checks found' ) }
@@ -44,7 +71,12 @@ export function UptimeChecksGrid({uptimeChecks}: Props) {
4471 grid = { {
4572 renderHeadCell : ( col : GridColumnOrder ) => < Cell > { col . name } </ Cell > ,
4673 renderBodyCell : ( column , dataRow ) => (
47- < CheckInBodyCell column = { column } check = { dataRow } />
74+ < CheckInBodyCell
75+ column = { column }
76+ uptimeRule = { uptimeRule }
77+ check = { dataRow }
78+ spanCount = { traceSpanCounts ?. [ dataRow . traceId ] }
79+ />
4880 ) ,
4981 } }
5082 />
@@ -54,9 +86,13 @@ export function UptimeChecksGrid({uptimeChecks}: Props) {
5486function CheckInBodyCell ( {
5587 check,
5688 column,
89+ spanCount,
90+ uptimeRule,
5791} : {
5892 check : UptimeCheck ;
5993 column : GridColumnOrder < keyof UptimeCheck > ;
94+ spanCount : number | undefined ;
95+ uptimeRule : UptimeRule ;
6096} ) {
6197 const theme = useTheme ( ) ;
6298
@@ -112,15 +148,51 @@ function CheckInBodyCell({
112148 </ Cell >
113149 ) ;
114150 }
115- case 'traceId' :
151+ case 'traceId' : {
116152 if ( traceId === EMPTY_TRACE ) {
117153 return < Cell /> ;
118154 }
155+
156+ const learnMore = (
157+ < ExternalLink href = "https://docs.sentry.io/product/alerts/uptime-monitoring/uptime-tracing/" />
158+ ) ;
159+
160+ const badge =
161+ spanCount === undefined ? (
162+ < Placeholder height = "20px" width = "70px" />
163+ ) : spanCount === 0 ? (
164+ < Tag
165+ type = "default"
166+ tooltipProps = { { isHoverable : true } }
167+ tooltipText = {
168+ uptimeRule . traceSampling
169+ ? tct (
170+ 'No spans found in this trace. Configure your SDKs to see correlated spans across services. [learnMore:Learn more].' ,
171+ { learnMore}
172+ )
173+ : tct (
174+ 'Span sampling is disabled. Enable sampling to collect trace data. [learnMore:Learn more].' ,
175+ { learnMore}
176+ )
177+ }
178+ >
179+ { t ( '0 spans' ) }
180+ </ Tag >
181+ ) : (
182+ < Tag type = "info" > { t ( '%s spans' , spanCount ) } </ Tag >
183+ ) ;
184+
119185 return (
120- < LinkCell to = { `/performance/trace/${ traceId } /` } >
121- { getShortEventId ( String ( traceId ) ) }
122- </ LinkCell >
186+ < TraceCell >
187+ { spanCount ? (
188+ < Link to = { `/performance/trace/${ traceId } /` } > { getShortEventId ( traceId ) } </ Link >
189+ ) : (
190+ getShortEventId ( traceId )
191+ ) }
192+ { badge }
193+ </ TraceCell >
123194 ) ;
195+ }
124196 default :
125197 return < Cell > { check [ column . key ] } </ Cell > ;
126198 }
@@ -139,9 +211,8 @@ const TimeCell = styled(Cell)`
139211 text-decoration-style: dotted;
140212` ;
141213
142- const LinkCell = styled ( Link ) `
143- text-decoration: underline;
144- text-decoration-color: ${ p => p . theme . subText } ;
145- cursor: pointer;
146- text-decoration-style: dotted;
214+ const TraceCell = styled ( Cell ) `
215+ display: grid;
216+ grid-template-columns: 65px auto;
217+ gap: ${ space ( 1 ) } ;
147218` ;
0 commit comments