Skip to content

Commit 68f0a23

Browse files
authored
chore(preprod): add builds list analytics hook (#105679)
Add preprod builds list analytics hook
1 parent c1ec1c7 commit 68f0a23

File tree

5 files changed

+132
-4
lines changed

5 files changed

+132
-4
lines changed

static/app/utils/analytics/preprodBuildAnalyticsEvents.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type {PreprodBuildsDisplay} from 'sentry/components/preprod/preprodBuildsDisplay';
12
import type {Organization} from 'sentry/types/organization';
23

34
type BasePreprodBuildEvent = {
@@ -8,6 +9,11 @@ type BasePreprodBuildEvent = {
89
project_type?: string | null;
910
};
1011

12+
export type BuildListPageSource =
13+
| 'preprod_builds_list'
14+
| 'releases_mobile_builds_tab'
15+
| 'releases_details_preprod_builds';
16+
1117
export type PreprodBuildEventParameters = {
1218
'preprod.builds.compare.go_to_build_details': BasePreprodBuildEvent & {
1319
slot?: 'head' | 'base';
@@ -28,6 +34,18 @@ export type PreprodBuildEventParameters = {
2834
'preprod.builds.install_modal.opened': BasePreprodBuildEvent & {
2935
source: 'build_details_sidebar' | 'builds_table';
3036
};
37+
'preprod.builds.list.metadata': {
38+
build_count_on_page: number;
39+
datetime_selection: string;
40+
display: PreprodBuildsDisplay;
41+
has_search_query: boolean;
42+
is_empty: boolean;
43+
organization: Organization;
44+
page_source: BuildListPageSource;
45+
project_count: number;
46+
query_status: 'success' | 'error';
47+
cursor?: string | null;
48+
};
3149
'preprod.builds.release.build_row_clicked': BasePreprodBuildEvent;
3250
'preprod.releases.mobile-builds.tab-clicked': {
3351
organization: Organization;
@@ -37,6 +55,7 @@ export type PreprodBuildEventParameters = {
3755
type PreprodBuildAnalyticsKey = keyof PreprodBuildEventParameters;
3856

3957
export const preprodBuildEventMap: Record<PreprodBuildAnalyticsKey, string | null> = {
58+
'preprod.builds.list.metadata': 'Preprod Builds: List Metadata',
4059
'preprod.builds.release.build_row_clicked': 'Preprod Builds: Release Build Row Clicked',
4160
'preprod.builds.details.open_insights_sidebar':
4261
'Preprod Build Details: Insights Sidebar Opened',

static/app/views/preprod/buildList/buildList.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Flex} from '@sentry/scraps/layout';
33
import Feature from 'sentry/components/acl/feature';
44
import {LinkButton} from 'sentry/components/core/button/linkButton';
55
import * as Layout from 'sentry/components/layouts/thirds';
6+
import {PreprodBuildsDisplay} from 'sentry/components/preprod/preprodBuildsDisplay';
67
import {PreprodBuildsTable} from 'sentry/components/preprod/preprodBuildsTable';
78
import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
89
import {IconSettings} from 'sentry/icons';
@@ -13,6 +14,7 @@ import type RequestError from 'sentry/utils/requestError/requestError';
1314
import useLocationQuery from 'sentry/utils/url/useLocationQuery';
1415
import useOrganization from 'sentry/utils/useOrganization';
1516
import {useParams} from 'sentry/utils/useParams';
17+
import {usePreprodBuildsAnalytics} from 'sentry/views/preprod/hooks/usePreprodBuildsAnalytics';
1618
import type {ListBuildsApiResponse} from 'sentry/views/preprod/types/listBuildsTypes';
1719

1820
export default function BuildList() {
@@ -55,6 +57,17 @@ export default function BuildList() {
5557
const builds = buildsData?.builds || [];
5658
const pageLinks = getResponseHeader?.('Link') || null;
5759

60+
usePreprodBuildsAnalytics({
61+
builds,
62+
cursor,
63+
display: PreprodBuildsDisplay.SIZE,
64+
enabled: !!projectId,
65+
error: !!error,
66+
isLoading,
67+
pageSource: 'preprod_builds_list',
68+
projectCount: 1,
69+
});
70+
5871
return (
5972
<SentryDocumentTitle title="Build list">
6073
<Layout.Page>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import {useEffect} from 'react';
2+
3+
import type {PreprodBuildsDisplay} from 'sentry/components/preprod/preprodBuildsDisplay';
4+
import {trackAnalytics} from 'sentry/utils/analytics';
5+
import type {BuildListPageSource} from 'sentry/utils/analytics/preprodBuildAnalyticsEvents';
6+
import useOrganization from 'sentry/utils/useOrganization';
7+
import usePageFilters from 'sentry/utils/usePageFilters';
8+
import type {BuildDetailsApiResponse} from 'sentry/views/preprod/types/buildDetailsTypes';
9+
10+
interface UsePreprodBuildsAnalyticsProps {
11+
builds: BuildDetailsApiResponse[];
12+
display: PreprodBuildsDisplay;
13+
isLoading: boolean;
14+
pageSource: BuildListPageSource;
15+
cursor?: string | null;
16+
enabled?: boolean;
17+
error?: boolean;
18+
projectCount?: number;
19+
searchQuery?: string | null;
20+
}
21+
22+
export function usePreprodBuildsAnalytics({
23+
builds,
24+
cursor,
25+
display,
26+
enabled = true,
27+
error,
28+
isLoading,
29+
pageSource,
30+
projectCount,
31+
searchQuery,
32+
}: UsePreprodBuildsAnalyticsProps) {
33+
const organization = useOrganization();
34+
const {selection} = usePageFilters();
35+
36+
const datetimeSelection = `${selection.datetime.start || ''}-${selection.datetime.end || ''}-${selection.datetime.period || ''}`;
37+
38+
useEffect(() => {
39+
if (!enabled || isLoading) {
40+
return;
41+
}
42+
const buildCountOnPage = builds.length;
43+
44+
trackAnalytics('preprod.builds.list.metadata', {
45+
organization,
46+
build_count_on_page: buildCountOnPage,
47+
query_status: error ? 'error' : 'success',
48+
is_empty: !error && buildCountOnPage === 0,
49+
has_search_query: (searchQuery?.trim() ?? '').length > 0,
50+
page_source: pageSource,
51+
display,
52+
cursor: cursor ?? null,
53+
project_count: projectCount ?? selection.projects.length,
54+
datetime_selection: datetimeSelection,
55+
});
56+
}, [
57+
builds.length,
58+
cursor,
59+
datetimeSelection,
60+
display,
61+
enabled,
62+
error,
63+
isLoading,
64+
organization,
65+
pageSource,
66+
projectCount,
67+
searchQuery,
68+
selection.projects.length,
69+
]);
70+
}

static/app/views/releases/detail/commitsAndFiles/preprodBuilds.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import useOrganization from 'sentry/utils/useOrganization';
2222
import {useParams} from 'sentry/utils/useParams';
2323
import {formatVersion} from 'sentry/utils/versions/formatVersion';
2424
import PreprodBuildsSearchBar from 'sentry/views/preprod/components/preprodBuildsSearchBar';
25+
import {usePreprodBuildsAnalytics} from 'sentry/views/preprod/hooks/usePreprodBuildsAnalytics';
2526
import type {BuildDetailsApiResponse} from 'sentry/views/preprod/types/buildDetailsTypes';
2627
import type {ListBuildsApiResponse} from 'sentry/views/preprod/types/listBuildsTypes';
2728
import {ReleaseContext} from 'sentry/views/releases/detail';
@@ -132,6 +133,18 @@ export default function PreprodBuilds() {
132133
const hasSearchQuery = !!urlSearchQuery?.trim();
133134
const showOnboarding = builds.length === 0 && !hasSearchQuery && !isLoadingBuilds;
134135

136+
usePreprodBuildsAnalytics({
137+
builds,
138+
cursor,
139+
display: activeDisplay,
140+
enabled: !!projectSlug && !!params.release,
141+
error: !!buildsError,
142+
isLoading: isLoadingBuilds,
143+
pageSource: 'releases_details_preprod_builds',
144+
projectCount: 1,
145+
searchQuery: urlSearchQuery,
146+
});
147+
135148
const handleBuildRowClick = useCallback(
136149
(build: BuildDetailsApiResponse) => {
137150
trackAnalytics('preprod.builds.release.build_row_clicked', {

static/app/views/releases/list/mobileBuilds.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type RequestError from 'sentry/utils/requestError/requestError';
1717
import {useLocation} from 'sentry/utils/useLocation';
1818
import {useNavigate} from 'sentry/utils/useNavigate';
1919
import PreprodBuildsSearchBar from 'sentry/views/preprod/components/preprodBuildsSearchBar';
20+
import {usePreprodBuildsAnalytics} from 'sentry/views/preprod/hooks/usePreprodBuildsAnalytics';
2021
import type {ListBuildsApiResponse} from 'sentry/views/preprod/types/listBuildsTypes';
2122

2223
type Props = {
@@ -100,14 +101,26 @@ export default function MobileBuilds({organization, selectedProjectIds}: Props)
100101
[location, navigate]
101102
);
102103

103-
if (selectedProjectIds.length === 0) {
104-
return <LoadingIndicator />;
105-
}
106-
107104
const builds = buildsData?.builds ?? [];
108105
const pageLinks = getResponseHeader?.('Link') ?? undefined;
109106
const hasSearchQuery = !!searchQuery?.trim();
110107
const showProjectColumn = selectedProjectIds.length > 1;
108+
usePreprodBuildsAnalytics({
109+
builds,
110+
cursor,
111+
display: activeDisplay,
112+
enabled: selectedProjectIds.length > 0,
113+
error: !!buildsError,
114+
isLoading: isLoadingBuilds,
115+
pageSource: 'releases_mobile_builds_tab',
116+
projectCount: selectedProjectIds.length,
117+
searchQuery,
118+
});
119+
120+
if (selectedProjectIds.length === 0) {
121+
return <LoadingIndicator />;
122+
}
123+
111124
return (
112125
<Stack gap="xl">
113126
<Flex

0 commit comments

Comments
 (0)