fix(headroom guardrail): log real token/compression stats instead of "allow" - #32158
Conversation
…"allow" The headroom guardrail fetched tokens_before/tokens_after/compression_ratio from Headroom's /v1/compress response but only surfaced them via a debug-level log line, so spend_logs.guardrail_information showed guardrail_response: "allow" with no way to tell whether compression actually ran or by how much. _call_compress now returns the token/compression stats alongside the compressed messages and success flag, and apply_guardrail logs them via add_standard_logging_guardrail_information_to_request_data when compression succeeds. Raw message content is intentionally excluded from what's logged - only token counts, compression ratio, and applied transform names.
…ntion Addresses codex review feedback - CLAUDE.md says not to add comments unless explicitly asked; the sensitive-logging guarantee is already expressed by the stats dict only pulling specific keys, not messages.
|
|
Greptile SummaryThis PR fixes the headroom guardrail's spend-log output so that real token/compression stats (
Confidence Score: 4/5Safe to merge; the change is additive and isolated to the headroom guardrail's logging path, with no behavioural change to the compression or routing logic. The implementation correctly mirrors the double-logging prevention pattern established by other guardrails, and failure paths all return empty stats so no data is lost. The only gap is that Only
|
| Filename | Overview |
|---|---|
| litellm/proxy/guardrails/guardrail_hooks/headroom/headroom.py | Extends _call_compress to return a 3-tuple with token stats, and calls add_standard_logging_guardrail_information_to_request_data on the success path — following the same pattern as block_code_execution and cisco_ai_defense. The double-logging guard in @log_guardrail_information correctly detects the manual call and skips the "allow" default. The event_type parameter is not passed to the logging helper, which may cause an inaccurate guardrail_mode in spend logs. |
Reviews (1): Last reviewed commit: "fix(review): remove comment per repo's n..." | Re-trigger Greptile
| self.add_standard_logging_guardrail_information_to_request_data( | ||
| guardrail_json_response=stats, | ||
| request_data=request_data, | ||
| guardrail_status="success", | ||
| guardrail_provider="headroom", | ||
| start_time=start_time, | ||
| end_time=end_time, | ||
| duration=end_time - start_time, | ||
| ) |
There was a problem hiding this comment.
The
event_type parameter is not passed to add_standard_logging_guardrail_information_to_request_data, so guardrail_mode in the spend-log entry falls back to self.event_hook, which may be a list or an unexpected value when the guardrail is configured for multiple hooks. Since apply_guardrail only executes on input_type == "request", the correct type is always pre_call. Other guardrails like block_code_execution explicitly pass this field.
| self.add_standard_logging_guardrail_information_to_request_data( | |
| guardrail_json_response=stats, | |
| request_data=request_data, | |
| guardrail_status="success", | |
| guardrail_provider="headroom", | |
| start_time=start_time, | |
| end_time=end_time, | |
| duration=end_time - start_time, | |
| ) | |
| self.add_standard_logging_guardrail_information_to_request_data( | |
| guardrail_json_response=stats, | |
| request_data=request_data, | |
| guardrail_status="success", | |
| guardrail_provider="headroom", | |
| start_time=start_time, | |
| end_time=end_time, | |
| duration=end_time - start_time, | |
| event_type=GuardrailEventHooks.pre_call, | |
| ) |
|
@BugBot please review |
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 60a6162. Configure here.
26c0c93
into
litellm_internal_staging
…"allow" (BerriAI#32158) * fix(headroom guardrail): log real token/compression stats instead of "allow" The headroom guardrail fetched tokens_before/tokens_after/compression_ratio from Headroom's /v1/compress response but only surfaced them via a debug-level log line, so spend_logs.guardrail_information showed guardrail_response: "allow" with no way to tell whether compression actually ran or by how much. _call_compress now returns the token/compression stats alongside the compressed messages and success flag, and apply_guardrail logs them via add_standard_logging_guardrail_information_to_request_data when compression succeeds. Raw message content is intentionally excluded from what's logged - only token counts, compression ratio, and applied transform names. * fix(ci): apply ruff format to headroom.py * fix(review): remove comment per repo's no-comments-unless-asked convention Addresses codex review feedback - CLAUDE.md says not to add comments unless explicitly asked; the sensitive-logging guarantee is already expressed by the stats dict only pulling specific keys, not messages.
(Replaces #32153 - that PR's head branch lived in a fork, which meant CircleCI never ran against it. This PR uses the same branch pushed directly into this repo instead.)
Summary
tokens_before/tokens_after/compression_ratio/transforms_appliedfrom Headroom's/v1/compressresponse, but only logged them via a debug-levelverbose_proxy_logger.debug(...)call - never persisted anywhere.spend_logs.guardrail_information.guardrail_responsealways showed the generic"allow", with no way to tell whether compression actually ran or by how much._call_compressnow returns the token/compression stats alongside the compressed messages and success flag, andapply_guardraillogs them viaadd_standard_logging_guardrail_information_to_request_datawhen compression succeeds (the same mechanism other guardrails likeblock_code_executionandcisco_ai_defenseuse for rich logging).litellm_internal_staging's existingfail_open/fail_closedunreachable-fallback change to the same function - stats are only logged on the success path.Before:
After:
Test plan
/v1/chat/completionsrequests through litellm with small/medium/large conversation payloads (plain, JSON tool output, log dumps, diffs, code) and confirmedguardrail_informationinLiteLLM_SpendLogsnow shows real token stats instead of"allow"for compressed requeststokens_saved: 0,compression_ratio: 1.0)Note
Low Risk
Observability-only change on the compression success path; no auth or request-payload behavior changes beyond existing guardrail logging.
Overview
Headroom guardrail now writes real compression metrics into
spend_logs/ standard guardrail logging instead of the generic"allow"string._call_compressreturns a third value: a dict of token/compression fields from Headroom’s/v1/compressJSON (tokens_before,tokens_after,tokens_saved,compression_ratio,transforms_applied). Failure paths return an empty stats dict. On a successful compress inapply_guardrail, the hook records timing and passes that dict throughadd_standard_logging_guardrail_information_to_request_data(same pattern as other guardrails with rich payloads), soguardrail_responsereflects actual compression outcomes without logging message bodies.Reviewed by Cursor Bugbot for commit 60a6162. Bugbot is set up for automated code reviews on this repo. Configure here.