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.