Skip to content

Commit

Permalink
chore(ourlogs): Separate explore page from logs page (#83860)
Browse files Browse the repository at this point in the history
We want to also add logs to the explore page under a separate tab, so
move the existing explore body into a separate file
  • Loading branch information
colin-sentry authored Jan 22, 2025
1 parent dd2cd20 commit a06fca2
Show file tree
Hide file tree
Showing 3 changed files with 316 additions and 285 deletions.
299 changes: 15 additions & 284 deletions static/app/views/explore/content.tsx
Original file line number Diff line number Diff line change
@@ -1,82 +1,29 @@
import {useCallback, useMemo} from 'react';
import styled from '@emotion/styled';
import * as Sentry from '@sentry/react';
import {useCallback} from 'react';

import Feature from 'sentry/components/acl/feature';
import {Alert} from 'sentry/components/alert';
import FeatureBadge from 'sentry/components/badge/featureBadge';
import {Button} from 'sentry/components/button';
import ButtonBar from 'sentry/components/buttonBar';
import FeedbackWidgetButton from 'sentry/components/feedback/widget/feedbackWidgetButton';
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 PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter';
import {PageHeadingQuestionTooltip} from 'sentry/components/pageHeadingQuestionTooltip';
import {
EAPSpanSearchQueryBuilder,
SpanSearchQueryBuilder,
} from 'sentry/components/performance/spanSearchQueryBuilder';
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Organization} from 'sentry/types/organization';
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 {useLocation} from 'sentry/utils/useLocation';
import {useNavigate} from 'sentry/utils/useNavigate';
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} from 'sentry/views/explore/utils';
import {SpansTabContent} from 'sentry/views/explore/spans/spansTab';
import {limitMaxPickableDays} from 'sentry/views/explore/utils';

function ExploreContentImpl() {
const location = useLocation();
const navigate = useNavigate();
export function ExploreContent() {
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 {defaultPeriod, maxPickableDays, relativeOptions} = limitMaxPickableDays(
organization!
);

const location = useLocation();
const navigate = useNavigate();
const switchToOldTraceExplorer = useCallback(() => {
navigate({
...location,
Expand All @@ -87,55 +34,8 @@ function ExploreContentImpl() {
});
}, [location, navigate]);

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 ?? '';

const {defaultPeriod, maxPickableDays, relativeOptions} =
limitMaxPickableDays(organization);

return (
<SentryDocumentTitle title={t('Traces')} orgSlug={organization.slug}>
<SentryDocumentTitle title={t('Traces')} orgSlug={organization?.slug}>
<PageFiltersContainer maxPickableDays={maxPickableDays}>
<Layout.Page>
<Layout.Header>
Expand Down Expand Up @@ -168,182 +68,13 @@ function ExploreContentImpl() {
</ButtonBar>
</Layout.HeaderActions>
</Layout.Header>
<Body>
<TopSection>
<StyledPageFilterBar condensed>
<ProjectPageFilter />
<EnvironmentPageFilter />
<DatePageFilter
defaultPeriod={defaultPeriod}
maxPickableDays={maxPickableDays}
relativeOptions={({arbitraryOptions}) => ({
...arbitraryOptions,
...relativeOptions,
})}
/>
</StyledPageFilterBar>
{dataset === DiscoverDatasets.SPANS_INDEXED ? (
<SpanSearchQueryBuilder
projects={selection.projects}
initialQuery={query}
onSearch={setQuery}
searchSource="explore"
/>
) : (
<EAPSpanSearchQueryBuilder
projects={selection.projects}
initialQuery={query}
onSearch={setQuery}
searchSource="explore"
getFilterTokenWarning={
mode === Mode.SAMPLES
? key => {
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}
/>
)}
</TopSection>
<ExploreToolbar extras={toolbarExtras} />
<MainSection fullWidth>
{(tableError || chartError) && (
<Alert type="error" showIcon>
{tableError || chartError}
</Alert>
)}
<ExploreCharts
canUsePreviousResults={canUsePreviousResults}
confidences={confidences}
query={query}
timeseriesResult={timeseriesResult}
/>
<ExploreTables
aggregatesTableResult={aggregatesTableResult}
spansTableResult={spansTableResult}
tracesTableResult={tracesTableResult}
confidences={confidences}
samplesTab={samplesTab}
setSamplesTab={setSamplesTab}
/>
</MainSection>
</Body>
<SpansTabContent
defaultPeriod={defaultPeriod}
maxPickableDays={maxPickableDays}
relativeOptions={relativeOptions}
/>
</Layout.Page>
</PageFiltersContainer>
</SentryDocumentTitle>
);
}

function ExploreTagsProvider({children}: any) {
const dataset = useExploreDataset();

return (
<SpanTagsProvider dataset={dataset} enabled>
{children}
</SpanTagsProvider>
);
}

export function ExploreContent() {
Sentry.setTag('explore.visited', 'yes');

return (
<PageParamsProvider>
<ExploreTagsProvider>
<ExploreContentImpl />
</ExploreTagsProvider>
</PageParamsProvider>
);
}

type MaxPickableDays = 7 | 14 | 30;
type DefaultPeriod = '7d' | '14d' | '30d';

function limitMaxPickableDays(organization: Organization): {
defaultPeriod: DefaultPeriod;
maxPickableDays: MaxPickableDays;
relativeOptions: Record<string, React.ReactNode>;
} {
const defaultPeriods: Record<MaxPickableDays, DefaultPeriod> = {
7: '7d',
14: '14d',
30: '30d',
};

const relativeOptions: [DefaultPeriod, React.ReactNode][] = [
['7d', t('Last 7 days')],
['14d', t('Last 14 days')],
['30d', t('Last 30 days')],
];

const maxPickableDays: MaxPickableDays = organization.features.includes(
'visibility-explore-range-high'
)
? 30
: organization.features.includes('visibility-explore-range-medium')
? 14
: 7;
const defaultPeriod: DefaultPeriod = defaultPeriods[maxPickableDays];

const index = relativeOptions.findIndex(([period, _]) => period === defaultPeriod) + 1;
const enabledOptions = relativeOptions.slice(0, index);

return {
defaultPeriod,
maxPickableDays,
relativeOptions: {
'1h': t('Last hour'),
'24h': t('Last 24 hours'),
...Object.fromEntries(enabledOptions),
},
};
}

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;
`;
Loading

0 comments on commit a06fca2

Please sign in to comment.