diff --git a/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.test.tsx b/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.test.tsx
index 49870e51c2b..6a66e845675 100644
--- a/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.test.tsx
+++ b/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.test.tsx
@@ -403,6 +403,41 @@ describe("RequestLogsPanel", () => {
expect(drawer()).toHaveAttribute("data-session-id", "sess-1");
});
});
+
+ it("clicking a multi-call session's row writes ?session_id= alongside ?log_id=", async () => {
+ const user = userEvent.setup();
+ respondWith([
+ logEntry({ request_id: "req-llm", call_type: "acompletion", session_id: "sess-1", session_total_count: 3 }),
+ logEntry({ request_id: "req-llm-2", call_type: "acompletion", session_id: "sess-1", session_total_count: 3 }),
+ ]);
+ renderWithProviders();
+
+ await waitFor(() => expect(row("req-llm")).not.toBeNull());
+ await user.click(row("req-llm") as HTMLElement);
+
+ const params = new URLSearchParams(window.location.search);
+ expect(params.get("session_id")).toBe("sess-1");
+ expect(params.get("log_id")).toBe("req-llm");
+ await waitFor(() => expect(drawer()).toHaveAttribute("data-session-id", "sess-1"));
+ });
+
+ it("selecting another log while a session view is open keeps the session open", async () => {
+ const user = userEvent.setup();
+ window.history.replaceState(null, "", "/logs/?log_id=req-llm");
+ respondWith([
+ logEntry({ request_id: "req-llm", call_type: "acompletion", session_id: "sess-1", session_total_count: 3 }),
+ logEntry({ request_id: "req-unenriched" }),
+ ]);
+ renderWithProviders();
+
+ await waitFor(() => expect(drawer()).toHaveAttribute("data-session-id", "sess-1"));
+
+ await user.click(screen.getByRole("button", { name: "select-next-log" }));
+
+ await waitFor(() => expect(drawer()).toHaveAttribute("data-log-id", "req-unenriched"));
+ expect(new URLSearchParams(window.location.search).get("session_id")).toBe("sess-1");
+ expect(drawer()).toHaveAttribute("data-session-id", "sess-1");
+ });
});
describe("live tail", () => {
diff --git a/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.tsx b/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.tsx
index 06c8ca26a7e..aa3fa32bdc8 100644
--- a/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.tsx
+++ b/ui/litellm-dashboard/src/components/view_logs/RequestLogsPanel.tsx
@@ -235,9 +235,13 @@ export default function RequestLogsPanel({ accessToken, token, userRole, userID,
const handleRowClick = useCallback(
(log: LogEntry) => {
setSelectedLog(log);
- openLog(log.request_id);
+ if (log.session_id && (log.session_total_count || 1) > 1) {
+ openSession(log.session_id, log.request_id);
+ } else {
+ openLog(log.request_id);
+ }
},
- [openLog],
+ [openLog, openSession],
);
const handleSessionClick = useCallback(
@@ -253,9 +257,9 @@ export default function RequestLogsPanel({ accessToken, token, userRole, userID,
const handleSelectLog = useCallback(
(log: LogEntry) => {
setSelectedLog(log);
- selectLog(log.request_id);
+ selectLog(log.request_id, displaySessionId);
},
- [selectLog],
+ [selectLog, displaySessionId],
);
const handleKeyHashClick = useCallback((keyHash: string) => {
diff --git a/ui/litellm-dashboard/src/components/view_logs/logDetailRouting.ts b/ui/litellm-dashboard/src/components/view_logs/logDetailRouting.ts
index 5b311c94627..b37a4604585 100644
--- a/ui/litellm-dashboard/src/components/view_logs/logDetailRouting.ts
+++ b/ui/litellm-dashboard/src/components/view_logs/logDetailRouting.ts
@@ -11,7 +11,7 @@ export interface LogDetailRouting {
sessionId: string | null;
openLog: (requestId: string) => void;
openSession: (sessionId: string, requestId: string | null) => void;
- selectLog: (requestId: string) => void;
+ selectLog: (requestId: string, sessionId?: string | null) => void;
close: () => void;
}
@@ -36,9 +36,12 @@ export function useLogDetailRouting(): LogDetailRouting {
});
}, []);
- const selectLog = useCallback((requestId: string) => {
+ const selectLog = useCallback((requestId: string, sessionId?: string | null) => {
navigateWithParams((params) => {
params.set(LOG_ID_QUERY_PARAM, requestId);
+ if (sessionId) {
+ params.set(SESSION_ID_QUERY_PARAM, sessionId);
+ }
}, "replace");
}, []);