import {type Theme, useTheme} from '@emotion/react'; import styled from '@emotion/styled'; import {LinkButton} from 'sentry/components/button'; import ProjectBadge from 'sentry/components/idBadge/projectBadge'; import Link from 'sentry/components/links/link'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import {ROW_HEIGHT, ROW_PADDING} from 'sentry/components/performance/waterfall/constants'; import {RowRectangle} from 'sentry/components/performance/waterfall/rowBar'; import {pickBarColor} from 'sentry/components/performance/waterfall/utils'; import PerformanceDuration from 'sentry/components/performanceDuration'; import {Tooltip} from 'sentry/components/tooltip'; import {IconIssues} from 'sentry/icons'; import {t} from 'sentry/locale'; import type {DateString} from 'sentry/types'; import EventView from 'sentry/utils/discover/eventView'; import { generateEventSlug, generateLinkToEventInTraceView, } from 'sentry/utils/discover/urls'; import {getShortEventId} from 'sentry/utils/events'; import toPercent from 'sentry/utils/number/toPercent'; import Projects from 'sentry/utils/projects'; import {useLocation} from 'sentry/utils/useLocation'; import useOrganization from 'sentry/utils/useOrganization'; import usePageFilters from 'sentry/utils/usePageFilters'; import useProjects from 'sentry/utils/useProjects'; import {normalizeUrl} from 'sentry/utils/withDomainRequired'; import {getTraceDetailsUrl} from 'sentry/views/performance/traceDetails/utils'; import {transactionSummaryRouteWithQuery} from 'sentry/views/performance/transactionSummary/utils'; import {useTraceMeta} from '../newTraceDetails/traceApi/useTraceMeta'; import type {TraceResult} from './content'; import type {Field} from './data'; interface ProjectRendererProps { projectSlug: string; hideName?: boolean; } export function ProjectRenderer({projectSlug, hideName}: ProjectRendererProps) { const organization = useOrganization(); return ( {({projects}) => { const project = projects.find(p => p.slug === projectSlug); return ( ); }} ); } export const TraceBreakdownContainer = styled('div')` position: relative; display: flex; min-width: 150px; height: ${ROW_HEIGHT - 2 * ROW_PADDING}px; background-color: ${p => p.theme.gray100}; `; const RectangleTraceBreakdown = styled(RowRectangle)` position: relative; width: 100%; `; export function TraceBreakdownRenderer({trace}: {trace: TraceResult}) { const theme = useTheme(); return ( {trace.breakdowns.map(breakdown => { return ( ); })} ); } export function SpanBreakdownSliceRenderer({ trace, theme, sliceName, sliceStart, sliceEnd, }: { sliceEnd: number; sliceName: string | null; sliceStart: number; theme: Theme; trace: TraceResult; }) { const traceDuration = trace.end - trace.start; const sliceDuration = sliceEnd - sliceStart; if (sliceDuration <= 0) { return null; } const sliceColor = sliceName ? pickBarColor(sliceName) : theme.gray100; const slicePercent = toPercent(sliceDuration / traceDuration); const relativeSliceStart = sliceStart - trace.start; const sliceOffset = toPercent(relativeSliceStart / traceDuration); return (
{sliceName}
} containerDisplayMode="block" > {}} /> ); } interface SpanIdRendererProps { projectSlug: string; spanId: string; timestamp: string; traceId: string; transactionId: string; } export function SpanIdRenderer({ projectSlug, spanId, timestamp, traceId, transactionId, }: SpanIdRendererProps) { const location = useLocation(); const organization = useOrganization(); const target = generateLinkToEventInTraceView({ eventSlug: generateEventSlug({ id: transactionId, project: projectSlug, }), organization, location, eventView: EventView.fromLocation(location), dataRow: { id: transactionId, trace: traceId, timestamp, }, spanId, }); return {getShortEventId(spanId)}; } interface TraceIdRendererProps { traceId: string; timestamp?: DateString; transactionId?: string; } export function TraceIdRenderer({ traceId, timestamp, transactionId, }: TraceIdRendererProps) { const organization = useOrganization(); const {selection} = usePageFilters(); const stringOrNumberTimestamp = timestamp instanceof Date ? timestamp.toISOString() : timestamp ?? ''; const target = getTraceDetailsUrl( organization, traceId, { start: selection.datetime.start, end: selection.datetime.end, statsPeriod: selection.datetime.period, }, {}, stringOrNumberTimestamp, transactionId ); return {getShortEventId(traceId)}; } interface TransactionRendererProps { projectSlug: string; transaction: string; } export function TransactionRenderer({ projectSlug, transaction, }: TransactionRendererProps) { const location = useLocation(); const organization = useOrganization(); const {projects} = useProjects({slugs: [projectSlug]}); const target = transactionSummaryRouteWithQuery({ orgSlug: organization.slug, transaction, query: { ...location.query, query: undefined, }, projectID: String(projects[0]?.id ?? ''), }); return {transaction}; } export function TraceIssuesRenderer({trace}: {trace: TraceResult}) { const traceMeta = useTraceMeta(trace.trace); const organization = useOrganization(); const issueCount = !traceMeta.data ? undefined : traceMeta.data.errors + traceMeta.data.performance_issues; return ( } > {issueCount !== undefined ? ( issueCount ) : ( )} {issueCount === 100 && '+'} ); }