import {Fragment} from 'react'; import styled from '@emotion/styled'; import type {Location} from 'history'; import {SectionHeading} from 'sentry/components/charts/styles'; import EventVitals from 'sentry/components/events/eventVitals'; import Panel from 'sentry/components/panels/panel'; import Placeholder from 'sentry/components/placeholder'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import type {EventTransaction, Organization} from 'sentry/types'; import {generateQueryWithTag} from 'sentry/utils'; import type EventView from 'sentry/utils/discover/eventView'; import {formatTagKey} from 'sentry/utils/discover/fields'; import type { TraceFullDetailed, TraceSplitResults, } from 'sentry/utils/performance/quickTrace/types'; import {WEB_VITAL_DETAILS} from 'sentry/utils/performance/vitals/constants'; import type {UseApiQueryResult} from 'sentry/utils/queryClient'; import type RequestError from 'sentry/utils/requestError/requestError'; import Tags from 'sentry/views/discover/tags'; import {getTraceInfo} from '../traceDetails/utils'; type TraceFooterProps = { location: Location; organization: Organization; rootEventResults: UseApiQueryResult; traceEventView: EventView; traces: TraceSplitResults | null; }; function NoWebVitals() { return (
{t('WebVitals')} {[ WEB_VITAL_DETAILS['measurements.cls'], WEB_VITAL_DETAILS['measurements.lcp'], WEB_VITAL_DETAILS['measurements.ttfb'], WEB_VITAL_DETAILS['measurements.fcp'], WEB_VITAL_DETAILS['measurements.fid'], ].map(detail => (
{detail.name}
{' \u2014 '}
))}
); } function TraceFooterLoading() { return (
{t('WebVitals')}
{t('Tag Summary')}
); } export function TraceFooter(props: TraceFooterProps) { if (!props.traces) { return ; } const {data: rootEvent} = props.rootEventResults; const {transactions, orphan_errors} = props.traces; const traceInfo = getTraceInfo(transactions, orphan_errors); const orphanErrorsCount = traceInfo.trailingOrphansCount ?? 0; const transactionsCount = traceInfo.transactions.size ?? 0; const totalNumOfEvents = transactionsCount + orphanErrorsCount; const webVitals = Object.keys(rootEvent?.measurements ?? {}) .filter(name => Boolean(WEB_VITAL_DETAILS[`measurements.${name}`])) .sort(); return rootEvent ? ( {webVitals.length > 0 ? (
) : ( )}
{ const url = props.traceEventView.getResultsViewUrlTarget( props.organization.slug, false ); url.query = generateQueryWithTag(url.query, { key: formatTagKey(key), value, }); return url; }} totalValues={totalNumOfEvents} eventView={props.traceEventView} organization={props.organization} location={props.location} />
) : null; } const TraceFooterWrapper = styled('div')` display: flex; gap: ${space(2)}; margin-top: ${space(2)}; `; const StyledPlaceholderTag = styled(Placeholder)` border-radius: ${p => p.theme.borderRadius}; height: 16px; margin-bottom: ${space(1.5)}; `; const StyledPlaceholderTagTitle = styled(Placeholder)` width: 100px; height: 12px; margin-bottom: ${space(0.5)}; `; const StyledPlaceholderVital = styled(StyledPlaceholderTagTitle)` width: 100%; height: 50px; margin-bottom: ${space(0.5)}; `; const StyledPanel = styled(Panel)` padding: ${space(1)} ${space(1.5)}; margin-bottom: ${space(1)}; width: 100%; `; const WebVitalsWrapper = styled('div')` display: flex; align-items: center; flex-direction: column; `;