diff --git a/static/app/components/preprod/preprodBuildsTable.tsx b/static/app/components/preprod/preprodBuildsTable.tsx index c7609d6e2b8e82..5c92e30e6439ff 100644 --- a/static/app/components/preprod/preprodBuildsTable.tsx +++ b/static/app/components/preprod/preprodBuildsTable.tsx @@ -28,6 +28,7 @@ interface PreprodBuildsTableProps { projectSlug: string; error?: boolean; hasSearchQuery?: boolean; + onRowClick?: (build: BuildDetailsApiResponse) => void; pageLinks?: string | null; } @@ -36,6 +37,7 @@ export function PreprodBuildsTable({ isLoading, error, pageLinks, + onRowClick, organizationSlug, projectSlug, hasSearchQuery, @@ -59,7 +61,7 @@ export function PreprodBuildsTable({ return ( - + onRowClick?.(build)}> {build.app_info?.name || build.app_info?.app_id ? ( @@ -176,7 +178,7 @@ export function PreprodBuildsTable({ ); } else { - tableContent = {builds.map(renderBuildRow)}; + tableContent = {builds.map(build => renderBuildRow(build))}; } return ( diff --git a/static/app/utils/analytics.tsx b/static/app/utils/analytics.tsx index 9cf3b07d6c5fa6..d08930298594c0 100644 --- a/static/app/utils/analytics.tsx +++ b/static/app/utils/analytics.tsx @@ -73,6 +73,8 @@ import type {OnboardingEventParameters} from './analytics/onboardingAnalyticsEve import {onboardingEventMap} from './analytics/onboardingAnalyticsEvents'; import type {PerformanceEventParameters} from './analytics/performanceAnalyticsEvents'; import {performanceEventMap} from './analytics/performanceAnalyticsEvents'; +import type {PreprodBuildEventParameters} from './analytics/preprodBuildAnalyticsEvents'; +import {preprodBuildEventMap} from './analytics/preprodBuildAnalyticsEvents'; import type {ProfilingEventParameters} from './analytics/profilingAnalyticsEvents'; import {profilingEventMap} from './analytics/profilingAnalyticsEvents'; import type {ProjectCreationEventParameters} from './analytics/projectCreationAnalyticsEvents'; @@ -113,6 +115,7 @@ interface EventParameters MonitorsEventParameters, PerformanceEventParameters, ProfilingEventParameters, + PreprodBuildEventParameters, ReleasesEventParameters, ReplayEventParameters, SearchEventParameters, @@ -151,6 +154,7 @@ const allEventMap: Record = { ...monitorsEventMap, ...nextJsInsightsEventMap, ...performanceEventMap, + ...preprodBuildEventMap, ...tracingEventMap, ...profilingEventMap, ...exploreAnalyticsEventMap, diff --git a/static/app/utils/analytics/preprodBuildAnalyticsEvents.tsx b/static/app/utils/analytics/preprodBuildAnalyticsEvents.tsx new file mode 100644 index 00000000000000..2bba73e1ded16f --- /dev/null +++ b/static/app/utils/analytics/preprodBuildAnalyticsEvents.tsx @@ -0,0 +1,48 @@ +import type {Organization} from 'sentry/types/organization'; + +type BasePreprodBuildEvent = { + organization: Organization; + build_id?: string; + platform?: string | null; + project_slug?: string; + project_type?: string | null; +}; + +export type PreprodBuildEventParameters = { + 'preprod.builds.compare.go_to_build_details': BasePreprodBuildEvent & { + slot?: 'head' | 'base'; + }; + 'preprod.builds.compare.select_base_build': BasePreprodBuildEvent; + 'preprod.builds.compare.trigger_comparison': BasePreprodBuildEvent; + 'preprod.builds.details.compare_build_clicked': BasePreprodBuildEvent; + 'preprod.builds.details.delete_build': BasePreprodBuildEvent; + 'preprod.builds.details.expand_insight': BasePreprodBuildEvent & { + insight_key: string; + }; + 'preprod.builds.details.open_insight_details_modal': BasePreprodBuildEvent & { + insight_key: string; + }; + 'preprod.builds.details.open_insights_sidebar': BasePreprodBuildEvent & { + source: 'metric_card' | 'insight_table'; + }; + 'preprod.builds.release.build_row_clicked': BasePreprodBuildEvent; +}; + +type PreprodBuildAnalyticsKey = keyof PreprodBuildEventParameters; + +export const preprodBuildEventMap: Record = { + 'preprod.builds.release.build_row_clicked': 'Preprod Builds: Release Build Row Clicked', + 'preprod.builds.details.open_insights_sidebar': + 'Preprod Build Details: Insights Sidebar Opened', + 'preprod.builds.details.expand_insight': 'Preprod Build Details: Insight Expanded', + 'preprod.builds.details.open_insight_details_modal': + 'Preprod Build Details: Open Insight Details Modal', + 'preprod.builds.details.delete_build': 'Preprod Build Details: Delete Build', + 'preprod.builds.details.compare_build_clicked': + 'Preprod Build Details: Compare Clicked', + 'preprod.builds.compare.go_to_build_details': + 'Preprod Build Comparison: Go to Build Details', + 'preprod.builds.compare.select_base_build': 'Preprod Build Comparison: Base Selected', + 'preprod.builds.compare.trigger_comparison': + 'Preprod Build Comparison: Compare Triggered', +}; diff --git a/static/app/views/preprod/buildComparison/main/sizeCompareSelectedBuilds.tsx b/static/app/views/preprod/buildComparison/main/sizeCompareSelectedBuilds.tsx index 81f0c4a382469c..9bea6d4b946c9b 100644 --- a/static/app/views/preprod/buildComparison/main/sizeCompareSelectedBuilds.tsx +++ b/static/app/views/preprod/buildComparison/main/sizeCompareSelectedBuilds.tsx @@ -7,6 +7,8 @@ import {Text} from '@sentry/scraps/text'; import {IconClose, IconCommit, IconFocus, IconLock, IconTelescope} from 'sentry/icons'; import {t} from 'sentry/locale'; +import ProjectsStore from 'sentry/stores/projectsStore'; +import {trackAnalytics} from 'sentry/utils/analytics'; import useOrganization from 'sentry/utils/useOrganization'; import {useParams} from 'sentry/utils/useParams'; import type {BuildDetailsApiResponse} from 'sentry/views/preprod/types/buildDetailsTypes'; @@ -15,10 +17,19 @@ interface BuildButtonProps { buildDetails: BuildDetailsApiResponse; icon: React.ReactNode; label: string; + projectType: string | null; + slot: 'head' | 'base'; onRemove?: () => void; } -function BuildButton({buildDetails, icon, label, onRemove}: BuildButtonProps) { +function BuildButton({ + buildDetails, + icon, + label, + onRemove, + slot, + projectType, +}: BuildButtonProps) { const organization = useOrganization(); const {projectId} = useParams<{projectId: string}>(); const sha = buildDetails.vcs_info?.head_sha?.substring(0, 7); @@ -26,9 +37,22 @@ function BuildButton({buildDetails, icon, label, onRemove}: BuildButtonProps) { const buildId = buildDetails.id; const buildUrl = `/organizations/${organization.slug}/preprod/${projectId}/${buildId}/`; + const platform = buildDetails.app_info?.platform ?? null; return ( - + + trackAnalytics('preprod.builds.compare.go_to_build_details', { + organization, + build_id: buildId, + project_slug: projectId, + platform, + project_type: projectType, + slot, + }) + } + > {icon} @@ -107,12 +131,20 @@ export function SizeCompareSelectedBuilds({ onClearBaseBuild, onTriggerComparison, }: SizeCompareSelectedBuildsProps) { + const organization = useOrganization(); + const {projectId} = useParams<{projectId: string}>(); + const platform = headBuildDetails.app_info?.platform ?? null; + const project = ProjectsStore.getBySlug(projectId); + const projectType = project?.platform ?? null; + return ( } label={t('Head')} + slot="head" + projectType={projectType} /> {t('vs')} @@ -123,6 +155,8 @@ export function SizeCompareSelectedBuilds({ icon={} label={t('Base')} onRemove={onClearBaseBuild} + slot="base" + projectType={projectType} /> ) : ( @@ -134,6 +168,13 @@ export function SizeCompareSelectedBuilds({