mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-07 06:29:41 +00:00
chore(proxy): log stripped pricing fields at debug for operator visibility
Operators upgrading would otherwise see client-supplied pricing overrides silently stop applying with no diagnostic. Emit a debug-level line listing the dropped fields and pointing at the opt-in flag when any are stripped; stay silent on the no-op path so the log isn't filled with noise. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -240,16 +240,31 @@ def _strip_client_pricing_overrides(data: Dict[str, Any]) -> None:
|
||||
"""Drop pricing overrides from the request body and any metadata variant.
|
||||
|
||||
Skipped only when the calling key/team carries
|
||||
``allow_client_pricing_override: True`` in its metadata.
|
||||
``allow_client_pricing_override: True`` in its metadata. Emits a
|
||||
``debug``-level log line naming the dropped fields so operators can
|
||||
trace why a client-supplied pricing override stopped being applied
|
||||
(otherwise the strip is invisible from the caller's perspective).
|
||||
"""
|
||||
stripped: List[str] = []
|
||||
for field in _CLIENT_PRICING_CONTROL_FIELDS:
|
||||
data.pop(field, None)
|
||||
if field in data:
|
||||
stripped.append(field)
|
||||
data.pop(field, None)
|
||||
for metadata_key in ("metadata", "litellm_metadata"):
|
||||
metadata = data.get(metadata_key)
|
||||
if not isinstance(metadata, dict):
|
||||
continue
|
||||
for field in _CLIENT_PRICING_METADATA_FIELDS:
|
||||
metadata.pop(field, None)
|
||||
if field in metadata:
|
||||
stripped.append(f"{metadata_key}.{field}")
|
||||
metadata.pop(field, None)
|
||||
if stripped:
|
||||
verbose_proxy_logger.debug(
|
||||
"Stripped client-supplied pricing fields from request body: %s. "
|
||||
"Set `allow_client_pricing_override: true` on the key or team "
|
||||
"metadata to keep these values.",
|
||||
", ".join(stripped),
|
||||
)
|
||||
|
||||
|
||||
def _get_metadata_variable_name(request: Request) -> str:
|
||||
|
||||
@@ -130,6 +130,41 @@ class TestStripClientPricingOverrides:
|
||||
def test_metadata_field_set_contains_model_info(self):
|
||||
assert "model_info" in _CLIENT_PRICING_METADATA_FIELDS
|
||||
|
||||
def test_strip_emits_debug_log_listing_dropped_fields(self, caplog):
|
||||
# Operators need a paper trail so they can diagnose why a previously
|
||||
# working override stopped applying after the strip landed.
|
||||
import logging
|
||||
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
|
||||
verbose_proxy_logger.setLevel(logging.DEBUG)
|
||||
with caplog.at_level(logging.DEBUG, logger=verbose_proxy_logger.name):
|
||||
_strip_client_pricing_overrides(
|
||||
{
|
||||
"model": "gpt-4",
|
||||
"input_cost_per_token": 0.0,
|
||||
"metadata": {"model_info": {"output_cost_per_token": 0.0}},
|
||||
}
|
||||
)
|
||||
log_text = " ".join(record.getMessage() for record in caplog.records)
|
||||
assert "input_cost_per_token" in log_text
|
||||
assert "metadata.model_info" in log_text
|
||||
assert "allow_client_pricing_override" in log_text
|
||||
|
||||
def test_strip_does_not_log_when_no_fields_present(self, caplog):
|
||||
# No-op strips must stay silent so the log isn't filled with noise on
|
||||
# every legitimate request.
|
||||
import logging
|
||||
|
||||
from litellm._logging import verbose_proxy_logger
|
||||
|
||||
verbose_proxy_logger.setLevel(logging.DEBUG)
|
||||
with caplog.at_level(logging.DEBUG, logger=verbose_proxy_logger.name):
|
||||
_strip_client_pricing_overrides({"model": "gpt-4", "temperature": 0.7})
|
||||
assert not any(
|
||||
"pricing" in record.getMessage().lower() for record in caplog.records
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_litellm_data_to_request_strips_root_pricing_fields():
|
||||
|
||||
Reference in New Issue
Block a user