import {useMemo} from 'react'; import styled from '@emotion/styled'; import * as Sentry from '@sentry/react'; import Alert from 'sentry/components/alert'; import * as Layout from 'sentry/components/layouts/thirds'; import {DatePageFilter} from 'sentry/components/organizations/datePageFilter'; import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter'; import PageFilterBar from 'sentry/components/organizations/pageFilterBar'; import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter'; import { EAPSpanSearchQueryBuilder, SpanSearchQueryBuilder, } from 'sentry/components/performance/spanSearchQueryBuilder'; import {t} from 'sentry/locale'; import {space} from 'sentry/styles/space'; import {defined} from 'sentry/utils'; import {dedupeArray} from 'sentry/utils/dedupeArray'; import {DiscoverDatasets} from 'sentry/utils/discover/types'; import { type AggregationKey, ALLOWED_EXPLORE_VISUALIZE_AGGREGATES, } from 'sentry/utils/fields'; import useOrganization from 'sentry/utils/useOrganization'; import usePageFilters from 'sentry/utils/usePageFilters'; import {ExploreCharts} from 'sentry/views/explore/charts'; import { PageParamsProvider, useExploreDataset, useExploreMode, useExploreQuery, useExploreVisualizes, useSetExploreQuery, } from 'sentry/views/explore/contexts/pageParamsContext'; import {Mode} from 'sentry/views/explore/contexts/pageParamsContext/mode'; import { SpanTagsProvider, useSpanTags, } from 'sentry/views/explore/contexts/spanTagsContext'; import {useExploreAggregatesTable} from 'sentry/views/explore/hooks/useExploreAggregatesTable'; import {useExploreSpansTable} from 'sentry/views/explore/hooks/useExploreSpansTable'; import {useExploreTimeseries} from 'sentry/views/explore/hooks/useExploreTimeseries'; import {useExploreTracesTable} from 'sentry/views/explore/hooks/useExploreTracesTable'; import {Tab, useTab} from 'sentry/views/explore/hooks/useTab'; import {ExploreTables} from 'sentry/views/explore/tables'; import {ExploreToolbar} from 'sentry/views/explore/toolbar'; import { combineConfidenceForSeries, type DefaultPeriod, type MaxPickableDays, } from 'sentry/views/explore/utils'; export type SpanTabProps = { defaultPeriod: DefaultPeriod; maxPickableDays: MaxPickableDays; relativeOptions: Record; }; export function SpansTabContentImpl({ defaultPeriod, maxPickableDays, relativeOptions, }: SpanTabProps) { const organization = useOrganization(); const {selection} = usePageFilters(); const dataset = useExploreDataset(); const mode = useExploreMode(); const visualizes = useExploreVisualizes(); const [samplesTab, setSamplesTab] = useTab(); const numberTags = useSpanTags('number'); const stringTags = useSpanTags('string'); const query = useExploreQuery(); const setQuery = useSetExploreQuery(); const toolbarExtras = organization?.features?.includes('visibility-explore-dataset') ? ['dataset toggle' as const] : []; const queryType: 'aggregate' | 'samples' | 'traces' = mode === Mode.AGGREGATE ? 'aggregate' : samplesTab === Tab.TRACE ? 'traces' : 'samples'; const limit = 25; const aggregatesTableResult = useExploreAggregatesTable({ query, limit, enabled: queryType === 'aggregate', }); const spansTableResult = useExploreSpansTable({ query, limit, enabled: queryType === 'samples', }); const tracesTableResult = useExploreTracesTable({ query, enabled: queryType === 'traces', }); const {timeseriesResult, canUsePreviousResults} = useExploreTimeseries({query}); const confidences = useMemo( () => visualizes.map(visualize => { const dedupedYAxes = dedupeArray(visualize.yAxes); const series = dedupedYAxes .flatMap(yAxis => timeseriesResult.data[yAxis]) .filter(defined); return combineConfidenceForSeries(series); }), [timeseriesResult.data, visualizes] ); const tableError = queryType === 'aggregate' ? aggregatesTableResult.result.error?.message ?? '' : queryType === 'traces' ? tracesTableResult.result.error?.message ?? '' : spansTableResult.result.error?.message ?? ''; const chartError = timeseriesResult.error?.message ?? ''; return ( ({ ...arbitraryOptions, ...relativeOptions, })} /> {dataset === DiscoverDatasets.SPANS_INDEXED ? ( ) : ( { if ( ALLOWED_EXPLORE_VISUALIZE_AGGREGATES.includes(key as AggregationKey) ) { return t( "This key won't affect the results because samples mode does not support aggregate functions" ); } return undefined; } : undefined } supportedAggregates={ALLOWED_EXPLORE_VISUALIZE_AGGREGATES} numberTags={numberTags} stringTags={stringTags} /> )} {(tableError || chartError) && ( {tableError || chartError} )} ); } function ExploreTagsProvider({children}: any) { const dataset = useExploreDataset(); return ( {children} ); } export function SpansTabContent(props: SpanTabProps) { Sentry.setTag('explore.visited', 'yes'); return ( ); } const Body = styled(Layout.Body)` gap: ${space(2)}; @media (min-width: ${p => p.theme.breakpoints.medium}) { grid-template-columns: 300px minmax(100px, auto); gap: ${space(2)}; } @media (min-width: ${p => p.theme.breakpoints.xxlarge}) { grid-template-columns: 400px minmax(100px, auto); } `; const TopSection = styled('div')` display: grid; gap: ${space(2)}; grid-column: 1/3; margin-bottom: ${space(2)}; @media (min-width: ${p => p.theme.breakpoints.large}) { grid-template-columns: minmax(300px, auto) 1fr; margin-bottom: 0; } @media (min-width: ${p => p.theme.breakpoints.xxlarge}) { grid-template-columns: minmax(400px, auto) 1fr; } `; const MainSection = styled(Layout.Main)` grid-column: 2/3; `; const StyledPageFilterBar = styled(PageFilterBar)` width: auto; `;