Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions static/app/components/sidebar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ import {useLocation} from 'sentry/utils/useLocation';
import useMedia from 'sentry/utils/useMedia';
import useOrganization from 'sentry/utils/useOrganization';
import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
import {
AGENTS_LANDING_SUB_PATH,
AGENTS_SIDEBAR_LABEL,
} from 'sentry/views/insights/pages/agents/settings';
import {
AI_LANDING_SUB_PATH,
AI_SIDEBAR_LABEL,
Expand Down Expand Up @@ -380,13 +385,26 @@ function Sidebar() {
id="performance-domains-mobile"
icon={<SubitemDot collapsed />}
/>
<SidebarItem
{...sidebarItemProps}
label={AI_SIDEBAR_LABEL}
to={`/organizations/${organization.slug}/${DOMAIN_VIEW_BASE_URL}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[AI_LANDING_SUB_PATH]}/`}
id="performance-domains-ai"
icon={<SubitemDot collapsed />}
/>
<AgentInsightsFeature
organization={organization}
renderDisabled={() => (
<SidebarItem
{...sidebarItemProps}
label={AI_SIDEBAR_LABEL}
to={`/organizations/${organization.slug}/${DOMAIN_VIEW_BASE_URL}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[AI_LANDING_SUB_PATH]}/`}
id="performance-domains-ai"
icon={<SubitemDot collapsed />}
/>
)}
>
<SidebarItem
{...sidebarItemProps}
label={AGENTS_SIDEBAR_LABEL}
to={`/organizations/${organization.slug}/${DOMAIN_VIEW_BASE_URL}/${AGENTS_LANDING_SUB_PATH}/${MODULE_BASE_URLS[AGENTS_LANDING_SUB_PATH]}/`}
id="performance-domains-agents"
icon={<SubitemDot collapsed />}
/>
</AgentInsightsFeature>
</SidebarAccordion>
</Feature>
);
Expand Down
11 changes: 11 additions & 0 deletions static/app/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import AuthLayout from 'sentry/views/auth/layout';
import {automationRoutes} from 'sentry/views/automations/routes';
import {detectorRoutes} from 'sentry/views/detectors/routes';
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
import {AGENTS_LANDING_SUB_PATH} from 'sentry/views/insights/pages/agents/settings';
import {AI_LANDING_SUB_PATH} from 'sentry/views/insights/pages/ai/settings';
import {BACKEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/backend/settings';
import {FRONTEND_LANDING_SUB_PATH} from 'sentry/views/insights/pages/frontend/settings';
Expand Down Expand Up @@ -1797,6 +1798,16 @@ function buildRoutes() {
{traceViewRoute}
{moduleRoutes}
</Route>
<Route path={`${AGENTS_LANDING_SUB_PATH}/`}>
<IndexRoute
component={make(
() => import('sentry/views/insights/agentMonitoring/views/agentsOverviewPage')
)}
/>
{transactionSummaryRoutes}
{traceViewRoute}
{moduleRoutes}
</Route>
<Route path="projects/" component={make(() => import('sentry/views/projects/'))}>
{projectsChildRoutes}
</Route>
Expand Down
2 changes: 2 additions & 0 deletions static/app/utils/analytics/insightAnalyticEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type InsightEventParameters = {
'insight.general.select_region_value': {regions: string[]};
'insight.general.table_paginate': {direction: string; source: string};
'insight.general.table_sort': {direction: string; field: string; source: string};
'insight.page_loads.agents': {has_ever_sent_data: boolean; view: DomainView};
'insight.page_loads.ai': {has_ever_sent_data: boolean; view: DomainView};
'insight.page_loads.app_start': {has_ever_sent_data: boolean; view: DomainView};
'insight.page_loads.assets': {has_ever_sent_data: boolean; view: DomainView};
Expand Down Expand Up @@ -55,6 +56,7 @@ export type InsightEventKey = keyof InsightEventParameters;
export const insightEventMap: Record<InsightEventKey, string | null> = {
'insights.page_loads.overview': 'Insights: Overview Page Load',
'insight.page_loads.ai': 'Insights: AI Page Load',
'insight.page_loads.agents': 'Insights: Agents Page Load',
'insight.page_loads.app_start': 'Insights: App Start Page Load',
'insight.page_loads.assets': 'Insights: Assets Page Load',
'insight.page_loads.cache': 'Insights: Cache Page Load',
Expand Down
11 changes: 11 additions & 0 deletions static/app/views/insights/agentMonitoring/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {t} from 'sentry/locale';

export const MODULE_TITLE = t('Overview');
export const BASE_URL = '';

export const DATA_TYPE = t('Agent');
export const DATA_TYPE_PLURAL = t('Agents');

export const MODULE_DOC_LINK = 'https://docs.sentry.io/product/insights/ai/';

export const MODULE_FEATURES = ['insights-addon-modules', 'agents-insights'];
17 changes: 17 additions & 0 deletions static/app/views/insights/agentMonitoring/utils/features.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Feature from 'sentry/components/acl/feature';
import {NoAccess} from 'sentry/components/noAccess';
import type {Organization} from 'sentry/types/organization';

export function hasAgentInsights(organization: Organization) {
return organization.features.includes('agents-insights');
}

type AgentInsightsFeatureProps = Omit<Parameters<typeof Feature>[0], 'features'>;

export function AgentInsightsFeature(props: AgentInsightsFeatureProps) {
return (
<Feature features="agents-insights" renderDisabled={props.renderDisabled ?? NoAccess}>
{props.children}
</Feature>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import styled from '@emotion/styled';

import * as Layout from 'sentry/components/layouts/thirds';
import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout';
import {ModulePageFilterBar} from 'sentry/views/insights/common/components/modulePageFilterBar';
import {ModulePageProviders} from 'sentry/views/insights/common/components/modulePageProviders';
import {ModuleBodyUpsellHook} from 'sentry/views/insights/common/components/moduleUpsellHookWrapper';
import {AgentsPageHeader} from 'sentry/views/insights/pages/agents/agentsPageHeader';
import {ModuleName} from 'sentry/views/insights/types';

function AgentsMonitoringPage() {
return (
<Layout.Page>
<AgentsPageHeader module={ModuleName.AGENTS} />
<ModuleBodyUpsellHook moduleName={ModuleName.AGENTS}>
<Layout.Body>
<Layout.Main fullWidth>
<ModuleLayout.Layout>
<ModuleLayout.Full>
<ModulePageFilterBar moduleName={ModuleName.AGENTS} />
</ModuleLayout.Full>
<ModuleLayout.Full>
<DashboardPlaceholder>Agent Monitoring Dashboard</DashboardPlaceholder>
</ModuleLayout.Full>
</ModuleLayout.Layout>
</Layout.Main>
</Layout.Body>
</ModuleBodyUpsellHook>
</Layout.Page>
);
}

function PageWithProviders() {
return (
<AgentInsightsFeature>
<ModulePageProviders
moduleName={ModuleName.AGENTS}
analyticEventName="insight.page_loads.agents"
>
<AgentsMonitoringPage />
</ModulePageProviders>
</AgentInsightsFeature>
);
}

const DashboardPlaceholder = styled('div')`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: ${p => p.theme.gray300};
font-size: ${p => p.theme.fontSizeLarge};
font-weight: ${p => p.theme.fontWeightBold};
`;

export default PageWithProviders;
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ const EMPTY_STATE_CONTENT: Record<TitleableModuleNames, EmptyStateContent> = {
imageSrc: llmPreviewImg,
supportedSdks: ['python'],
},
agents: {
heading: t('TODO'),
description: t('TODO'),
valuePropDescription: t('Mobile UI load insights include:'),
valuePropPoints: [],
imageSrc: screenLoadsPreviewImg,
},
'mobile-ui': {
heading: t('TODO'),
description: t('TODO'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const excludedModuleNames = [
ModuleName.CRONS,
ModuleName.UPTIME,
ModuleName.SESSIONS,
ModuleName.AGENTS,
] as const;

type ExcludedModuleNames = (typeof excludedModuleNames)[number];
Expand Down
2 changes: 2 additions & 0 deletions static/app/views/insights/common/utils/useModuleURL.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import useOrganization from 'sentry/utils/useOrganization';
import {BASE_URL as AGENTS_BASE_URL} from 'sentry/views/insights/agentMonitoring/settings';
import {BASE_URL as RESOURCES_BASE_URL} from 'sentry/views/insights/browser/resources/settings';
import {BASE_URL as VITALS_BASE_URL} from 'sentry/views/insights/browser/webVitals/settings';
import {BASE_URL as CACHE_BASE_URL} from 'sentry/views/insights/cache/settings';
Expand Down Expand Up @@ -33,6 +34,7 @@ export const MODULE_BASE_URLS: Record<ModuleName, string> = {
[ModuleName.VITAL]: VITALS_BASE_URL,
[ModuleName.RESOURCE]: RESOURCES_BASE_URL,
[ModuleName.AI]: AI_BASE_URL,
[ModuleName.AGENTS]: AGENTS_BASE_URL,
[ModuleName.MOBILE_UI]: MOBILE_UI_BASE_URL,
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_BASE_URL,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_BASE_URL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,6 @@ const LABEL_FOR_MODULE_NAME: Record<ModuleName, ReactNode> = {
'mobile-vitals': t('Action'),
'screen-rendering': t('Action'),
ai: 'Action',
agents: t('Action'),
sessions: t('Action'),
};
51 changes: 51 additions & 0 deletions static/app/views/insights/pages/agents/agentsPageHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import normalizeUrl from 'sentry/utils/url/normalizeUrl';
import useOrganization from 'sentry/utils/useOrganization';
import {
AGENTS_LANDING_SUB_PATH,
AGENTS_LANDING_TITLE,
MODULES,
} from 'sentry/views/insights/pages/agents/settings';
import {
DomainViewHeader,
type Props as HeaderProps,
} from 'sentry/views/insights/pages/domainViewHeader';
import {DOMAIN_VIEW_BASE_URL} from 'sentry/views/insights/pages/settings';

type Props = {
breadcrumbs?: HeaderProps['additionalBreadCrumbs'];
headerActions?: HeaderProps['additonalHeaderActions'];
headerTitle?: HeaderProps['headerTitle'];
hideDefaultTabs?: HeaderProps['hideDefaultTabs'];
module?: HeaderProps['selectedModule'];
tabs?: HeaderProps['tabs'];
};

export function AgentsPageHeader({
module,
headerTitle,
headerActions,
breadcrumbs,
tabs,
hideDefaultTabs,
}: Props) {
const {slug} = useOrganization();

const agentsBaseUrl = normalizeUrl(
`/organizations/${slug}/${DOMAIN_VIEW_BASE_URL}/${AGENTS_LANDING_SUB_PATH}`
);

return (
<DomainViewHeader
hasOverviewPage={false}
domainBaseUrl={agentsBaseUrl}
headerTitle={headerTitle}
domainTitle={AGENTS_LANDING_TITLE}
modules={MODULES}
selectedModule={module}
additonalHeaderActions={headerActions}
additionalBreadCrumbs={breadcrumbs}
tabs={tabs}
hideDefaultTabs={hideDefaultTabs}
/>
);
}
8 changes: 8 additions & 0 deletions static/app/views/insights/pages/agents/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {t} from 'sentry/locale';
import {ModuleName} from 'sentry/views/insights/types';

export const AGENTS_LANDING_SUB_PATH = 'agents';
export const AGENTS_LANDING_TITLE = t('Agents');
export const AGENTS_SIDEBAR_LABEL = t('Agents');

export const MODULES = [ModuleName.AGENTS];
13 changes: 13 additions & 0 deletions static/app/views/insights/settings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import {t} from 'sentry/locale';
import {
DATA_TYPE as AGENTS_DATA_TYPE,
DATA_TYPE_PLURAL as AGENTS_DATA_TYPE_PLURAL,
MODULE_DOC_LINK as AGENTS_MODULE_DOC_LINK,
MODULE_FEATURES as AGENTS_MODULE_FEATURES,
MODULE_TITLE as AGENTS_MODULE_TITLE,
} from 'sentry/views/insights/agentMonitoring/settings';
import {
DATA_TYPE as RESOURCE_DATA_TYPE,
DATA_TYPE_PLURAL as RESOURCE_DATA_TYPE_PLURAL,
Expand Down Expand Up @@ -128,6 +135,7 @@ export const MODULE_TITLES: Record<ModuleName, string> = {
[ModuleName.VITAL]: VITALS_MODULE_TITLE,
[ModuleName.RESOURCE]: RESOURCES_MODULE_TITLE,
[ModuleName.AI]: AI_MODULE_TITLE,
[ModuleName.AGENTS]: AGENTS_MODULE_TITLE,
[ModuleName.MOBILE_UI]: MOBILE_UI_MODULE_TITLE,
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_MODULE_TITLE,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_MODULE_TITLE,
Expand All @@ -147,6 +155,7 @@ export const MODULE_DATA_TYPES: Record<ModuleName, string> = {
[ModuleName.VITAL]: WEB_VITALS_DATA_TYPE,
[ModuleName.RESOURCE]: RESOURCE_DATA_TYPE,
[ModuleName.AI]: AI_DATA_TYPE,
[ModuleName.AGENTS]: AGENTS_DATA_TYPE,
[ModuleName.MOBILE_UI]: t('Mobile UI'),
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_DATA_TYPE,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_DATA_TYPE,
Expand All @@ -166,6 +175,7 @@ export const MODULE_DATA_TYPES_PLURAL: Record<ModuleName, string> = {
[ModuleName.VITAL]: WEB_VITALS_DATA_TYPE_PLURAL,
[ModuleName.RESOURCE]: RESOURCE_DATA_TYPE_PLURAL,
[ModuleName.AI]: AI_DATA_TYPE_PLURAL,
[ModuleName.AGENTS]: AGENTS_DATA_TYPE_PLURAL,
[ModuleName.MOBILE_UI]: t('Mobile UI'),
[ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_DATA_TYPE_PLURAL,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_DATA_TYPE_PLURAL,
Expand All @@ -188,6 +198,7 @@ export const MODULE_PRODUCT_DOC_LINKS = {
[ModuleName.VITAL]: VITALS_MODULE_DOC_LINK,
[ModuleName.RESOURCE]: RESOURCES_MODULE_DOC_LINK,
[ModuleName.AI]: AI_MODULE_DOC_LINK,
[ModuleName.AGENTS]: AGENTS_MODULE_DOC_LINK,
[ModuleName.MOBILE_UI]: MODULE_UI_DOC_LINK,
[ModuleName.MOBILE_VITALS]: MODULE_SCREENS_DOC_LINK,
[ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_MODULE_DOC_LINK,
Expand All @@ -212,6 +223,7 @@ export const MODULE_FEATURE_MAP: Record<ModuleName, string[]> = {
[ModuleName.CACHE]: CACHE_MODULE_FEATURES,
[ModuleName.QUEUE]: QUEUE_MODULE_FEATURES,
[ModuleName.AI]: AI_MODULE_FEATURES,
[ModuleName.AGENTS]: AGENTS_MODULE_FEATURES,
[ModuleName.SCREEN_LOAD]: SCREEN_LOADS_MODULE_FEATURES,
[ModuleName.MOBILE_UI]: MOBILE_UI_MODULE_FEATURES,
[ModuleName.MOBILE_VITALS]: [MOBILE_SCREENS_MODULE_FEATURE],
Expand All @@ -234,6 +246,7 @@ export const MODULE_FEATURE_VISIBLE_MAP: Record<ModuleName, string[]> = {
[ModuleName.CACHE]: ['insights-entry-points'],
[ModuleName.QUEUE]: ['insights-entry-points'],
[ModuleName.AI]: ['insights-entry-points'],
[ModuleName.AGENTS]: ['insights-entry-points'],
[ModuleName.SCREEN_LOAD]: ['insights-entry-points'],
[ModuleName.MOBILE_UI]: ['insights-entry-points'],
[ModuleName.MOBILE_VITALS]: ['insights-entry-points'],
Expand Down
1 change: 1 addition & 0 deletions static/app/views/insights/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum ModuleName {
APP_START = 'app_start',
RESOURCE = 'resource',
AI = 'ai',
AGENTS = 'agents',
MOBILE_UI = 'mobile-ui',
MOBILE_VITALS = 'mobile-vitals',
SCREEN_RENDERING = 'screen-rendering',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import type {Project} from 'sentry/types/project';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import useProjects from 'sentry/utils/useProjects';
import {AgentInsightsFeature} from 'sentry/views/insights/agentMonitoring/utils/features';
import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
import {
AGENTS_LANDING_SUB_PATH,
AGENTS_SIDEBAR_LABEL,
} from 'sentry/views/insights/pages/agents/settings';
import {
AI_LANDING_SUB_PATH,
AI_SIDEBAR_LABEL,
Expand Down Expand Up @@ -91,12 +96,25 @@ export function InsightsSecondaryNav() {
>
{MOBILE_SIDEBAR_LABEL}
</SecondaryNav.Item>
<SecondaryNav.Item
to={`${baseUrl}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[ModuleName.AI]}/`}
analyticsItemName="insights_ai"

<AgentInsightsFeature
organization={organization}
renderDisabled={() => (
<SecondaryNav.Item
to={`${baseUrl}/${AI_LANDING_SUB_PATH}/${MODULE_BASE_URLS[ModuleName.AI]}/`}
analyticsItemName="insights_ai"
>
{AI_SIDEBAR_LABEL}
</SecondaryNav.Item>
)}
>
{AI_SIDEBAR_LABEL}
</SecondaryNav.Item>
<SecondaryNav.Item
to={`${baseUrl}/${AGENTS_LANDING_SUB_PATH}/`}
analyticsItemName="insights_agents"
>
{AGENTS_SIDEBAR_LABEL}
</SecondaryNav.Item>
</AgentInsightsFeature>
</SecondaryNav.Section>
<SecondaryNav.Section id="insights-projects-all">
<SecondaryNav.Item
Expand Down
Loading