forked from phoenix/litellm-mirror
feat(redact_messages.py): allow remove sensitive key information before passing to logging integration
This commit is contained in:
parent
0b9e93d863
commit
548e4f53f8
7 changed files with 65 additions and 4 deletions
|
@ -48,6 +48,20 @@ A number of these headers could be useful for troubleshooting, but the
|
|||
`x-litellm-call-id` is the one that is most useful for tracking a request across
|
||||
components in your system, including in logging tools.
|
||||
|
||||
## Redacting UserAPIKeyInfo
|
||||
|
||||
Redact information about the user api key (hashed token, user_id, team id, etc.), from logs.
|
||||
|
||||
Currently supported for Langfuse, OpenTelemetry, Logfire, ArizeAI logging.
|
||||
|
||||
```yaml
|
||||
litellm_settings:
|
||||
callbacks: ["langfuse"]
|
||||
redact_user_api_key_info: true
|
||||
```
|
||||
|
||||
Removes any field with `user_api_key_*` from metadata.
|
||||
|
||||
## Logging Proxy Input/Output - Langfuse
|
||||
|
||||
We will use the `--config` to set `litellm.success_callback = ["langfuse"]` this will log all successfull LLM calls to langfuse. Make sure to set `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY` in your environment
|
||||
|
|
|
@ -76,6 +76,7 @@ post_call_rules: List[Callable] = []
|
|||
turn_off_message_logging: Optional[bool] = False
|
||||
log_raw_request_response: bool = False
|
||||
redact_messages_in_exceptions: Optional[bool] = False
|
||||
redact_user_api_key_info: Optional[bool] = False
|
||||
store_audit_logs = False # Enterprise feature, allow users to see audit logs
|
||||
## end of callbacks #############
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ from packaging.version import Version
|
|||
|
||||
import litellm
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.litellm_core_utils.redact_messages import redact_user_api_key_info
|
||||
|
||||
|
||||
class LangFuseLogger:
|
||||
|
@ -382,6 +383,8 @@ class LangFuseLogger:
|
|||
mask_input = clean_metadata.pop("mask_input", False)
|
||||
mask_output = clean_metadata.pop("mask_output", False)
|
||||
|
||||
clean_metadata = redact_user_api_key_info(metadata=clean_metadata)
|
||||
|
||||
if trace_name is None and existing_trace_id is None:
|
||||
# just log `litellm-{call_type}` as the trace name
|
||||
## DO NOT SET TRACE_NAME if trace-id set. this can lead to overwriting of past traces.
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
#### What this does ####
|
||||
# On success + failure, log events to Logfire
|
||||
|
||||
import dotenv, os
|
||||
import os
|
||||
|
||||
import dotenv
|
||||
|
||||
dotenv.load_dotenv() # Loading env variables using dotenv
|
||||
import traceback
|
||||
import uuid
|
||||
from litellm._logging import print_verbose, verbose_logger
|
||||
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, NamedTuple
|
||||
|
||||
from typing_extensions import LiteralString
|
||||
|
||||
from litellm._logging import print_verbose, verbose_logger
|
||||
from litellm.litellm_core_utils.redact_messages import redact_user_api_key_info
|
||||
|
||||
|
||||
class SpanConfig(NamedTuple):
|
||||
message_template: LiteralString
|
||||
|
@ -135,6 +139,8 @@ class LogfireLogger:
|
|||
else:
|
||||
clean_metadata[key] = value
|
||||
|
||||
clean_metadata = redact_user_api_key_info(metadata=clean_metadata)
|
||||
|
||||
# Build the initial payload
|
||||
payload = {
|
||||
"id": id,
|
||||
|
|
|
@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
|
|||
import litellm
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.integrations.custom_logger import CustomLogger
|
||||
from litellm.litellm_core_utils.redact_messages import redact_user_api_key_info
|
||||
from litellm.types.services import ServiceLoggerPayload
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -315,7 +316,9 @@ class OpenTelemetry(CustomLogger):
|
|||
#############################################
|
||||
metadata = litellm_params.get("metadata", {}) or {}
|
||||
|
||||
for key, value in metadata.items():
|
||||
clean_metadata = redact_user_api_key_info(metadata=metadata)
|
||||
|
||||
for key, value in clean_metadata.items():
|
||||
if self.is_primitive(value):
|
||||
span.set_attribute("metadata.{}".format(key), value)
|
||||
|
||||
|
|
|
@ -87,3 +87,33 @@ def redact_message_input_output_from_logging(
|
|||
|
||||
# by default return result
|
||||
return result
|
||||
|
||||
|
||||
def redact_user_api_key_info(metadata: dict) -> dict:
|
||||
"""
|
||||
removes any user_api_key_info before passing to logging object, if flag set
|
||||
|
||||
Usage:
|
||||
|
||||
SDK
|
||||
```python
|
||||
litellm.redact_user_api_key_info = True
|
||||
```
|
||||
|
||||
PROXY:
|
||||
```yaml
|
||||
litellm_settings:
|
||||
redact_user_api_key_info: true
|
||||
```
|
||||
"""
|
||||
if litellm.redact_user_api_key_info is not True:
|
||||
return metadata
|
||||
|
||||
new_metadata = {}
|
||||
for k, v in metadata.items():
|
||||
if isinstance(k, str) and k.startswith("user_api_key"):
|
||||
pass
|
||||
else:
|
||||
new_metadata[k] = v
|
||||
|
||||
return new_metadata
|
||||
|
|
|
@ -3,3 +3,7 @@ model_list:
|
|||
litellm_params:
|
||||
model: groq/llama3-groq-70b-8192-tool-use-preview
|
||||
api_key: os.environ/GROQ_API_KEY
|
||||
|
||||
litellm_settings:
|
||||
callbacks: ["logfire"]
|
||||
redact_user_api_key_info: true
|
Loading…
Add table
Add a link
Reference in a new issue