123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- import styled from '@emotion/styled';
- import omit from 'lodash/omit';
- import Breadcrumbs from 'sentry/components/breadcrumbs';
- import ButtonBar from 'sentry/components/buttonBar';
- import ErrorBoundary from 'sentry/components/errorBoundary';
- import FeedbackWidgetButton from 'sentry/components/feedback/widget/feedbackWidgetButton';
- import * as Layout from 'sentry/components/layouts/thirds';
- import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
- import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
- import {t} from 'sentry/locale';
- import {space} from 'sentry/styles/space';
- import {DurationUnit} from 'sentry/utils/discover/fields';
- import {DiscoverDatasets} from 'sentry/utils/discover/types';
- import {PageAlert, PageAlertProvider} from 'sentry/utils/performance/contexts/pageAlert';
- import {useLocation} from 'sentry/utils/useLocation';
- import useOrganization from 'sentry/utils/useOrganization';
- import useRouter from 'sentry/utils/useRouter';
- import {SpanSamplesPanel} from 'sentry/views/performance/mobile/components/spanSamplesPanel';
- import {
- ScreenCharts,
- YAxis,
- } from 'sentry/views/performance/mobile/screenload/screenLoadSpans/charts';
- import {ScreenLoadEventSamples} from 'sentry/views/performance/mobile/screenload/screenLoadSpans/eventSamples';
- import {MetricsRibbon} from 'sentry/views/performance/mobile/screenload/screenLoadSpans/metricsRibbon';
- import {ScreenLoadSpansTable} from 'sentry/views/performance/mobile/screenload/screenLoadSpans/table';
- import {
- MobileCursors,
- MobileSortKeys,
- } from 'sentry/views/performance/mobile/screenload/screens/constants';
- import {PlatformSelector} from 'sentry/views/performance/mobile/screenload/screens/platformSelector';
- import useCrossPlatformProject from 'sentry/views/performance/mobile/useCrossPlatformProject';
- import {ModulePageProviders} from 'sentry/views/performance/modulePageProviders';
- import {useModuleBreadcrumbs} from 'sentry/views/performance/utils/useModuleBreadcrumbs';
- import {
- PRIMARY_RELEASE_ALIAS,
- ReleaseComparisonSelector,
- SECONDARY_RELEASE_ALIAS,
- } from 'sentry/views/starfish/components/releaseSelector';
- import {ModuleName} from 'sentry/views/starfish/types';
- import {QueryParameterNames} from 'sentry/views/starfish/views/queryParameters';
- type Query = {
- primaryRelease: string;
- project: string;
- secondaryRelease: string;
- spanGroup: string;
- transaction: string;
- [QueryParameterNames.SPANS_SORT]: string;
- spanDescription?: string;
- };
- function ScreenLoadSpans() {
- const location = useLocation<Query>();
- const organization = useOrganization();
- const router = useRouter();
- const {isProjectCrossPlatform} = useCrossPlatformProject();
- const crumbs = useModuleBreadcrumbs('screen_load');
- const {
- spanGroup,
- primaryRelease,
- secondaryRelease,
- transaction: transactionName,
- spanDescription,
- } = location.query;
- return (
- <Layout.Page>
- <PageAlertProvider>
- <Layout.Header>
- <Layout.HeaderContent>
- <Breadcrumbs
- crumbs={[
- ...crumbs,
- {
- label: t('Screen Summary'),
- },
- ]}
- />
- <HeaderWrapper>
- <Layout.Title>{transactionName}</Layout.Title>
- {organization.features.includes('insights-initial-modules') &&
- isProjectCrossPlatform && <PlatformSelector />}
- </HeaderWrapper>
- </Layout.HeaderContent>
- <Layout.HeaderActions>
- <ButtonBar gap={1}>
- <FeedbackWidgetButton />
- </ButtonBar>
- </Layout.HeaderActions>
- </Layout.Header>
- <Layout.Body>
- <Layout.Main fullWidth>
- <PageAlert />
- <Container>
- <FilterContainer>
- <PageFilterBar condensed>
- <DatePageFilter />
- </PageFilterBar>
- <ReleaseComparisonSelector />
- </FilterContainer>
- <MetricsRibbon
- dataset={DiscoverDatasets.METRICS}
- filters={[
- 'event.type:transaction',
- 'transaction.op:ui.load',
- `transaction:${transactionName}`,
- ]}
- fields={[
- `avg_if(measurements.time_to_initial_display,release,${primaryRelease})`,
- `avg_if(measurements.time_to_initial_display,release,${secondaryRelease})`,
- `avg_if(measurements.time_to_full_display,release,${primaryRelease})`,
- `avg_if(measurements.time_to_full_display,release,${secondaryRelease})`,
- 'count()',
- ]}
- blocks={[
- {
- unit: DurationUnit.MILLISECOND,
- dataKey: `avg_if(measurements.time_to_initial_display,release,${primaryRelease})`,
- title: t('Avg TTID (%s)', PRIMARY_RELEASE_ALIAS),
- },
- {
- unit: DurationUnit.MILLISECOND,
- dataKey: `avg_if(measurements.time_to_initial_display,release,${secondaryRelease})`,
- title: t('Avg TTID (%s)', SECONDARY_RELEASE_ALIAS),
- },
- {
- unit: DurationUnit.MILLISECOND,
- dataKey: `avg_if(measurements.time_to_full_display,release,${primaryRelease})`,
- title: t('Avg TTFD (%s)', PRIMARY_RELEASE_ALIAS),
- },
- {
- unit: DurationUnit.MILLISECOND,
- dataKey: `avg_if(measurements.time_to_full_display,release,${secondaryRelease})`,
- title: t('Avg TTFD (%s)', SECONDARY_RELEASE_ALIAS),
- },
- {
- unit: 'count',
- dataKey: 'count()',
- title: t('Total Count'),
- },
- ]}
- referrer="api.starfish.mobile-screen-totals"
- />
- </Container>
- <ErrorBoundary mini>
- <ScreenCharts
- yAxes={[YAxis.TTID, YAxis.TTFD, YAxis.COUNT]}
- additionalFilters={[`transaction:${transactionName}`]}
- chartHeight={120}
- />
- <SampleContainer>
- <SampleContainerItem>
- <ScreenLoadEventSamples
- release={primaryRelease}
- sortKey={MobileSortKeys.RELEASE_1_EVENT_SAMPLE_TABLE}
- cursorName={MobileCursors.RELEASE_1_EVENT_SAMPLE_TABLE}
- transaction={transactionName}
- showDeviceClassSelector
- />
- </SampleContainerItem>
- <SampleContainerItem>
- <ScreenLoadEventSamples
- release={secondaryRelease}
- sortKey={MobileSortKeys.RELEASE_2_EVENT_SAMPLE_TABLE}
- cursorName={MobileCursors.RELEASE_2_EVENT_SAMPLE_TABLE}
- transaction={transactionName}
- />
- </SampleContainerItem>
- </SampleContainer>
- <ScreenLoadSpansTable
- transaction={transactionName}
- primaryRelease={primaryRelease}
- secondaryRelease={secondaryRelease}
- />
- {spanGroup && (
- <SpanSamplesPanel
- groupId={spanGroup}
- moduleName={ModuleName.SCREEN_LOAD}
- transactionName={transactionName}
- spanDescription={spanDescription}
- onClose={() => {
- router.replace({
- pathname: router.location.pathname,
- query: omit(
- router.location.query,
- 'spanGroup',
- 'transactionMethod'
- ),
- });
- }}
- />
- )}
- </ErrorBoundary>
- </Layout.Main>
- </Layout.Body>
- </PageAlertProvider>
- </Layout.Page>
- );
- }
- function PageWithProviders() {
- const location = useLocation<Query>();
- const {transaction} = location.query;
- return (
- <ModulePageProviders
- moduleName="screen_load"
- pageTitle={transaction}
- features="insights-initial-modules"
- >
- <ScreenLoadSpans />
- </ModulePageProviders>
- );
- }
- export default PageWithProviders;
- const Container = styled('div')`
- display: grid;
- grid-template-rows: 1fr 1fr;
- grid-template-columns: 1fr;
- column-gap: ${space(2)};
- @media (min-width: ${p => p.theme.breakpoints.large}) {
- grid-template-rows: auto;
- grid-template-columns: auto minmax(100px, max-content);
- }
- `;
- const FilterContainer = styled('div')`
- display: grid;
- column-gap: ${space(1)};
- grid-template-rows: auto;
- grid-template-columns: auto 1fr;
- `;
- const SampleContainer = styled('div')`
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- gap: ${space(2)};
- `;
- const SampleContainerItem = styled('div')`
- flex: 1;
- `;
- const HeaderWrapper = styled('div')`
- display: flex;
- `;
|