fix(litellm_logging.py): log custom headers in requester metadata (#10818)

* fix(litellm_logging.py): log custom headers in requester metadata

allows passing along custom headers from client to logging integration - e.g. `x-correlation-id`

* refactor: move enterprise code out of OSS package

work towards simplified CE version of docker image

* test: update test

* fix: fix linting error
This commit is contained in:
Krish Dholakia
2025-05-13 23:04:37 -07:00
committed by GitHub
parent cf4b2ebda4
commit a421316e56
5 changed files with 70 additions and 1 deletions
@@ -0,0 +1,28 @@
"""
Enterprise specific logging utils
"""
from litellm.litellm_core_utils.litellm_logging import StandardLoggingMetadata
class StandardLoggingPayloadSetup:
@staticmethod
def apply_enterprise_specific_metadata(
standard_logging_metadata: StandardLoggingMetadata,
proxy_server_request: dict,
) -> StandardLoggingMetadata:
"""
Adds enterprise-only metadata to the standard logging metadata.
"""
_request_headers = proxy_server_request.get("headers", {})
if _request_headers:
custom_headers = {
k: v
for k, v in _request_headers.items()
if k.startswith("x-") and v is not None and isinstance(v, str)
}
standard_logging_metadata["requester_custom_headers"] = custom_headers
return standard_logging_metadata
+35 -1
View File
@@ -13,7 +13,18 @@ import traceback
import uuid
from datetime import datetime as dt_object
from functools import lru_cache
from typing import Any, Callable, Dict, List, Literal, Optional, Tuple, Union, cast
from typing import (
Any,
Callable,
Dict,
List,
Literal,
Optional,
Tuple,
Type,
Union,
cast,
)
from pydantic import BaseModel
@@ -143,6 +154,13 @@ try:
from litellm_enterprise.enterprise_callbacks.send_emails.smtp_email import (
SMTPEmailLogger,
)
from litellm_enterprise.litellm_core_utils.litellm_logging import (
StandardLoggingPayloadSetup as EnterpriseStandardLoggingPayloadSetup,
)
EnterpriseStandardLoggingPayloadSetupVAR: Optional[
Type[EnterpriseStandardLoggingPayloadSetup]
] = EnterpriseStandardLoggingPayloadSetup
except Exception as e:
verbose_logger.debug(
f"[Non-Blocking] Unable to import GenericAPILogger - LiteLLM Enterprise Feature - {str(e)}"
@@ -150,6 +168,7 @@ except Exception as e:
GenericAPILogger = CustomLogger # type: ignore
ResendEmailLogger = CustomLogger # type: ignore
SMTPEmailLogger = CustomLogger # type: ignore
EnterpriseStandardLoggingPayloadSetupVAR = None
_in_memory_loggers: List[Any] = []
### GLOBAL VARIABLES ###
@@ -3328,6 +3347,7 @@ class StandardLoggingPayloadSetup:
List[StandardLoggingVectorStoreRequest]
] = None,
usage_object: Optional[dict] = None,
proxy_server_request: Optional[dict] = None,
) -> StandardLoggingMetadata:
"""
Clean and filter the metadata dictionary to include only the specified keys in StandardLoggingMetadata.
@@ -3377,6 +3397,7 @@ class StandardLoggingPayloadSetup:
mcp_tool_call_metadata=mcp_tool_call_metadata,
vector_store_request_metadata=vector_store_request_metadata,
usage_object=usage_object,
requester_custom_headers=None,
)
if isinstance(metadata, dict):
# Filter the metadata dictionary to include only the specified keys
@@ -3399,6 +3420,16 @@ class StandardLoggingPayloadSetup:
and isinstance(_potential_requester_metadata, dict)
):
clean_metadata["requester_metadata"] = _potential_requester_metadata
if (
EnterpriseStandardLoggingPayloadSetupVAR
and proxy_server_request is not None
):
clean_metadata = EnterpriseStandardLoggingPayloadSetupVAR.apply_enterprise_specific_metadata(
standard_logging_metadata=clean_metadata,
proxy_server_request=proxy_server_request,
)
return clean_metadata
@staticmethod
@@ -3730,6 +3761,7 @@ def get_standard_logging_object_payload(
clean_hidden_params = StandardLoggingPayloadSetup.get_hidden_params(
hidden_params
)
# clean up litellm metadata
clean_metadata = StandardLoggingPayloadSetup.get_standard_logging_metadata(
metadata=metadata,
@@ -3741,6 +3773,7 @@ def get_standard_logging_object_payload(
"vector_store_request_metadata", None
),
usage_object=usage.model_dump(),
proxy_server_request=proxy_server_request,
)
_request_body = proxy_server_request.get("body", {})
@@ -3886,6 +3919,7 @@ def get_standard_logging_metadata(
mcp_tool_call_metadata=None,
vector_store_request_metadata=None,
usage_object=None,
requester_custom_headers=None,
)
if isinstance(metadata, dict):
# Filter the metadata dictionary to include only the specified keys
+3
View File
@@ -72,3 +72,6 @@ model_list:
model_info:
id: my-unique-azure-deployment
mode: batch
litellm_settings:
success_callback: ["generic_api"]
+3
View File
@@ -1785,6 +1785,9 @@ class StandardLoggingMetadata(StandardLoggingUserAPIKeyMetadata):
] # special param to log k,v pairs to spendlogs for a call
requester_ip_address: Optional[str]
requester_metadata: Optional[dict]
requester_custom_headers: Optional[
Dict[str, str]
] # Log any custom (`x-`) headers sent by the client to the proxy.
prompt_management_metadata: Optional[StandardLoggingPromptManagementMetadata]
mcp_tool_call_metadata: Optional[StandardLoggingMCPToolCall]
vector_store_request_metadata: Optional[List[StandardLoggingVectorStoreRequest]]
@@ -277,6 +277,7 @@ def validate_redacted_message_span_attributes(span):
"metadata.applied_guardrails",
"metadata.mcp_tool_call_metadata",
"metadata.vector_store_request_metadata",
"metadata.requester_custom_headers",
]
_all_attributes = set(