From 440277c97b1b8b1c9a1caf121796e6f1edbfdb26 Mon Sep 17 00:00:00 2001 From: Yucheng Zhu Date: Wed, 29 Jul 2026 16:19:46 -0700 Subject: [PATCH] fix(ui): keep non-OTEL logging callbacks in the Add Callback list The Add Logging Callback dropdown was filtering out langfuse (v2 SDK), otel (Open Telemetry), and the other non-OTEL callbacks along with the OTEL trace destinations, so those integrations disappeared from the UI. Restrict the destination filtering to the OTEL trace-destination backends only (arize, langfuse_otel, weave_otel, generic), so non-OTEL logging callbacks keep their existing global-callback path. Also relabel the langfuse_otel destination to "Langfuse OTEL" so it is distinct from the Langfuse SDK entry, collapse the duplicate destination-id set into a single LOGGING_BACKEND_IDS, and format the logging UI files. --- .../logging_credentials/AccessControlFields.tsx | 15 +++------------ .../logging_credentials/loggingCredentialApi.ts | 17 +++++------------ .../loggingDestinationFields.ts | 2 +- .../organization/organization_view.tsx | 2 -- .../src/components/settings.test.tsx | 4 ++-- .../src/components/settings.tsx | 11 +++-------- .../src/components/templates/key_edit_view.tsx | 2 +- 7 files changed, 15 insertions(+), 38 deletions(-) diff --git a/ui/litellm-dashboard/src/components/logging_credentials/AccessControlFields.tsx b/ui/litellm-dashboard/src/components/logging_credentials/AccessControlFields.tsx index 66bcf4e5bdb..9c7eab205eb 100644 --- a/ui/litellm-dashboard/src/components/logging_credentials/AccessControlFields.tsx +++ b/ui/litellm-dashboard/src/components/logging_credentials/AccessControlFields.tsx @@ -28,16 +28,10 @@ const AccessControlFields: React.FC = ({ value = {}, o return ( <> - + onChange({ ...value, global })} /> - + = new Set(LOGGING_DESTINATION_BACKENDS.map((b) => b.id)); -// Callback ids that must not surface as global callbacks. Per LIT-3850 OTEL is admin- -// owned and routed per identity via trace destinations, and the legacy Langfuse/OTEL -// callback paths (`langfuse` v2 SDK, `langfuse_otel` v1, the generic `otel` callback) -// are deprecated, so these are only ever destinations -- never callback rows or options. -export const NON_CALLBACK_LOGGING_IDS: ReadonlySet = new Set([ - ...LOGGING_DESTINATION_BACKENDS.map((b) => b.id), - "langfuse", - "otel", -]); - export const backendLabel = (id?: string): string => LOGGING_DESTINATION_BACKENDS.find((b) => b.id === id)?.label ?? id ?? "-"; diff --git a/ui/litellm-dashboard/src/components/logging_credentials/loggingDestinationFields.ts b/ui/litellm-dashboard/src/components/logging_credentials/loggingDestinationFields.ts index 2c63e969b21..d861191db2d 100644 --- a/ui/litellm-dashboard/src/components/logging_credentials/loggingDestinationFields.ts +++ b/ui/litellm-dashboard/src/components/logging_credentials/loggingDestinationFields.ts @@ -27,7 +27,7 @@ export interface LoggingDestinationBackend { export const LOGGING_DESTINATION_BACKENDS: LoggingDestinationBackend[] = [ { id: "langfuse_otel", - label: "Langfuse", + label: "Langfuse OTEL", fields: [ { name: "langfuse_host", diff --git a/ui/litellm-dashboard/src/components/organization/organization_view.tsx b/ui/litellm-dashboard/src/components/organization/organization_view.tsx index 2d213045e85..e96296b1b39 100644 --- a/ui/litellm-dashboard/src/components/organization/organization_view.tsx +++ b/ui/litellm-dashboard/src/components/organization/organization_view.tsx @@ -258,7 +258,6 @@ const OrganizationInfoView: React.FC = ({ loggingExporterBadges.map((exporter, index) => ( {exporter.name} - )) ) : ( @@ -360,7 +359,6 @@ const OrganizationInfoView: React.FC = ({ {loggingExporterBadges.map((exporter, index) => ( {exporter.name} - ))} diff --git a/ui/litellm-dashboard/src/components/settings.test.tsx b/ui/litellm-dashboard/src/components/settings.test.tsx index a400bd4ca4d..6c255deac7b 100644 --- a/ui/litellm-dashboard/src/components/settings.test.tsx +++ b/ui/litellm-dashboard/src/components/settings.test.tsx @@ -137,8 +137,8 @@ describe("Settings", () => { }); it("should display edit modal with fields when edit is clicked", async () => { - // Use a config callback that is NOT a logging-destination backend (langfuse, - // arize, etc. are filtered from the table via NON_CALLBACK_LOGGING_IDS and + // Use a config callback that is NOT a logging-destination backend (arize, + // langfuse_otel, etc. are filtered from the table via LOGGING_BACKEND_IDS and // edited through the destination flow instead). Datadog is a plain config // callback, so it still renders a row with the legacy Test/Edit/Delete actions. const mockCallback = { diff --git a/ui/litellm-dashboard/src/components/settings.tsx b/ui/litellm-dashboard/src/components/settings.tsx index c03a2dc329d..bcad61c56fd 100644 --- a/ui/litellm-dashboard/src/components/settings.tsx +++ b/ui/litellm-dashboard/src/components/settings.tsx @@ -47,12 +47,7 @@ import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; import { useOrganizations } from "@/app/(dashboard)/hooks/organizations/useOrganizations"; import EditLoggingCredentialModal from "./logging_credentials/EditLoggingCredentialModal"; import AccessControlFields from "./logging_credentials/AccessControlFields"; -import { - backendLabel, - createLoggingCredential, - LOGGING_BACKEND_IDS, - NON_CALLBACK_LOGGING_IDS, -} from "./logging_credentials/loggingCredentialApi"; +import { backendLabel, createLoggingCredential, LOGGING_BACKEND_IDS } from "./logging_credentials/loggingCredentialApi"; import { LOGGING_DESTINATION_BACKENDS } from "./logging_credentials/loggingDestinationFields"; import { parseErrorMessage } from "./shared/errorUtils"; interface SettingsPageProps { @@ -675,7 +670,7 @@ const Settings: React.FC = ({ accessToken, userRole, userID, !NON_CALLBACK_LOGGING_IDS.has(c.name)), ...destinationRows]} + callbacks={[...callbacks.filter((c) => !LOGGING_BACKEND_IDS.has(c.name)), ...destinationRows]} availableCallbacks={allCallbacks} isLoading={isLoadingCallbacks} readOnly={!isProxyAdmin} @@ -840,7 +835,7 @@ const Settings: React.FC = ({ accessToken, userRole, userID, > !NON_CALLBACK_LOGGING_IDS.has(c.id)), + ...callbackConfigs.filter((c: { id: string }) => !LOGGING_BACKEND_IDS.has(c.id)), ...LOGGING_DESTINATION_BACKENDS.map((b) => ({ id: b.id, displayName: b.label, logo: "" })), ]} selectedCallback={selectedCallback} diff --git a/ui/litellm-dashboard/src/components/templates/key_edit_view.tsx b/ui/litellm-dashboard/src/components/templates/key_edit_view.tsx index 468e6f10a9f..310c5240e01 100644 --- a/ui/litellm-dashboard/src/components/templates/key_edit_view.tsx +++ b/ui/litellm-dashboard/src/components/templates/key_edit_view.tsx @@ -239,7 +239,7 @@ export function KeyEditView({ mcp_tool_permissions: keyData.object_permission?.mcp_tool_permissions || {}, throttle_on_budget_exceeded: keyData.metadata?.throttle_on_budget_exceeded || false, logging_settings: extractLoggingSettings(keyData.metadata), - disabled_callbacks: Array.isArray(keyData.metadata?.litellm_disabled_callbacks) + disabled_callbacks: Array.isArray(keyData.metadata?.litellm_disabled_callbacks) ? mapInternalToDisplayNames(keyData.metadata.litellm_disabled_callbacks) : [], access_group_ids: keyData.access_group_ids || [],