From d6c562a35da1f4198e3c8f5a67a2b181abacdd82 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Fri, 20 Feb 2026 14:55:15 -0800 Subject: [PATCH] address greptile review feedback + UI refinements for retry display - Show "-" when retry info is absent (older logs) - Show green "None" tag when not retried (attempted_retries === 0) - Update max_retries after deployment/retry-policy overrides (greptile feedback) - Update tests to match new display behavior Co-Authored-By: Claude Opus 4.6 --- litellm/router.py | 5 ++++- .../LogDetailsDrawer/LogDetailContent.tsx | 12 +++++------ .../src/components/view_logs/index.test.tsx | 9 +++++---- .../src/components/view_logs/index.tsx | 20 +++++++++---------- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/litellm/router.py b/litellm/router.py index a7fa6129c1..b1337159e5 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -5130,7 +5130,7 @@ class Router: ) ## ADD RETRY TRACKING TO METADATA - used for spend logs retry tracking _metadata["attempted_retries"] = 0 - _metadata["max_retries"] = num_retries + _metadata["max_retries"] = num_retries # Updated after overrides in exception handler try: self._handle_mock_testing_rate_limit_error( model_group=model_group, kwargs=kwargs @@ -5196,6 +5196,9 @@ class Router: regular_fallbacks=fallbacks, content_policy_fallbacks=content_policy_fallbacks, ) + # Update max_retries after overrides (deployment_num_retries / retry_policy) + _metadata["max_retries"] = num_retries + ## LOGGING if num_retries > 0: kwargs = self.log_retry(kwargs=kwargs, e=original_exception) diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.tsx index 30a884a009..be25eed8ec 100644 --- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.tsx @@ -296,13 +296,13 @@ function MetricsSection({ logEntry, metadata }: { logEntry: LogEntry; metadata: )} - {metadata?.attempted_retries !== undefined && metadata?.attempted_retries !== null && ( - - {metadata.attempted_retries > 0 + + {metadata?.attempted_retries !== undefined && metadata?.attempted_retries !== null + ? metadata.attempted_retries > 0 ? <>{metadata.attempted_retries}{metadata.max_retries !== undefined && metadata.max_retries !== null ? ` / ${metadata.max_retries}` : ''} - : "Not Retried"} - - )} + : None + : "-"} + {moment(logEntry.startTime).format("YYYY-MM-DDTHH:mm:ss.SSS[Z]")} diff --git a/ui/litellm-dashboard/src/components/view_logs/index.test.tsx b/ui/litellm-dashboard/src/components/view_logs/index.test.tsx index 61d96f72ce..7d4fc98111 100644 --- a/ui/litellm-dashboard/src/components/view_logs/index.test.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/index.test.tsx @@ -145,7 +145,7 @@ describe("Request Viewer", () => { expect(screen.getByText("2 / 3")).toBeInTheDocument(); }); - it("should display 'Not Retried' when attempted_retries is 0", () => { + it("should display green 'None' tag when attempted_retries is 0", () => { render( { ); expect(screen.getByText("Retries:")).toBeInTheDocument(); - expect(screen.getByText("Not Retried")).toBeInTheDocument(); + expect(screen.getByText("None")).toBeInTheDocument(); }); - it("should not display Retries when attempted_retries is not present in metadata", () => { + it("should display '-' for Retries when attempted_retries is not present in metadata", () => { render(); - expect(screen.queryByText("Retries:")).not.toBeInTheDocument(); + expect(screen.getByText("Retries:")).toBeInTheDocument(); + expect(screen.getByText("-")).toBeInTheDocument(); }); }); diff --git a/ui/litellm-dashboard/src/components/view_logs/index.tsx b/ui/litellm-dashboard/src/components/view_logs/index.tsx index 153acdc9ca..a3f40aff99 100644 --- a/ui/litellm-dashboard/src/components/view_logs/index.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/index.tsx @@ -7,7 +7,7 @@ import { truncateString } from "@/utils/textUtils"; import { SettingOutlined, SyncOutlined } from "@ant-design/icons"; import { Row } from "@tanstack/react-table"; import { Switch, Tab, TabGroup, TabList, TabPanel, TabPanels } from "@tremor/react"; -import { Button, Tooltip } from "antd"; +import { Button, Tag, Tooltip } from "antd"; import { internalUserRoles } from "../../utils/roles"; import DeletedKeysPage from "../DeletedKeysPage/DeletedKeysPage"; import DeletedTeamsPage from "../DeletedTeamsPage/DeletedTeamsPage"; @@ -960,16 +960,16 @@ export function RequestViewer({ row, onOpenSettings }: { row: Row; onO {row.original.metadata.litellm_overhead_time_ms} ms )} - {row.original.metadata?.attempted_retries !== undefined && row.original.metadata?.attempted_retries !== null && ( -
- Retries: - - {row.original.metadata.attempted_retries > 0 +
+ Retries: + + {row.original.metadata?.attempted_retries !== undefined && row.original.metadata?.attempted_retries !== null + ? row.original.metadata.attempted_retries > 0 ? `${row.original.metadata.attempted_retries}${row.original.metadata.max_retries !== undefined && row.original.metadata.max_retries !== null ? ` / ${row.original.metadata.max_retries}` : ''}` - : 'Not Retried'} - -
- )} + : None + : '-'} +
+