Skip to content

Commit f9a0eee

Browse files
authored
ref(agent-insights): Split into tabs (#103145)
### Motivation We are aiming to use standardized controls and widgets in all the insights pages to achieve a platformization of the product area and synergies with the dashboard product. In the AI insights area there is a unique control in form of a tabs in the middle of the page. Introducing this to the platform would mean significant effort. ### Solution Split the Agents and MCP page into multiple tabs (Overview, Models, Tools, Resources, Prompts). This gets rid of the inline controls while also making the agent insights easier to discover. #### Agents https://github.com/user-attachments/assets/787c3b1c-dba4-4278-a881-cba7221f3871 #### MCP https://github.com/user-attachments/assets/fa713f0c-5631-4c5e-be64-e3809ca24d91
1 parent 2c66b4f commit f9a0eee

File tree

128 files changed

+1756
-1033
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+1756
-1033
lines changed

static/app/router/routes.tsx

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL'
2222
import {AGENTS_LANDING_SUB_PATH} from 'sentry/views/insights/pages/agents/settings';
2323
import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backend/settings';
2424
import {FRONTEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/frontend/settings';
25+
import {MCP_LANDING_SUB_PATH} from 'sentry/views/insights/pages/mcp/settings';
2526
import {MOBILE_LANDING_SUB_PATH} from 'sentry/views/insights/pages/mobile/settings';
2627
import {DOMAIN_VIEW_BASE_URL} from 'sentry/views/insights/pages/settings';
2728
import {getModuleView} from 'sentry/views/insights/pages/utils';
@@ -2069,35 +2070,101 @@ function buildRoutes(): RouteObject[] {
20692070
...moduleRoutes,
20702071
],
20712072
},
2073+
// Redirect old links to the new mcp landing page
2074+
{
2075+
path: `ai/mcp/`,
2076+
redirectTo: `/${DOMAIN_VIEW_BASE_URL}/${MCP_LANDING_SUB_PATH}/`,
2077+
},
2078+
{
2079+
path: `${MCP_LANDING_SUB_PATH}/`,
2080+
component: make(() => import('sentry/views/insights/pages/mcp/layout')),
2081+
children: [
2082+
{
2083+
index: true,
2084+
handle: {module: undefined},
2085+
component: make(() => import('sentry/views/insights/pages/mcp/overview')),
2086+
},
2087+
transactionSummaryRoute,
2088+
traceView,
2089+
{
2090+
path: `${MODULE_BASE_URLS[ModuleName.MCP_TOOLS]}/`,
2091+
children: [
2092+
{
2093+
index: true,
2094+
handle: {module: ModuleName.MCP_TOOLS},
2095+
component: make(
2096+
() => import('sentry/views/insights/mcp-tools/views/mcpToolsLandingPage')
2097+
),
2098+
},
2099+
],
2100+
},
2101+
{
2102+
path: `${MODULE_BASE_URLS[ModuleName.MCP_RESOURCES]}/`,
2103+
children: [
2104+
{
2105+
index: true,
2106+
handle: {module: ModuleName.MCP_RESOURCES},
2107+
component: make(
2108+
() =>
2109+
import(
2110+
'sentry/views/insights/mcp-resources/views/mcpResourcesLandingPage'
2111+
)
2112+
),
2113+
},
2114+
],
2115+
},
2116+
{
2117+
path: `${MODULE_BASE_URLS[ModuleName.MCP_PROMPTS]}/`,
2118+
children: [
2119+
{
2120+
index: true,
2121+
handle: {module: ModuleName.MCP_PROMPTS},
2122+
component: make(
2123+
() =>
2124+
import('sentry/views/insights/mcp-prompts/views/mcpPromptsLandingPage')
2125+
),
2126+
},
2127+
],
2128+
},
2129+
],
2130+
},
2131+
// Redirect old links to the new agents landing page
2132+
{
2133+
path: `ai/*`,
2134+
redirectTo: `/${DOMAIN_VIEW_BASE_URL}/${AGENTS_LANDING_SUB_PATH}/`,
2135+
},
20722136
{
20732137
path: `${AGENTS_LANDING_SUB_PATH}/`,
20742138
component: make(() => import('sentry/views/insights/pages/agents/layout')),
20752139
children: [
20762140
{
20772141
index: true,
2078-
component: make(() => import('sentry/views/insights/pages/agents/redirect')),
2142+
handle: {module: undefined},
2143+
component: make(() => import('sentry/views/insights/pages/agents/overview')),
20792144
},
20802145
transactionSummaryRoute,
20812146
traceView,
20822147
{
2083-
path: `${MODULE_BASE_URLS[ModuleName.AGENTS]}/`,
2148+
path: `${MODULE_BASE_URLS[ModuleName.AGENT_MODELS]}/`,
20842149
children: [
20852150
{
20862151
index: true,
2087-
handle: {module: ModuleName.AGENTS},
2152+
handle: {module: ModuleName.AGENT_MODELS},
20882153
component: make(
2089-
() => import('sentry/views/insights/agents/views/overview')
2154+
() => import('sentry/views/insights/agentModels/views/modelsLandingPage')
20902155
),
20912156
},
20922157
],
20932158
},
20942159
{
2095-
path: `${MODULE_BASE_URLS[ModuleName.MCP]}/`,
2160+
path: `${MODULE_BASE_URLS[ModuleName.AGENT_TOOLS]}/`,
20962161
children: [
20972162
{
20982163
index: true,
2099-
handle: {module: ModuleName.MCP},
2100-
component: make(() => import('sentry/views/insights/mcp/views/overview')),
2164+
handle: {module: ModuleName.AGENT_TOOLS},
2165+
component: make(
2166+
() => import('sentry/views/insights/agentTools/views/toolsLandingPage')
2167+
),
21012168
},
21022169
],
21032170
},

static/app/utils/analytics/insightAnalyticEvents.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@ 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};
26+
'insight.page_loads.agent_models': {has_ever_sent_data: boolean; view: DomainView};
27+
'insight.page_loads.agent_tools': {has_ever_sent_data: boolean; view: DomainView};
2728
'insight.page_loads.ai': {has_ever_sent_data: boolean; view: DomainView};
2829
'insight.page_loads.app_start': {has_ever_sent_data: boolean; view: DomainView};
2930
'insight.page_loads.assets': {has_ever_sent_data: boolean; view: DomainView};
3031
'insight.page_loads.cache': {has_ever_sent_data: boolean; view: DomainView};
3132
'insight.page_loads.db': {has_ever_sent_data: boolean; view: DomainView};
3233
'insight.page_loads.http': {has_ever_sent_data: boolean; view: DomainView};
34+
'insight.page_loads.mcp_prompts': {has_ever_sent_data: boolean; view: DomainView};
35+
'insight.page_loads.mcp_resources': {has_ever_sent_data: boolean; view: DomainView};
36+
'insight.page_loads.mcp_tools': {has_ever_sent_data: boolean; view: DomainView};
3337
'insight.page_loads.queue': {has_ever_sent_data: boolean; view: DomainView};
3438
'insight.page_loads.screen_load': {has_ever_sent_data: boolean; view: DomainView};
3539
'insight.page_loads.screen_rendering': {has_ever_sent_data: boolean; view: DomainView};
@@ -58,7 +62,11 @@ export type InsightEventKey = keyof InsightEventParameters;
5862
export const insightEventMap: Record<InsightEventKey, string | null> = {
5963
'insights.page_loads.overview': 'Insights: Overview Page Load',
6064
'insight.page_loads.ai': 'Insights: AI Page Load',
61-
'insight.page_loads.agents': 'Insights: Agents Page Load',
65+
'insight.page_loads.agent_models': 'Insights: Agent Models Page Load',
66+
'insight.page_loads.agent_tools': 'Insights: Agent Tools Page Load',
67+
'insight.page_loads.mcp_prompts': 'Insights: MCP Prompts Page Load',
68+
'insight.page_loads.mcp_resources': 'Insights: MCP Resources Page Load',
69+
'insight.page_loads.mcp_tools': 'Insights: MCP Tools Page Load',
6270
'insight.page_loads.app_start': 'Insights: App Start Page Load',
6371
'insight.page_loads.assets': 'Insights: Assets Page Load',
6472
'insight.page_loads.cache': 'Insights: Cache Page Load',

static/app/utils/discover/fieldRenderers.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ import {
6868
import {QuickContextHoverWrapper} from 'sentry/views/discover/table/quickContext/quickContextWrapper';
6969
import {ContextType} from 'sentry/views/discover/table/quickContext/utils';
7070
import type {TraceItemDetailsMeta} from 'sentry/views/explore/hooks/useTraceItemDetails';
71-
import {ModelName} from 'sentry/views/insights/agents/components/modelName';
7271
import {PerformanceBadge} from 'sentry/views/insights/browser/webVitals/components/performanceBadge';
7372
import {CurrencyCell} from 'sentry/views/insights/common/components/tableCells/currencyCell';
7473
import {PercentChangeCell} from 'sentry/views/insights/common/components/tableCells/percentChangeCell';
7574
import {ResponseStatusCodeCell} from 'sentry/views/insights/common/components/tableCells/responseStatusCodeCell';
7675
import {SpanDescriptionCell} from 'sentry/views/insights/common/components/tableCells/spanDescriptionCell';
7776
import {StarredSegmentCell} from 'sentry/views/insights/common/components/tableCells/starredSegmentCell';
7877
import {TimeSpentCell} from 'sentry/views/insights/common/components/tableCells/timeSpentCell';
78+
import {ModelName} from 'sentry/views/insights/pages/agents/components/modelName';
7979
import {ModuleName, SpanFields} from 'sentry/views/insights/types';
8080
import {
8181
filterToLocationQuery,
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('Models');
4+
export const BASE_URL = 'models';
5+
6+
export const DATA_TYPE = t('Model');
7+
export const DATA_TYPE_PLURAL = t('Models');
8+
9+
export const MODULE_DOC_LINK = 'https://docs.sentry.io/product/insights/agents/';
10+
11+
export const MODULE_FEATURES = [];
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import {Fragment} from 'react';
2+
3+
import {Flex} from 'sentry/components/core/layout';
4+
import * as Layout from 'sentry/components/layouts/thirds';
5+
import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
6+
import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
7+
import {EAPSpanSearchQueryBuilder} from 'sentry/components/performance/spanSearchQueryBuilder';
8+
import {SearchQueryBuilderProvider} from 'sentry/components/searchQueryBuilder/context';
9+
import useOrganization from 'sentry/utils/useOrganization';
10+
import {TraceItemAttributeProvider} from 'sentry/views/explore/contexts/traceItemAttributeContext';
11+
import {TraceItemDataset} from 'sentry/views/explore/types';
12+
import {limitMaxPickableDays} from 'sentry/views/explore/utils';
13+
import {InsightsEnvironmentSelector} from 'sentry/views/insights/common/components/enviornmentSelector';
14+
import {ModuleFeature} from 'sentry/views/insights/common/components/moduleFeature';
15+
import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout';
16+
import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders';
17+
import {InsightsProjectSelector} from 'sentry/views/insights/common/components/projectSelector';
18+
import {ToolRibbon} from 'sentry/views/insights/common/components/ribbon';
19+
import {useDefaultToAllProjects} from 'sentry/views/insights/common/utils/useDefaultToAllProjects';
20+
import TokenCostWidget from 'sentry/views/insights/pages/agents/components/modelCostWidget';
21+
import {ModelsTable} from 'sentry/views/insights/pages/agents/components/modelsTable';
22+
import {WidgetGrid} from 'sentry/views/insights/pages/agents/components/styles';
23+
import TokenTypesWidget from 'sentry/views/insights/pages/agents/components/tokenTypesWidget';
24+
import TokenUsageWidget from 'sentry/views/insights/pages/agents/components/tokenUsageWidget';
25+
import {useAgentSpanSearchProps} from 'sentry/views/insights/pages/agents/hooks/useAgentSpanSearchProps';
26+
import {useShowAgentOnboarding} from 'sentry/views/insights/pages/agents/hooks/useShowAgentOnboarding';
27+
import {Onboarding} from 'sentry/views/insights/pages/agents/onboarding';
28+
import {TableUrlParams} from 'sentry/views/insights/pages/agents/utils/urlParams';
29+
import {ModuleName} from 'sentry/views/insights/types';
30+
31+
function AgentModelsLandingPage() {
32+
const organization = useOrganization();
33+
const showOnboarding = useShowAgentOnboarding();
34+
const datePageFilterProps = limitMaxPickableDays(organization);
35+
useDefaultToAllProjects();
36+
37+
const agentSpanSearchProps = useAgentSpanSearchProps();
38+
39+
return (
40+
<SearchQueryBuilderProvider {...agentSpanSearchProps.provider}>
41+
<ModuleFeature moduleName={ModuleName.AGENT_MODELS}>
42+
<Layout.Body>
43+
<Layout.Main width="full">
44+
<ModuleLayout.Layout>
45+
<ModuleLayout.Full>
46+
<ToolRibbon>
47+
<PageFilterBar condensed>
48+
<InsightsProjectSelector
49+
resetParamsOnChange={[TableUrlParams.CURSOR]}
50+
/>
51+
<InsightsEnvironmentSelector
52+
resetParamsOnChange={[TableUrlParams.CURSOR]}
53+
/>
54+
<DatePageFilter
55+
{...datePageFilterProps}
56+
resetParamsOnChange={[TableUrlParams.CURSOR]}
57+
/>
58+
</PageFilterBar>
59+
{!showOnboarding && (
60+
<Flex flex={2}>
61+
<EAPSpanSearchQueryBuilder {...agentSpanSearchProps.queryBuilder} />
62+
</Flex>
63+
)}
64+
</ToolRibbon>
65+
</ModuleLayout.Full>
66+
67+
<ModuleLayout.Full>
68+
{showOnboarding ? (
69+
<Onboarding />
70+
) : (
71+
<Fragment>
72+
<WidgetGrid rowHeight={260}>
73+
<WidgetGrid.Position1>
74+
<TokenCostWidget />
75+
</WidgetGrid.Position1>
76+
<WidgetGrid.Position2>
77+
<TokenUsageWidget />
78+
</WidgetGrid.Position2>
79+
<WidgetGrid.Position3>
80+
<TokenTypesWidget />
81+
</WidgetGrid.Position3>
82+
</WidgetGrid>
83+
<ModelsTable />
84+
</Fragment>
85+
)}
86+
</ModuleLayout.Full>
87+
</ModuleLayout.Layout>
88+
</Layout.Main>
89+
</Layout.Body>
90+
</ModuleFeature>
91+
</SearchQueryBuilderProvider>
92+
);
93+
}
94+
95+
function PageWithProviders() {
96+
return (
97+
<ModulePageProviders
98+
moduleName={ModuleName.AGENT_MODELS}
99+
analyticEventName="insight.page_loads.agent_models"
100+
>
101+
<TraceItemAttributeProvider traceItemType={TraceItemDataset.SPANS} enabled>
102+
<AgentModelsLandingPage />
103+
</TraceItemAttributeProvider>
104+
</ModulePageProviders>
105+
);
106+
}
107+
108+
export default PageWithProviders;
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('Tools');
4+
export const BASE_URL = 'tools';
5+
6+
export const DATA_TYPE = t('Tool');
7+
export const DATA_TYPE_PLURAL = t('Tools');
8+
9+
export const MODULE_DOC_LINK = 'https://docs.sentry.io/product/insights/agents/';
10+
11+
export const MODULE_FEATURES = [];

0 commit comments

Comments
 (0)