diff --git a/static/app/views/insights/pages/ai/aiOverviewPage.tsx b/static/app/views/insights/pages/ai/aiOverviewPage.tsx
index f6d0c7be62651a..efb354aed1bf06 100644
--- a/static/app/views/insights/pages/ai/aiOverviewPage.tsx
+++ b/static/app/views/insights/pages/ai/aiOverviewPage.tsx
@@ -47,13 +47,13 @@ import {
} from 'sentry/views/performance/utils';
export const AI_COLUMN_TITLES = [
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'p50()',
- 'p95()',
- 'users',
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'p50()'},
+ {title: 'p95()'},
+ {title: 'users'},
];
function AiOverviewPage() {
diff --git a/static/app/views/insights/pages/backend/backendOverviewPage.tsx b/static/app/views/insights/pages/backend/backendOverviewPage.tsx
index 1b78987b2cac4e..ff19a33302a390 100644
--- a/static/app/views/insights/pages/backend/backendOverviewPage.tsx
+++ b/static/app/views/insights/pages/backend/backendOverviewPage.tsx
@@ -47,17 +47,17 @@ import {
} from 'sentry/views/performance/utils';
export const BACKEND_COLUMN_TITLES = [
- 'http method',
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'p50()',
- 'p95()',
- 'failure rate',
- 'apdex',
- 'users',
- 'user misery',
+ {title: 'http method'},
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'p50()'},
+ {title: 'p95()'},
+ {title: 'failure rate'},
+ {title: 'apdex'},
+ {title: 'users'},
+ {title: 'user misery'},
];
function BackendOverviewPage() {
diff --git a/static/app/views/insights/pages/frontend/frontendOverviewPage.tsx b/static/app/views/insights/pages/frontend/frontendOverviewPage.tsx
index 1270d7ab712307..9a081f2e7a3e4b 100644
--- a/static/app/views/insights/pages/frontend/frontendOverviewPage.tsx
+++ b/static/app/views/insights/pages/frontend/frontendOverviewPage.tsx
@@ -3,6 +3,7 @@ import styled from '@emotion/styled';
import Feature from 'sentry/components/acl/feature';
import {COL_WIDTH_UNDEFINED} from 'sentry/components/gridEditable';
import * as Layout from 'sentry/components/layouts/thirds';
+import ExternalLink from 'sentry/components/links/externalLink';
import {NoAccess} from 'sentry/components/noAccess';
import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter';
@@ -10,6 +11,7 @@ import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter';
import TransactionNameSearchBar from 'sentry/components/performance/searchBar';
import * as TeamKeyTransactionManager from 'sentry/components/performance/teamKeyTransactionsManager';
+import {tct} from 'sentry/locale';
import {trackAnalytics} from 'sentry/utils/analytics';
import {
canUseMetricsData,
@@ -47,16 +49,25 @@ import {
ProjectPerformanceType,
} from 'sentry/views/performance/utils';
+const DURATION_TOOLTIP = tct(
+ 'A heuristic measuring when a pageload or navigation completes. Based on whether the initial load of the webpage has become idle [link:Learn more.]',
+ {
+ link: (
+
+ ),
+ }
+);
+
export const FRONTEND_COLUMN_TITLES = [
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'p50()',
- 'p75()',
- 'p95()',
- 'users',
- 'user misery',
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'p50()', tooltip: DURATION_TOOLTIP},
+ {title: 'p75()', tooltip: DURATION_TOOLTIP},
+ {title: 'p95()', tooltip: DURATION_TOOLTIP},
+ {title: 'users'},
+ {title: 'user misery'},
];
function FrontendOverviewPage() {
diff --git a/static/app/views/insights/pages/mobile/mobileOverviewPage.tsx b/static/app/views/insights/pages/mobile/mobileOverviewPage.tsx
index dc98ca6d8c7653..393375c6feb6ec 100644
--- a/static/app/views/insights/pages/mobile/mobileOverviewPage.tsx
+++ b/static/app/views/insights/pages/mobile/mobileOverviewPage.tsx
@@ -51,26 +51,26 @@ import {
} from 'sentry/views/performance/utils';
const MOBILE_COLUMN_TITLES = [
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'slow frame %',
- 'frozen frame %',
- 'users',
- 'user misery',
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'slow frame %'},
+ {title: 'frozen frame %'},
+ {title: 'users'},
+ {title: 'user misery'},
];
const REACT_NATIVE_COLUMN_TITLES = [
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'slow frame %',
- 'frozen frame %',
- 'stall %',
- 'users',
- 'user misery',
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'slow frame %'},
+ {title: 'frozen frame %'},
+ {title: 'stall %'},
+ {title: 'users'},
+ {title: 'user misery'},
];
function MobileOverviewPage() {
@@ -124,7 +124,11 @@ function MobileOverviewPage() {
);
if (organization.features.includes('mobile-vitals')) {
- columnTitles = [...columnTitles.slice(0, 5), 'ttid', ...columnTitles.slice(5, 0)];
+ columnTitles = [
+ ...columnTitles.slice(0, 5),
+ {title: 'ttid'},
+ ...columnTitles.slice(5, 0),
+ ];
tripleChartRowCharts.push(
...[
PerformanceWidgetSetting.TIME_TO_INITIAL_DISPLAY,
diff --git a/static/app/views/performance/landing/data.tsx b/static/app/views/performance/landing/data.tsx
index 84833e8ae26af8..171d4acc8de49b 100644
--- a/static/app/views/performance/landing/data.tsx
+++ b/static/app/views/performance/landing/data.tsx
@@ -1,60 +1,60 @@
export const FRONTEND_PAGELOAD_COLUMN_TITLES = [
- 'transaction',
- 'project',
- 'tpm',
- 'FCP',
- 'LCP',
- 'FID',
- 'CLS',
- 'users',
- 'user misery',
+ {title: 'transaction'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'FCP'},
+ {title: 'LCP'},
+ {title: 'FID'},
+ {title: 'CLS'},
+ {title: 'users'},
+ {title: 'user misery'},
];
export const FRONTEND_OTHER_COLUMN_TITLES = [
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'p50()',
- 'p75()',
- 'p95()',
- 'users',
- 'user misery',
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'p50()'},
+ {title: 'p75()'},
+ {title: 'p95()'},
+ {title: 'users'},
+ {title: 'user misery'},
];
export const BACKEND_COLUMN_TITLES = [
- 'http method',
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'p50',
- 'p95',
- 'failure rate',
- 'apdex',
- 'users',
- 'user misery',
+ {title: 'http method'},
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'p50'},
+ {title: 'p95'},
+ {title: 'failure rate'},
+ {title: 'apdex'},
+ {title: 'users'},
+ {title: 'user misery'},
];
export const MOBILE_COLUMN_TITLES = [
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'slow frame %',
- 'frozen frame %',
- 'users',
- 'user misery',
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'slow frame %'},
+ {title: 'frozen frame %'},
+ {title: 'users'},
+ {title: 'user misery'},
];
export const REACT_NATIVE_COLUMN_TITLES = [
- 'transaction',
- 'operation',
- 'project',
- 'tpm',
- 'slow frame %',
- 'frozen frame %',
- 'stall %',
- 'users',
- 'user misery',
+ {title: 'transaction'},
+ {title: 'operation'},
+ {title: 'project'},
+ {title: 'tpm'},
+ {title: 'slow frame %'},
+ {title: 'frozen frame %'},
+ {title: 'stall %'},
+ {title: 'users'},
+ {title: 'user misery'},
];
diff --git a/static/app/views/performance/landing/index.spec.tsx b/static/app/views/performance/landing/index.spec.tsx
index d5682aca554c07..687c19a260a089 100644
--- a/static/app/views/performance/landing/index.spec.tsx
+++ b/static/app/views/performance/landing/index.spec.tsx
@@ -198,7 +198,7 @@ describe('Performance > Landing > Index', function () {
expect(columnHeaders).toHaveLength(REACT_NATIVE_COLUMN_TITLES.length);
for (const [index, title] of columnHeaders.entries()) {
- expect(title).toHaveTextContent(REACT_NATIVE_COLUMN_TITLES[index]!);
+ expect(title).toHaveTextContent(REACT_NATIVE_COLUMN_TITLES[index].title!);
}
});
diff --git a/static/app/views/performance/landing/views/mobileView.tsx b/static/app/views/performance/landing/views/mobileView.tsx
index 649ca11f077535..87b2c66f0b1d4c 100644
--- a/static/app/views/performance/landing/views/mobileView.tsx
+++ b/static/app/views/performance/landing/views/mobileView.tsx
@@ -32,7 +32,11 @@ export function MobileView(props: BasePerformanceViewProps) {
];
if (organization.features.includes('mobile-vitals')) {
- columnTitles = [...columnTitles.slice(0, 5), 'ttid', ...columnTitles.slice(5, 0)];
+ columnTitles = [
+ ...columnTitles.slice(0, 5),
+ {title: 'ttid'},
+ ...columnTitles.slice(5, 0),
+ ];
allowedCharts.push(
...[
PerformanceWidgetSetting.TIME_TO_INITIAL_DISPLAY,
diff --git a/static/app/views/performance/table.tsx b/static/app/views/performance/table.tsx
index 4e220b99915365..a88bbf69a39433 100644
--- a/static/app/views/performance/table.tsx
+++ b/static/app/views/performance/table.tsx
@@ -1,4 +1,4 @@
-import {Component, useEffect} from 'react';
+import {Component, type ReactNode, useEffect} from 'react';
import styled from '@emotion/styled';
import type {Location, LocationDescriptorObject} from 'history';
@@ -11,9 +11,11 @@ import SortLink from 'sentry/components/gridEditable/sortLink';
import Link from 'sentry/components/links/link';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import Pagination from 'sentry/components/pagination';
+import QuestionTooltip from 'sentry/components/questionTooltip';
import {Tooltip} from 'sentry/components/tooltip';
import {IconStar} from 'sentry/icons';
import {t, tct} from 'sentry/locale';
+import {space} from 'sentry/styles/space';
import type {Organization} from 'sentry/types/organization';
import type {Project} from 'sentry/types/project';
import {trackAnalytics} from 'sentry/utils/analytics';
@@ -55,6 +57,15 @@ import {
UNPARAMETERIZED_TRANSACTION,
} from './utils';
+type ColumnTitle = {
+ title: string | ReactNode;
+ tooltip?: string | ReactNode;
+};
+
+const COLUMN_TITLES_OPTIONAL_TOOLTIP = COLUMN_TITLES.map(title => {
+ return {title};
+});
+
type Props = {
eventView: EventView;
location: Location;
@@ -62,7 +73,7 @@ type Props = {
projects: Project[];
setError: (msg: string | undefined) => void;
withStaticFilters: boolean;
- columnTitles?: string[];
+ columnTitles?: ColumnTitle[];
domainViewFilters?: DomainViewFilters;
summaryConditions?: string;
};
@@ -402,7 +413,7 @@ class _Table extends Component {
renderHeadCell(
tableMeta: TableData['meta'],
column: TableColumn,
- title: React.ReactNode
+ title: ColumnTitle
): React.ReactNode {
const {eventView, location} = this.props;
@@ -437,7 +448,7 @@ class _Table extends Component {
const sortLink = (
{
);
}
- return sortLink;
+
+ if (!title.tooltip) {
+ return sortLink;
+ }
+ return (
+
+ );
}
renderHeadCellWithMeta = (tableMeta: TableData['meta']) => {
- const columnTitles = this.props.columnTitles ?? COLUMN_TITLES;
+ const columnTitles = this.props.columnTitles ?? COLUMN_TITLES_OPTIONAL_TOOLTIP;
return (column: TableColumn, index: number): React.ReactNode =>
this.renderHeadCell(tableMeta, column, columnTitles[index]);
};
@@ -479,7 +499,9 @@ class _Table extends Component {
/>
);
- return [this.renderHeadCell(tableData?.meta, teamKeyTransactionColumn, star)];
+ return [
+ this.renderHeadCell(tableData?.meta, teamKeyTransactionColumn, {title: star}),
+ ];
}
return [this.renderBodyCell(tableData, teamKeyTransactionColumn, dataRow)];
}
@@ -627,4 +649,12 @@ const UnparameterizedTooltipWrapper = styled('div')`
justify-content: center;
`;
+const Header = styled('div')`
+ display: grid;
+ grid-template-columns: repeat(2, max-content);
+ align-items: center;
+ padding: ${space(1.5)};
+ grid-column-gap: ${space(0.5)};
+`;
+
export default Table;