From c2c2552cc6f5a56623b1edf7d1fe1c1b723857bb Mon Sep 17 00:00:00 2001 From: Gaurav Tewari Date: Mon, 20 Jul 2026 13:30:39 +0530 Subject: [PATCH] feat: add llm observability to side navigation [1/3] (#12123) * feat: add llm o11y to side nav * chore: update comment --------- Co-authored-by: Gaurav Tewari --- frontend/src/container/SideNav/SideNav.tsx | 18 ++++++++++++++---- frontend/src/container/SideNav/menuItems.tsx | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/frontend/src/container/SideNav/SideNav.tsx b/frontend/src/container/SideNav/SideNav.tsx index a858e8811de..b1bfbe2be70 100644 --- a/frontend/src/container/SideNav/SideNav.tsx +++ b/frontend/src/container/SideNav/SideNav.tsx @@ -47,6 +47,7 @@ import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys'; import useComponentPermission from 'hooks/useComponentPermission'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import { useIsAIAssistantEnabled } from 'hooks/useIsAIAssistantEnabled'; +import { useIsAIObservabilityEnabled } from 'hooks/useIsAIObservabilityEnabled'; import { useNotifications } from 'hooks/useNotifications'; import history from 'lib/history'; import { isArray } from 'lodash-es'; @@ -253,6 +254,7 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { const isAdmin = user.role === USER_ROLES.ADMIN; const isEditor = user.role === USER_ROLES.EDITOR; const isAIAssistantEnabled = useIsAIAssistantEnabled(); + const isAIObservabilityEnabled = useIsAIObservabilityEnabled(); const aiAssistantActiveConversationId = useAIAssistantStore( (s) => s.activeConversationId, ); @@ -288,15 +290,22 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { const shouldShowIntegrationsValue = (isCloudUser || isEnterpriseSelfHostedUser) && (isAdmin || isEditor); + const isEnabledForItem = (item: SidebarItem): boolean | undefined => { + if (item.key === ROUTES.INTEGRATIONS) { + return shouldShowIntegrationsValue; + } + if (item.key === ROUTES.LLM_OBSERVABILITY_OVERVIEW) { + return isAIObservabilityEnabled; + } + return item.isEnabled; + }; + return defaultMoreMenuItems.map((item) => ({ ...item, isPinned: computedPinnedMenuItems.some( (pinned) => pinned.itemKey === item.itemKey, ), - isEnabled: - item.key === ROUTES.INTEGRATIONS - ? shouldShowIntegrationsValue - : item.isEnabled, + isEnabled: isEnabledForItem(item), })); }, [ computedPinnedMenuItems, @@ -304,6 +313,7 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { isEnterpriseSelfHostedUser, isAdmin, isEditor, + isAIObservabilityEnabled, ]); // Track if we've done the initial sync (to avoid overwriting user actions during session) diff --git a/frontend/src/container/SideNav/menuItems.tsx b/frontend/src/container/SideNav/menuItems.tsx index ea7b13958b9..068f2de2248 100644 --- a/frontend/src/container/SideNav/menuItems.tsx +++ b/frontend/src/container/SideNav/menuItems.tsx @@ -36,6 +36,7 @@ import { UserPlus, Users, Binoculars, + Brain, } from '@signozhq/icons'; import { @@ -288,6 +289,16 @@ export const defaultMoreMenuItems: SidebarItem[] = [ isEnabled: true, itemKey: 'external-apis', }, + { + key: ROUTES.LLM_OBSERVABILITY_OVERVIEW, + label: 'LLM Observability', + icon: , + isNew: true, + // Gated behind the `enable_ai_observability` feature flag in + // SideNav's `computedSecondaryMenuItems`; disabled by default. + isEnabled: false, + itemKey: 'llm-observability', + }, { key: ROUTES.METER, label: 'Cost Meter', @@ -553,7 +564,9 @@ export const getUserSettingsDropdownMenuItems = ({ }, ].filter(Boolean); -/** Mapping of some newly added routes and their corresponding active sidebar menu key */ +/** Mapping of some newly added routes and their corresponding active sidebar menu key + This is used to highlight the correct menu item when the user navigates to a new route +**/ export const NEW_ROUTES_MENU_ITEM_KEY_MAP: Record = { [ROUTES.TRACE]: ROUTES.TRACES_EXPLORER, [ROUTES.TRACE_EXPLORER]: ROUTES.TRACES_EXPLORER, @@ -563,6 +576,7 @@ export const NEW_ROUTES_MENU_ITEM_KEY_MAP: Record = { ROUTES.INFRASTRUCTURE_MONITORING_HOSTS, [ROUTES.API_MONITORING_BASE]: ROUTES.API_MONITORING, [ROUTES.MESSAGING_QUEUES_BASE]: ROUTES.MESSAGING_QUEUES_OVERVIEW, + [ROUTES.LLM_OBSERVABILITY_BASE]: ROUTES.LLM_OBSERVABILITY_OVERVIEW, // `getActiveMenuKeyFromPath` strips the URL down to its first segment; // `/ai-assistant/` reduces to `/ai-assistant`, which we point back // to the AI Assistant menu item's concrete key.