diff --git a/litellm/litellm_core_utils/litellm_logging.py b/litellm/litellm_core_utils/litellm_logging.py index e88de4acd0e..9ba9fd082f3 100644 --- a/litellm/litellm_core_utils/litellm_logging.py +++ b/litellm/litellm_core_utils/litellm_logging.py @@ -6021,7 +6021,6 @@ def _get_status_fields( "failure": "guardrail_failed_to_respond", # legacy "guardrail_failed_to_respond": "guardrail_failed_to_respond", # direct "not_run": "not_run", - "skipped": "not_run", } # Set LLM API status diff --git a/litellm/llms/openai/chat/guardrail_translation/handler.py b/litellm/llms/openai/chat/guardrail_translation/handler.py index dca90e07421..0f5096d0108 100644 --- a/litellm/llms/openai/chat/guardrail_translation/handler.py +++ b/litellm/llms/openai/chat/guardrail_translation/handler.py @@ -214,7 +214,7 @@ class OpenAIChatCompletionsHandler(BaseTranslation): guardrail_to_apply.add_standard_logging_guardrail_information_to_request_data( guardrail_json_response="no scannable content after message scoping", request_data=data, - guardrail_status="skipped", + guardrail_status="not_run", ) verbose_proxy_logger.debug( diff --git a/litellm/proxy/compliance_checks.py b/litellm/proxy/compliance_checks.py index ef2d8fb6e20..d9cc1d0f4fc 100644 --- a/litellm/proxy/compliance_checks.py +++ b/litellm/proxy/compliance_checks.py @@ -26,7 +26,7 @@ class ComplianceChecker: def __init__(self, data: ComplianceCheckRequest): self.data = data - self.guardrails = [g for g in (data.guardrail_information or []) if g.get("guardrail_status") != "skipped"] + self.guardrails = [g for g in (data.guardrail_information or []) if g.get("guardrail_status") != "not_run"] def _get_guardrails_by_mode(self, mode: str) -> list[dict]: """ diff --git a/litellm/proxy/guardrails/usage_endpoints.py b/litellm/proxy/guardrails/usage_endpoints.py index 651c4bb1963..556b6a4e919 100644 --- a/litellm/proxy/guardrails/usage_endpoints.py +++ b/litellm/proxy/guardrails/usage_endpoints.py @@ -42,7 +42,7 @@ if TYPE_CHECKING: router: Final = APIRouter() _EMPTY_UNITS: Final[Mapping[str, int]] = MappingProxyType({}) -_ACTION_SEVERITY: Final[Mapping[str, int]] = MappingProxyType({"skipped": 0, "passed": 1, "flagged": 2, "blocked": 3}) +_ACTION_SEVERITY: Final[Mapping[str, int]] = MappingProxyType({"not_run": 0, "passed": 1, "flagged": 2, "blocked": 3}) _T = TypeVar("_T") @@ -325,7 +325,7 @@ class UsageDetailResponse(BaseModel): class UsageLogEntry(BaseModel): id: str timestamp: str - action: str # blocked | passed | flagged | skipped + action: str # blocked | passed | flagged | not_run score: float | None latency_ms: float | None model: str | None diff --git a/litellm/proxy/guardrails/usage_tracking.py b/litellm/proxy/guardrails/usage_tracking.py index 8a131fbfcde..7e11b69108b 100644 --- a/litellm/proxy/guardrails/usage_tracking.py +++ b/litellm/proxy/guardrails/usage_tracking.py @@ -193,12 +193,12 @@ async def _upsert_rows_with_retry( def guardrail_status_to_action(status: str | None) -> str: - """Map StandardLogging guardrail_status to blocked/passed/flagged/skipped.""" + """Map StandardLogging guardrail_status to blocked/passed/flagged/not_run.""" if not status: return "passed" s: Final = (status or "").lower() - if s == "skipped": - return "skipped" + if s == "not_run": + return "not_run" if "intervened" in s or "block" in s: return "blocked" if "flagged" in s or "fail" in s or "error" in s: @@ -380,7 +380,7 @@ async def process_spend_logs_guardrail_usage( if not isinstance(guardrail_id, str) or not guardrail_id: continue action = guardrail_status_to_action(entry.get("guardrail_status")) - if action != "skipped": + if action != "not_run": key = _MetricsKey(guardrail_id, date_key) daily_guardrail[key]["requests_evaluated"] += 1 if action == "passed": diff --git a/litellm/types/utils.py b/litellm/types/utils.py index cf302b3f27f..1d73542c9bb 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3120,7 +3120,7 @@ class GuardrailMode(TypedDict, total=False): GuardrailStatus = Literal[ - "success", "guardrail_flagged", "guardrail_intervened", "guardrail_failed_to_respond", "not_run", "skipped" + "success", "guardrail_flagged", "guardrail_intervened", "guardrail_failed_to_respond", "not_run" ] # Fields on a guardrail record whose values can quote the caller's prompt: the payload sent to the @@ -3367,7 +3367,6 @@ class StandardLoggingPayloadStatusFields(TypedDict, total=False): - 'guardrail_intervened': Guardrail blocked or modified content - 'guardrail_failed_to_respond': Guardrail had technical failure - 'not_run': No guardrail was run - - 'skipped': Only used per guardrail entry, message scoping left the guardrail nothing to scan """ diff --git a/tests/test_litellm/litellm_core_utils/test_litellm_logging.py b/tests/test_litellm/litellm_core_utils/test_litellm_logging.py index 6e67781944e..70f9bae283b 100644 --- a/tests/test_litellm/litellm_core_utils/test_litellm_logging.py +++ b/tests/test_litellm/litellm_core_utils/test_litellm_logging.py @@ -6926,18 +6926,6 @@ def test_get_status_fields_ranks_guardrail_flagged_between_success_and_intervene )["guardrail_status"] == "guardrail_intervened" -def test_get_status_fields_rolls_skipped_entries_up_to_not_run(): - """LIT-6314: a guardrail that message scoping left nothing to scan records a - skipped entry. At request level that means no guardrail ran, and a skipped - entry must never outrank a sibling that did evaluate.""" - skipped = {"guardrail_status": "skipped"} - - assert _get_status_fields("success", [skipped], None)["guardrail_status"] == "not_run" - assert _get_status_fields( - "success", [skipped, {"guardrail_status": "success"}], None - )["guardrail_status"] == "success" - - def test_get_error_information_redacts_provider_key_from_upstream_url(): """A pass-through upstream failure logs the httpx traceback, whose message quotes the upstream URL with the provider key in its query string. That diff --git a/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py b/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py index c6d01db45de..4f1163ed806 100644 --- a/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py +++ b/tests/test_litellm/llms/openai/chat/guardrail_translation/test_openai_guardrail_handler.py @@ -1893,7 +1893,7 @@ class TestScanOnlyToolResults: assert data["messages"][4]["content"] == "and then?" -class TestNoScannableContentRecordsSkipped: +class TestNoScannableContentRecordsNotRun: """LIT-6314: a guardrail whose scoping leaves nothing to scan must still persist an evaluation record""" def _system_only_data(self) -> dict: @@ -1904,7 +1904,7 @@ class TestNoScannableContentRecordsSkipped: return metadata.get("standard_logging_guardrail_information") or [] @pytest.mark.asyncio - async def test_skipped_scan_records_skipped_entry(self): + async def test_skipped_scan_records_not_run_entry(self): handler = OpenAIChatCompletionsHandler() guardrail = MockGuardrail(guardrail_name="skip-system-guardrail") guardrail.skip_system_message_in_guardrail = True @@ -1916,7 +1916,7 @@ class TestNoScannableContentRecordsSkipped: entries = self._recorded_entries(data) assert len(entries) == 1 assert entries[0]["guardrail_name"] == "skip-system-guardrail" - assert entries[0]["guardrail_status"] == "skipped" + assert entries[0]["guardrail_status"] == "not_run" @pytest.mark.asyncio async def test_self_recording_guardrail_is_left_alone(self): @@ -1940,7 +1940,7 @@ class TestNoScannableContentRecordsSkipped: await handler.process_input_messages(data=data, guardrail_to_apply=guardrail) assert guardrail.last_inputs is not None - assert all(e.get("guardrail_status") != "skipped" for e in self._recorded_entries(data)) + assert all(e.get("guardrail_status") != "not_run" for e in self._recorded_entries(data)) class TestBuildBlockSseChunks: diff --git a/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py b/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py index 1df0c1477e2..db87e12ac88 100644 --- a/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py +++ b/tests/test_litellm/proxy/guardrails/test_usage_endpoints.py @@ -685,7 +685,7 @@ async def test_detail_prev_trend_query_is_bounded(): @pytest.mark.asyncio -async def test_logs_report_skipped_entries_as_skipped_not_passed(): +async def test_logs_report_not_run_entries_as_not_run_not_passed(): """LIT-6314: a guardrail that never scanned must not be reported as a pass in the drill-down.""" index_row = MagicMock() index_row.request_id = "req-nr" @@ -697,7 +697,7 @@ async def test_logs_report_skipped_entries_as_skipped_not_passed(): spend_log.startTime = datetime(2026, 4, 22) spend_log.metadata = { "guardrail_information": [ - {"guardrail_name": "db-1", "guardrail_status": "skipped", "duration": 0.0}, + {"guardrail_name": "db-1", "guardrail_status": "not_run", "duration": 0.0}, ] } prisma = _prisma(find_unique=_db_row(), index_find_many=[index_row]) @@ -715,11 +715,11 @@ async def test_logs_report_skipped_entries_as_skipped_not_passed(): end_date=END, user_api_key_dict=ADMIN, ) - assert [log.action for log in resp.logs] == ["skipped"] + assert [log.action for log in resp.logs] == ["not_run"] @pytest.mark.asyncio -async def test_logs_action_passed_filter_excludes_skipped_entries(): +async def test_logs_action_passed_filter_excludes_not_run_entries(): """LIT-6314: filtering the drill-down for passes must not return unscanned requests.""" index_row = MagicMock() index_row.request_id = "req-nr" @@ -729,7 +729,7 @@ async def test_logs_action_passed_filter_excludes_skipped_entries(): spend_log.request_id = "req-nr" spend_log.model = "gpt-4o-mini" spend_log.startTime = datetime(2026, 4, 22) - spend_log.metadata = {"guardrail_information": [{"guardrail_name": "db-1", "guardrail_status": "skipped"}]} + spend_log.metadata = {"guardrail_information": [{"guardrail_name": "db-1", "guardrail_status": "not_run"}]} prisma = _prisma(find_unique=_db_row(), index_find_many=[index_row]) prisma.db.litellm_spendlogs.find_many = AsyncMock(return_value=[spend_log]) handler = _config_handler() diff --git a/tests/test_litellm/proxy/guardrails/test_usage_tracking.py b/tests/test_litellm/proxy/guardrails/test_usage_tracking.py index cb85eb8b5ec..69ec098b840 100644 --- a/tests/test_litellm/proxy/guardrails/test_usage_tracking.py +++ b/tests/test_litellm/proxy/guardrails/test_usage_tracking.py @@ -350,15 +350,15 @@ async def test_zero_and_non_int_usage_counters_are_skipped(): @pytest.mark.asyncio -async def test_skipped_entries_are_indexed_but_not_counted_as_evaluations(): +async def test_not_run_entries_are_indexed_but_not_counted_as_evaluations(): """ - LIT-6314 records a skipped entry when message scoping leaves a guardrail + LIT-6314 records a not_run entry when message scoping leaves a guardrail nothing to scan. The guardrail never evaluated the request, so counting it as a passed evaluation would inflate daily pass rates; it still gets an index row so per-request drill-down finds the spend log. """ prisma = _prisma() - logs = [_payload("r1", guardrail_status="skipped"), _payload("r2")] + logs = [_payload("r1", guardrail_status="not_run"), _payload("r2")] await process_spend_logs_guardrail_usage(prisma, logs) @@ -370,26 +370,26 @@ async def test_skipped_entries_are_indexed_but_not_counted_as_evaluations(): @pytest.mark.asyncio -async def test_skipped_entry_shares_index_key_with_evaluated_sibling_of_same_name(): +async def test_not_run_entry_shares_index_key_with_evaluated_sibling_of_same_name(): """ - The skipped entry from the shared base guardrail carries only guardrail_name, + The not_run entry from the shared base guardrail carries only guardrail_name, while the evaluated entry from the same guardrail (e.g. content filter on the output of a logging_only run) carries its guardrail_id. Keying them differently - lists one request twice in the monitor, once as skipped and once as passed. + lists one request twice in the monitor, once as not_run and once as passed. """ prisma = _prisma() payload = _payload("r1") payload["metadata"] = json.dumps( { "guardrail_information": [ - {"guardrail_name": "cf", "guardrail_status": "skipped"}, + {"guardrail_name": "cf", "guardrail_status": "not_run"}, { "guardrail_name": "cf", "guardrail_id": "cf-uuid", "policy_id": "pol-1", "guardrail_status": "success", }, - {"guardrail_name": "other", "guardrail_status": "skipped"}, + {"guardrail_name": "other", "guardrail_status": "not_run"}, ] } ) @@ -406,7 +406,7 @@ async def test_skipped_entry_shares_index_key_with_evaluated_sibling_of_same_nam @pytest.mark.asyncio -async def test_malformed_skipped_entry_does_not_drop_the_batch(): +async def test_malformed_not_run_entry_does_not_drop_the_batch(): prisma = _prisma() payload = _payload("r1") payload["metadata"] = json.dumps( @@ -428,10 +428,10 @@ async def test_malformed_skipped_entry_does_not_drop_the_batch(): @pytest.mark.asyncio -async def test_batch_of_only_skipped_entries_writes_no_metrics_row(): +async def test_batch_of_only_not_run_entries_writes_no_metrics_row(): prisma = _prisma() - await process_spend_logs_guardrail_usage(prisma, [_payload("r1", guardrail_status="skipped")]) + await process_spend_logs_guardrail_usage(prisma, [_payload("r1", guardrail_status="not_run")]) assert prisma.db.litellm_dailyguardrailmetrics.upsert.call_count == 0 index_rows = prisma.db.litellm_spendlogguardrailindex.create_many.call_args.kwargs["data"] diff --git a/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py b/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py index 9587e3d95ee..8382a5ada96 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py +++ b/tests/test_litellm/proxy/management_endpoints/test_compliance_endpoints.py @@ -591,17 +591,17 @@ class TestModeMatching: assert mode in _guaranteed_modes(g_mode), (g_mode, mode) -class TestSkippedGuardrails: - """LIT-6314 logs a skipped entry for a guardrail that message scoping left nothing to scan.""" +class TestNotRunGuardrails: + """LIT-6314 logs a not_run entry for a guardrail that message scoping left nothing to scan.""" - def test_skipped_alone_never_evidences_compliance(self): + def test_not_run_alone_never_evidences_compliance(self): data = ComplianceCheckRequest( request_id="req-601", user_id="user-1", model="gpt-4", timestamp="2026-02-17T00:00:00Z", guardrail_information=[ - {"guardrail_name": "pii_detection", "guardrail_status": "skipped", "guardrail_mode": "pre_call"}, + {"guardrail_name": "pii_detection", "guardrail_status": "not_run", "guardrail_mode": "pre_call"}, ], ) results = {c.check_name: c.passed for c in ComplianceChecker(data).check_eu_ai_act()} @@ -609,7 +609,7 @@ class TestSkippedGuardrails: assert results["Content screened before LLM"] is False assert results["Audit record complete"] is False - def test_skipped_sibling_does_not_fail_a_passing_request(self): + def test_not_run_sibling_does_not_fail_a_passing_request(self): data = ComplianceCheckRequest( request_id="req-602", user_id="user-1", @@ -618,7 +618,7 @@ class TestSkippedGuardrails: pii_detected=True, guardrail_information=[ {"guardrail_name": "pii_detection", "guardrail_status": "success", "guardrail_mode": "pre_call"}, - {"guardrail_name": "system_only", "guardrail_status": "skipped", "guardrail_mode": "pre_call"}, + {"guardrail_name": "system_only", "guardrail_status": "not_run", "guardrail_mode": "pre_call"}, ], ) results = {c.check_name: c.passed for c in ComplianceChecker(data).check_gdpr()} diff --git a/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.test.tsx b/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.test.tsx index af5284830dc..083b1e5f3e2 100644 --- a/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.test.tsx +++ b/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.test.tsx @@ -96,14 +96,14 @@ describe("GuardrailsMonitor LogViewer drawer", () => { }); }); -describe("GuardrailsMonitor LogViewer skipped rows", () => { - it("renders a skipped log as a neutral Skipped badge instead of a pass or failure", () => { +describe("GuardrailsMonitor LogViewer not_run rows", () => { + it("renders a not_run log as a neutral Not run badge instead of a pass or failure", () => { renderWithProviders( - , + , ); const row = screen.getByRole("button", { name: /system prompt only/ }); - expect(within(row).getByText("Skipped")).toHaveClass("text-muted-foreground"); + expect(within(row).getByText("Not run")).toHaveClass("text-muted-foreground"); expect(within(row).queryByText("Passed")).not.toBeInTheDocument(); expect(within(row).queryByText("Blocked")).not.toBeInTheDocument(); }); diff --git a/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.tsx b/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.tsx index b113c49e0a3..2abd699ba86 100644 --- a/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.tsx +++ b/ui/litellm-dashboard/src/components/GuardrailsMonitor/LogViewer.tsx @@ -10,15 +10,15 @@ import type { LogEntry as ViewLogsLogEntry } from "@/components/view_logs/column import type { LogEntry } from "./mockData"; const actionConfig: Record< - "blocked" | "passed" | "flagged" | "skipped", + "blocked" | "passed" | "flagged" | "not_run", { icon: React.ElementType; color: string; bg: string; border: string; label: string } > = { - skipped: { + not_run: { icon: MinusCircle, color: "text-muted-foreground", bg: "bg-muted", border: "border-border", - label: "Skipped", + label: "Not run", }, blocked: { icon: X, diff --git a/ui/litellm-dashboard/src/components/GuardrailsMonitor/mockData.ts b/ui/litellm-dashboard/src/components/GuardrailsMonitor/mockData.ts index 7053efcf88d..591d5cd3edd 100644 --- a/ui/litellm-dashboard/src/components/GuardrailsMonitor/mockData.ts +++ b/ui/litellm-dashboard/src/components/GuardrailsMonitor/mockData.ts @@ -10,7 +10,7 @@ export interface LogEntry { input_snippet?: string; output_snippet?: string; score?: number; - action: "blocked" | "passed" | "flagged" | "skipped"; + action: "blocked" | "passed" | "flagged" | "not_run"; model?: string; reason?: string; latency_ms?: number; diff --git a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx index 740ef857690..7f343211596 100644 --- a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.test.tsx @@ -16,7 +16,7 @@ const PresidioPath = "@/components/view_logs/GuardrailViewer/PresidioDetectedEnt const BedrockPath = "@/components/view_logs/GuardrailViewer/BedrockGuardrailDetails"; const skippedPreCall: Partial = { - guardrail_status: "skipped", + guardrail_status: "not_run", guardrail_mode: "pre_call", guardrail_response: "no scannable content after message scoping", start_time: null, @@ -68,15 +68,15 @@ describe("GuardrailViewer", () => { expect(screen.queryByText("FAILED")).not.toBeInTheDocument(); }); - it("renders skipped as SKIPPED (muted) and keeps it out of the evaluated and passed counts", async () => { + it("renders not_run as NOT RUN (muted) and keeps it out of the evaluated and passed counts", async () => { const user = userEvent.setup(); const data = makeGuardrailInformation(skippedPreCall); renderWithProviders(); expect(screen.getByText(/0 guardrails evaluated/)).toBeInTheDocument(); expect(screen.getByText(/0 Passed/)).toHaveClass("text-muted-foreground"); - expect(screen.getByText(/1 Skipped/)).toBeInTheDocument(); - const badge = screen.getByText("SKIPPED"); + expect(screen.getByText(/1 Not run/)).toBeInTheDocument(); + const badge = screen.getByText("NOT RUN"); expect(badge).toHaveClass("text-muted-foreground"); expect(screen.queryByText("FAILED")).not.toBeInTheDocument(); expect(screen.queryByText(/^T\+/)).not.toBeInTheDocument(); @@ -85,7 +85,7 @@ describe("GuardrailViewer", () => { expect(screen.getByText("no scannable content after message scoping")).toBeInTheDocument(); }); - it("anchors the lifecycle timeline on timed entries when an untimed skipped entry sorts first", () => { + it("anchors the lifecycle timeline on timed entries when an untimed not_run entry sorts first", () => { const skipped = makeGuardrailInformation({ ...skippedPreCall, guardrail_name: "skipped-rail" }); const ran = makeGuardrailInformation(ranPostCall); renderWithProviders(); diff --git a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx index c67d682a233..1de0e3878b2 100644 --- a/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/GuardrailViewer/GuardrailViewer.tsx @@ -134,13 +134,13 @@ const getTotalMasked = (entry: GuardrailInformation): number => { ); }; -type EntryOutcome = "passed" | "flagged" | "failed" | "skipped"; +type EntryOutcome = "passed" | "flagged" | "failed" | "not_run"; const getEntryOutcome = (entry: GuardrailInformation): EntryOutcome => { const status = (entry.guardrail_status ?? "").toLowerCase(); if (status === "success") return "passed"; if (status === "guardrail_flagged") return "flagged"; - if (status === "skipped") return "skipped"; + if (status === "not_run") return "not_run"; return "failed"; }; @@ -150,18 +150,18 @@ const OUTCOME_LABEL: Record = { passed: "PASSED", flagged: "FLAGGED", failed: "FAILED", - skipped: "SKIPPED", + not_run: "NOT RUN", }; const OUTCOME_BADGE_CLASS: Record = { passed: "bg-success/15 text-success border border-success/20", flagged: "bg-warning/15 text-warning border border-warning/20", failed: "bg-destructive/15 text-destructive border border-destructive/20", - skipped: "bg-muted text-muted-foreground border border-border", + not_run: "bg-muted text-muted-foreground border border-border", }; const getHeaderOutcome = (counts: { evaluated: number; passed: number; flagged: number }): EntryOutcome => { - if (counts.evaluated === 0) return "skipped"; + if (counts.evaluated === 0) return "not_run"; if (counts.passed === counts.evaluated) return "passed"; if (counts.passed + counts.flagged === counts.evaluated) return "flagged"; return "failed"; @@ -242,7 +242,7 @@ const FlagCircleIcon = ({ className }: { className?: string }) => ( const OutcomeIcon = ({ outcome }: { outcome: EntryOutcome }) => { if (outcome === "passed") return ; if (outcome === "flagged") return ; - if (outcome === "skipped") return ; + if (outcome === "not_run") return ; return ; }; @@ -675,7 +675,7 @@ const EvaluationCard = ({ entry }: { entry: GuardrailInformation }) => { )} - {outcome === "skipped" && typeof guardrailResponse === "string" && ( + {outcome === "not_run" && typeof guardrailResponse === "string" && (

{guardrailResponse}

)} @@ -717,8 +717,8 @@ const GuardrailViewer = ({ data, accessToken, logEntry }: GuardrailViewerProps) const passedCount = guardrailEntries.filter(isEntrySuccess).length; const flaggedCount = guardrailEntries.filter((e) => getEntryOutcome(e) === "flagged").length; - const skippedCount = guardrailEntries.filter((e) => getEntryOutcome(e) === "skipped").length; - const evaluatedCount = guardrailEntries.length - skippedCount; + const notRunCount = guardrailEntries.filter((e) => getEntryOutcome(e) === "not_run").length; + const evaluatedCount = guardrailEntries.length - notRunCount; const allPassed = evaluatedCount > 0 && passedCount === evaluatedCount; const headerOutcome = getHeaderOutcome({ evaluated: evaluatedCount, passed: passedCount, flagged: flaggedCount }); @@ -778,11 +778,11 @@ const GuardrailViewer = ({ data, accessToken, logEntry }: GuardrailViewerProps) {flaggedCount} Flagged )} - {skippedCount > 0 && ( + {notRunCount > 0 && ( - {skippedCount} Skipped + {notRunCount} Not run )} diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.integration.test.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.integration.test.tsx index cbc377c1b73..3637b6c55a3 100644 --- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.integration.test.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.integration.test.tsx @@ -637,20 +637,20 @@ describe("GuardrailJumpLink", () => { }); it.each([ - [["success", "skipped"], "text-success", "\u2713"], - [["guardrail_intervened", "skipped"], "text-destructive", "\u2717"], - ])("ignores skipped when styling %j as %s", (statuses, expectedClass, glyph) => { + [["success", "not_run"], "text-success", "\u2713"], + [["guardrail_intervened", "not_run"], "text-destructive", "\u2717"], + ])("ignores not_run when styling %j as %s", (statuses, expectedClass, glyph) => { render( ({ guardrail_status: s }))} />); - const pill = screen.getByText(/1 guardrail evaluated, 1 skipped/); + const pill = screen.getByText(/1 guardrail evaluated, 1 not run/); expect(pill).toHaveClass(expectedClass); expect(pill).toHaveTextContent(glyph); }); - it("renders an all skipped request as neutral rather than passed", () => { - render(); + it("renders an all not_run request as neutral rather than passed", () => { + render(); - const pill = screen.getByText(/0 guardrails evaluated, 1 skipped/); + const pill = screen.getByText(/0 guardrails evaluated, 1 not run/); expect(pill).toHaveClass("text-muted-foreground"); expect(pill).not.toHaveTextContent("\u2713"); }); 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 e052faa2228..30cd96935f7 100644 --- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailContent.tsx @@ -700,15 +700,15 @@ const GUARDRAIL_JUMP_LINK_STYLE = { passed: { className: "border border-success/20 bg-success/10 text-success", glyph: "\u2713" }, flagged: { className: "border border-warning/20 bg-warning/10 text-warning", glyph: "\u26A0" }, failed: { className: "border border-destructive/20 bg-destructive/10 text-destructive", glyph: "\u2717" }, - skipped: { className: "border border-border bg-muted text-muted-foreground", glyph: "\u2013" }, + not_run: { className: "border border-border bg-muted text-muted-foreground", glyph: "\u2013" }, } as const; const isPassedStatus = (status: unknown) => status === "pass" || status === "passed" || status === "success"; const isFlaggedStatus = (status: unknown) => status === "flagged" || status === "guardrail_flagged"; -const isSkippedStatus = (status: unknown) => status === "skipped"; +const isNotRunStatus = (status: unknown) => status === "not_run"; const guardrailJumpLinkOutcome = (evaluated: unknown[]): keyof typeof GUARDRAIL_JUMP_LINK_STYLE => { - if (evaluated.length === 0) return "skipped"; + if (evaluated.length === 0) return "not_run"; if (evaluated.every(isPassedStatus)) return "passed"; if (evaluated.every((s) => isPassedStatus(s) || isFlaggedStatus(s))) return "flagged"; return "failed"; @@ -716,8 +716,8 @@ const guardrailJumpLinkOutcome = (evaluated: unknown[]): keyof typeof GUARDRAIL_ export function GuardrailJumpLink({ guardrailEntries }: { guardrailEntries: any[] }) { const statuses = guardrailEntries.map((e) => e?.guardrail_status || e?.status); - const evaluated = statuses.filter((s) => !isSkippedStatus(s)); - const skippedCount = statuses.length - evaluated.length; + const evaluated = statuses.filter((s) => !isNotRunStatus(s)); + const notRunCount = statuses.length - evaluated.length; const { className, glyph } = GUARDRAIL_JUMP_LINK_STYLE[guardrailJumpLinkOutcome(evaluated)]; const handleClick = () => { @@ -743,7 +743,7 @@ export function GuardrailJumpLink({ guardrailEntries }: { guardrailEntries: any[ > {glyph} {evaluated.length} guardrail {evaluated.length !== 1 ? "s" : ""} evaluated - {skippedCount > 0 ? `, ${skippedCount} skipped` : ""} + {notRunCount > 0 ? `, ${notRunCount} not run` : ""} {"\u2193"}