Skip to content

Commit 955c2a8

Browse files
authored
feat(agents-insights): dashboard placeholder (#92021)
1 parent 99640c2 commit 955c2a8

File tree

15 files changed

+230
-12
lines changed

15 files changed

+230
-12
lines changed

static/app/components/sidebar/index.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ import {useLocation} from 'sentry/utils/useLocation';
5353
import useMedia from 'sentry/utils/useMedia';
5454
import useOrganization from 'sentry/utils/useOrganization';
5555
import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
56+
import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
5657
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
58+
import {
59+
AGENTS_LANDING_SUB_PATH,
60+
AGENTS_SIDEBAR_LABEL,
61+
} from 'sentry/views/insights/pages/agents/settings';
5762
import {
5863
AI_LANDING_SUB_PATH,
5964
AI_SIDEBAR_LABEL,
@@ -380,13 +385,26 @@ function Sidebar() {
380385
id="performance-domains-mobile"
381386
icon={<SubitemDot collapsed />}
382387
/>
383-
<SidebarItem
384-
{...sidebarItemProps}
385-
label={AI_SIDEBAR_LABEL}
386-
to={`/organizations/${organization.slug}/${DOMAIN_VIEW_BASE_URL}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[AI_LANDING_SUB_PATH]}/`}
387-
id="performance-domains-ai"
388-
icon={<SubitemDot collapsed />}
389-
/>
388+
<AgentInsightsFeature
389+
organization={organization}
390+
renderDisabled={() => (
391+
<SidebarItem
392+
{...sidebarItemProps}
393+
label={AI_SIDEBAR_LABEL}
394+
to={`/organizations/${organization.slug}/${DOMAIN_VIEW_BASE_URL}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[AI_LANDING_SUB_PATH]}/`}
395+
id="performance-domains-ai"
396+
icon={<SubitemDot collapsed />}
397+
/>
398+
)}
399+
>
400+
<SidebarItem
401+
{...sidebarItemProps}
402+
label={AGENTS_SIDEBAR_LABEL}
403+
to={`/organizations/${organization.slug}/${DOMAIN_VIEW_BASE_URL}/${AGENTS_LANDING_SUB_PATH}/${MODULE_BASE_URLS[AGENTS_LANDING_SUB_PATH]}/`}
404+
id="performance-domains-agents"
405+
icon={<SubitemDot collapsed />}
406+
/>
407+
</AgentInsightsFeature>
390408
</SidebarAccordion>
391409
</Feature>
392410
);

static/app/routes.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import AuthLayout from 'sentry/views/auth/layout';
1717
import {automationRoutes} from 'sentry/views/automations/routes';
1818
import {detectorRoutes} from 'sentry/views/detectors/routes';
1919
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
20+
import {AGENTS_LANDING_SUB_PATH} from 'sentry/views/insights/pages/agents/settings';
2021
import {AI_LANDING_SUB_PATH} from 'sentry/views/insights/pages/ai/settings';
2122
import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backend/settings';
2223
import {FRONTEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/frontend/settings';
@@ -1797,6 +1798,16 @@ function buildRoutes() {
17971798
{traceViewRoute}
17981799
{moduleRoutes}
17991800
</Route>
1801+
<Route path={`${AGENTS_LANDING_SUB_PATH}/`}>
1802+
<IndexRoute
1803+
component={make(
1804+
() => import('sentry/views/insights/agentMonitoring/views/agentsOverviewPage')
1805+
)}
1806+
/>
1807+
{transactionSummaryRoutes}
1808+
{traceViewRoute}
1809+
{moduleRoutes}
1810+
</Route>
18001811
<Route path="projects/" component={make(() => import('sentry/views/projects/'))}>
18011812
{projectsChildRoutes}
18021813
</Route>

static/app/utils/analytics/insightAnalyticEvents.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export type InsightEventParameters = {
2323
'insight.general.select_region_value': {regions: string[]};
2424
'insight.general.table_paginate': {direction: string; source: string};
2525
'insight.general.table_sort': {direction: string; field: string; source: string};
26+
'insight.page_loads.agents': {has_ever_sent_data: boolean; view: DomainView};
2627
'insight.page_loads.ai': {has_ever_sent_data: boolean; view: DomainView};
2728
'insight.page_loads.app_start': {has_ever_sent_data: boolean; view: DomainView};
2829
'insight.page_loads.assets': {has_ever_sent_data: boolean; view: DomainView};
@@ -55,6 +56,7 @@ export type InsightEventKey = keyof InsightEventParameters;
5556
export const insightEventMap: Record<InsightEventKey, string | null> = {
5657
'insights.page_loads.overview': 'Insights: Overview Page Load',
5758
'insight.page_loads.ai': 'Insights: AI Page Load',
59+
'insight.page_loads.agents': 'Insights: Agents Page Load',
5860
'insight.page_loads.app_start': 'Insights: App Start Page Load',
5961
'insight.page_loads.assets': 'Insights: Assets Page Load',
6062
'insight.page_loads.cache': 'Insights: Cache Page Load',
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {t} from 'sentry/locale';
2+
3+
export const MODULE_TITLE = t('Overview');
4+
export const BASE_URL = '';
5+
6+
export const DATA_TYPE = t('Agent');
7+
export const DATA_TYPE_PLURAL = t('Agents');
8+
9+
export const MODULE_DOC_LINK = 'https://docs.sentry.io/product/insights/ai/';
10+
11+
export const MODULE_FEATURES = ['insights-addon-modules', 'agents-insights'];
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import Feature from 'sentry/components/acl/feature';
2+
import {NoAccess} from 'sentry/components/noAccess';
3+
import type {Organization} from 'sentry/types/organization';
4+
5+
export function hasAgentInsights(organization: Organization) {
6+
return organization.features.includes('agents-insights');
7+
}
8+
9+
type AgentInsightsFeatureProps = Omit<Parameters<typeof Feature>[0], 'features'>;
10+
11+
export function AgentInsightsFeature(props: AgentInsightsFeatureProps) {
12+
return (
13+
<Feature features="agents-insights" renderDisabled={props.renderDisabled ?? NoAccess}>
14+
{props.children}
15+
</Feature>
16+
);
17+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import styled from '@emotion/styled';
2+
3+
import * as Layout from 'sentry/components/layouts/thirds';
4+
import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
5+
import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout';
6+
import {ModulePageFilterBar} from 'sentry/views/insights/common/components/modulePageFilterBar';
7+
import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders';
8+
import {ModuleBodyUpsellHook} from 'sentry/views/insights/common/components/moduleUpsellHookWrapper';
9+
import {AgentsPageHeader} from 'sentry/views/insights/pages/agents/agentsPageHeader';
10+
import {ModuleName} from 'sentry/views/insights/types';
11+
12+
function AgentsMonitoringPage() {
13+
return (
14+
<Layout.Page>
15+
<AgentsPageHeader module={ModuleName.AGENTS} />
16+
<ModuleBodyUpsellHook moduleName={ModuleName.AGENTS}>
17+
<Layout.Body>
18+
<Layout.Main fullWidth>
19+
<ModuleLayout.Layout>
20+
<ModuleLayout.Full>
21+
<ModulePageFilterBar moduleName={ModuleName.AGENTS} />
22+
</ModuleLayout.Full>
23+
<ModuleLayout.Full>
24+
<DashboardPlaceholder>Agent Monitoring Dashboard</DashboardPlaceholder>
25+
</ModuleLayout.Full>
26+
</ModuleLayout.Layout>
27+
</Layout.Main>
28+
</Layout.Body>
29+
</ModuleBodyUpsellHook>
30+
</Layout.Page>
31+
);
32+
}
33+
34+
function PageWithProviders() {
35+
return (
36+
<AgentInsightsFeature>
37+
<ModulePageProviders
38+
moduleName={ModuleName.AGENTS}
39+
analyticEventName="insight.page_loads.agents"
40+
>
41+
<AgentsMonitoringPage />
42+
</ModulePageProviders>
43+
</AgentInsightsFeature>
44+
);
45+
}
46+
47+
const DashboardPlaceholder = styled('div')`
48+
display: flex;
49+
flex-direction: column;
50+
align-items: center;
51+
justify-content: center;
52+
color: ${p => p.theme.gray300};
53+
font-size: ${p => p.theme.fontSizeLarge};
54+
font-weight: ${p => p.theme.fontWeightBold};
55+
`;
56+
57+
export default PageWithProviders;

static/app/views/insights/common/components/modulesOnboarding.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,13 @@ const EMPTY_STATE_CONTENT: Record<TitleableModuleNames, EmptyStateContent> = {
307307
imageSrc: llmPreviewImg,
308308
supportedSdks: ['python'],
309309
},
310+
agents: {
311+
heading: t('TODO'),
312+
description: t('TODO'),
313+
valuePropDescription: t('Mobile UI load insights include:'),
314+
valuePropPoints: [],
315+
imageSrc: screenLoadsPreviewImg,
316+
},
310317
'mobile-ui': {
311318
heading: t('TODO'),
312319
description: t('TODO'),

static/app/views/insights/common/queries/useHasFirstSpan.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const excludedModuleNames = [
1111
ModuleName.CRONS,
1212
ModuleName.UPTIME,
1313
ModuleName.SESSIONS,
14+
ModuleName.AGENTS,
1415
] as const;
1516

1617
type ExcludedModuleNames = (typeof excludedModuleNames)[number];

static/app/views/insights/common/utils/useModuleURL.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
22
import useOrganization from 'sentry/utils/useOrganization';
3+
import {BASE_URL as AGENTS_BASE_URL} from 'sentry/views/insights/agentMonitoring/settings';
34
import {BASE_URL as RESOURCES_BASE_URL} from 'sentry/views/insights/browser/resources/settings';
45
import {BASE_URL as VITALS_BASE_URL} from 'sentry/views/insights/browser/webVitals/settings';
56
import {BASE_URL as CACHE_BASE_URL} from 'sentry/views/insights/cache/settings';
@@ -33,6 +34,7 @@ export const MODULE_BASE_URLS: Record<ModuleName, string> = {
3334
[ModuleName.VITAL]: VITALS_BASE_URL,
3435
[ModuleName.RESOURCE]: RESOURCES_BASE_URL,
3536
[ModuleName.AI]: AI_BASE_URL,
37+
[ModuleName.AGENTS]: AGENTS_BASE_URL,
3638
[ModuleName.MOBILE_UI]: MOBILE_UI_BASE_URL,
3739
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_BASE_URL,
3840
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_BASE_URL,

static/app/views/insights/common/views/spans/selectors/actionSelector.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,6 @@ const LABEL_FOR_MODULE_NAME: Record<ModuleName, ReactNode> = {
132132
'mobile-vitals': t('Action'),
133133
'screen-rendering': t('Action'),
134134
ai: 'Action',
135+
agents: t('Action'),
135136
sessions: t('Action'),
136137
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
2+
import useOrganization from 'sentry/utils/useOrganization';
3+
import {
4+
AGENTS_LANDING_SUB_PATH,
5+
AGENTS_LANDING_TITLE,
6+
MODULES,
7+
} from 'sentry/views/insights/pages/agents/settings';
8+
import {
9+
DomainViewHeader,
10+
type Props as HeaderProps,
11+
} from 'sentry/views/insights/pages/domainViewHeader';
12+
import {DOMAIN_VIEW_BASE_URL} from 'sentry/views/insights/pages/settings';
13+
14+
type Props = {
15+
breadcrumbs?: HeaderProps['additionalBreadCrumbs'];
16+
headerActions?: HeaderProps['additonalHeaderActions'];
17+
headerTitle?: HeaderProps['headerTitle'];
18+
hideDefaultTabs?: HeaderProps['hideDefaultTabs'];
19+
module?: HeaderProps['selectedModule'];
20+
tabs?: HeaderProps['tabs'];
21+
};
22+
23+
export function AgentsPageHeader({
24+
module,
25+
headerTitle,
26+
headerActions,
27+
breadcrumbs,
28+
tabs,
29+
hideDefaultTabs,
30+
}: Props) {
31+
const {slug} = useOrganization();
32+
33+
const agentsBaseUrl = normalizeUrl(
34+
`/organizations/${slug}/${DOMAIN_VIEW_BASE_URL}/${AGENTS_LANDING_SUB_PATH}`
35+
);
36+
37+
return (
38+
<DomainViewHeader
39+
hasOverviewPage={false}
40+
domainBaseUrl={agentsBaseUrl}
41+
headerTitle={headerTitle}
42+
domainTitle={AGENTS_LANDING_TITLE}
43+
modules={MODULES}
44+
selectedModule={module}
45+
additonalHeaderActions={headerActions}
46+
additionalBreadCrumbs={breadcrumbs}
47+
tabs={tabs}
48+
hideDefaultTabs={hideDefaultTabs}
49+
/>
50+
);
51+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import {t} from 'sentry/locale';
2+
import {ModuleName} from 'sentry/views/insights/types';
3+
4+
export const AGENTS_LANDING_SUB_PATH = 'agents';
5+
export const AGENTS_LANDING_TITLE = t('Agents');
6+
export const AGENTS_SIDEBAR_LABEL = t('Agents');
7+
8+
export const MODULES = [ModuleName.AGENTS];

static/app/views/insights/settings.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
import {t} from 'sentry/locale';
2+
import {
3+
DATA_TYPE as AGENTS_DATA_TYPE,
4+
DATA_TYPE_PLURAL as AGENTS_DATA_TYPE_PLURAL,
5+
MODULE_DOC_LINK as AGENTS_MODULE_DOC_LINK,
6+
MODULE_FEATURES as AGENTS_MODULE_FEATURES,
7+
MODULE_TITLE as AGENTS_MODULE_TITLE,
8+
} from 'sentry/views/insights/agentMonitoring/settings';
29
import {
310
DATA_TYPE as RESOURCE_DATA_TYPE,
411
DATA_TYPE_PLURAL as RESOURCE_DATA_TYPE_PLURAL,
@@ -128,6 +135,7 @@ export const MODULE_TITLES: Record<ModuleName, string> = {
128135
[ModuleName.VITAL]: VITALS_MODULE_TITLE,
129136
[ModuleName.RESOURCE]: RESOURCES_MODULE_TITLE,
130137
[ModuleName.AI]: AI_MODULE_TITLE,
138+
[ModuleName.AGENTS]: AGENTS_MODULE_TITLE,
131139
[ModuleName.MOBILE_UI]: MOBILE_UI_MODULE_TITLE,
132140
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_MODULE_TITLE,
133141
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_MODULE_TITLE,
@@ -147,6 +155,7 @@ export const MODULE_DATA_TYPES: Record<ModuleName, string> = {
147155
[ModuleName.VITAL]: WEB_VITALS_DATA_TYPE,
148156
[ModuleName.RESOURCE]: RESOURCE_DATA_TYPE,
149157
[ModuleName.AI]: AI_DATA_TYPE,
158+
[ModuleName.AGENTS]: AGENTS_DATA_TYPE,
150159
[ModuleName.MOBILE_UI]: t('Mobile UI'),
151160
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_DATA_TYPE,
152161
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_DATA_TYPE,
@@ -166,6 +175,7 @@ export const MODULE_DATA_TYPES_PLURAL: Record<ModuleName, string> = {
166175
[ModuleName.VITAL]: WEB_VITALS_DATA_TYPE_PLURAL,
167176
[ModuleName.RESOURCE]: RESOURCE_DATA_TYPE_PLURAL,
168177
[ModuleName.AI]: AI_DATA_TYPE_PLURAL,
178+
[ModuleName.AGENTS]: AGENTS_DATA_TYPE_PLURAL,
169179
[ModuleName.MOBILE_UI]: t('Mobile UI'),
170180
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_DATA_TYPE_PLURAL,
171181
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_DATA_TYPE_PLURAL,
@@ -188,6 +198,7 @@ export const MODULE_PRODUCT_DOC_LINKS = {
188198
[ModuleName.VITAL]: VITALS_MODULE_DOC_LINK,
189199
[ModuleName.RESOURCE]: RESOURCES_MODULE_DOC_LINK,
190200
[ModuleName.AI]: AI_MODULE_DOC_LINK,
201+
[ModuleName.AGENTS]: AGENTS_MODULE_DOC_LINK,
191202
[ModuleName.MOBILE_UI]: MODULE_UI_DOC_LINK,
192203
[ModuleName.MOBILE_VITALS]: MODULE_SCREENS_DOC_LINK,
193204
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_MODULE_DOC_LINK,
@@ -212,6 +223,7 @@ export const MODULE_FEATURE_MAP: Record<ModuleName, string[]> = {
212223
[ModuleName.CACHE]: CACHE_MODULE_FEATURES,
213224
[ModuleName.QUEUE]: QUEUE_MODULE_FEATURES,
214225
[ModuleName.AI]: AI_MODULE_FEATURES,
226+
[ModuleName.AGENTS]: AGENTS_MODULE_FEATURES,
215227
[ModuleName.SCREEN_LOAD]: SCREEN_LOADS_MODULE_FEATURES,
216228
[ModuleName.MOBILE_UI]: MOBILE_UI_MODULE_FEATURES,
217229
[ModuleName.MOBILE_VITALS]: [MOBILE_SCREENS_MODULE_FEATURE],
@@ -234,6 +246,7 @@ export const MODULE_FEATURE_VISIBLE_MAP: Record<ModuleName, string[]> = {
234246
[ModuleName.CACHE]: ['insights-entry-points'],
235247
[ModuleName.QUEUE]: ['insights-entry-points'],
236248
[ModuleName.AI]: ['insights-entry-points'],
249+
[ModuleName.AGENTS]: ['insights-entry-points'],
237250
[ModuleName.SCREEN_LOAD]: ['insights-entry-points'],
238251
[ModuleName.MOBILE_UI]: ['insights-entry-points'],
239252
[ModuleName.MOBILE_VITALS]: ['insights-entry-points'],

static/app/views/insights/types.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export enum ModuleName {
1111
APP_START = 'app_start',
1212
RESOURCE = 'resource',
1313
AI = 'ai',
14+
AGENTS = 'agents',
1415
MOBILE_UI = 'mobile-ui',
1516
MOBILE_VITALS = 'mobile-vitals',
1617
SCREEN_RENDERING = 'screen-rendering',

static/app/views/nav/secondary/sections/insights/insightsSecondaryNav.tsx

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import type {Project} from 'sentry/types/project';
88
import {useLocation} from 'sentry/utils/useLocation';
99
import useOrganization from 'sentry/utils/useOrganization';
1010
import useProjects from 'sentry/utils/useProjects';
11+
import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
1112
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
13+
import {
14+
AGENTS_LANDING_SUB_PATH,
15+
AGENTS_SIDEBAR_LABEL,
16+
} from 'sentry/views/insights/pages/agents/settings';
1217
import {
1318
AI_LANDING_SUB_PATH,
1419
AI_SIDEBAR_LABEL,
@@ -91,12 +96,25 @@ export function InsightsSecondaryNav() {
9196
>
9297
{MOBILE_SIDEBAR_LABEL}
9398
</SecondaryNav.Item>
94-
<SecondaryNav.Item
95-
to={`${baseUrl}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[ModuleName.AI]}/`}
96-
analyticsItemName="insights_ai"
99+
100+
<AgentInsightsFeature
101+
organization={organization}
102+
renderDisabled={() => (
103+
<SecondaryNav.Item
104+
to={`${baseUrl}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[ModuleName.AI]}/`}
105+
analyticsItemName="insights_ai"
106+
>
107+
{AI_SIDEBAR_LABEL}
108+
</SecondaryNav.Item>
109+
)}
97110
>
98-
{AI_SIDEBAR_LABEL}
99-
</SecondaryNav.Item>
111+
<SecondaryNav.Item
112+
to={`${baseUrl}/${AGENTS_LANDING_SUB_PATH}/`}
113+
analyticsItemName="insights_agents"
114+
>
115+
{AGENTS_SIDEBAR_LABEL}
116+
</SecondaryNav.Item>
117+
</AgentInsightsFeature>
100118
</SecondaryNav.Section>
101119
<SecondaryNav.Section id="insights-projects-all">
102120
<SecondaryNav.Item

0 commit comments

Comments
 (0)