mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-26 06:03:19 +00:00
* fix(batches): dispatch configured success callbacks during reconciliation * fix(batches): retain billed job claim when sync dispatch shuts down * fix(batches): finish reconciliation when logging executor is stopped * fix(logging): avoid duplicate custom hooks during async batch dispatch * fix: preserve sync-only custom callback delivery * fix: scope callback deduplication to per-call async recipients * refactor: type per-call async success callbacks * refactor: retain logging constructor callback compatibility * test: support current batch reconciliation metadata * fix(logging): honor per-logger redaction during sync success delivery * fix(logging): centralize completed success callback dispatch * fix(guardrails): avoid duplicate success callback dispatch --------- Co-authored-by: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com>
59 lines
2.1 KiB
Python
59 lines
2.1 KiB
Python
import json
|
|
import os
|
|
from collections.abc import Mapping
|
|
from datetime import datetime
|
|
from typing import Final
|
|
|
|
import httpx
|
|
from pydantic import BaseModel
|
|
|
|
from litellm.integrations.custom_logger import CustomLogger
|
|
|
|
|
|
def _payload(kwargs: Mapping[str, object], response_obj: object, logger: str, hook: str) -> str:
|
|
params: Final = kwargs.get("litellm_params")
|
|
request: Final = params.get("proxy_server_request") if isinstance(params, Mapping) else None
|
|
standard: Final = kwargs.get("standard_logging_object")
|
|
return json.dumps(
|
|
{
|
|
"logger": logger,
|
|
"hook": hook,
|
|
"standard": standard,
|
|
"request": request,
|
|
"response": response_obj.model_dump() if isinstance(response_obj, BaseModel) else response_obj,
|
|
"standard_response": standard.get("response") if isinstance(standard, Mapping) else None,
|
|
},
|
|
default=str,
|
|
)
|
|
|
|
|
|
class SyncRedactionProbe(CustomLogger):
|
|
def log_success_event(
|
|
self, kwargs: Mapping[str, object], response_obj: object, start_time: datetime, end_time: datetime
|
|
) -> None:
|
|
with httpx.Client(trust_env=False) as client:
|
|
response: Final = client.post(
|
|
os.environ["REDACTION_PROBE_URL"], content=_payload(kwargs, response_obj, type(self).__name__, "sync")
|
|
)
|
|
response.raise_for_status()
|
|
|
|
|
|
class RedactionProbe(CustomLogger):
|
|
async def async_log_success_event(
|
|
self, kwargs: Mapping[str, object], response_obj: object, start_time: datetime, end_time: datetime
|
|
) -> None:
|
|
async with httpx.AsyncClient(trust_env=False) as client:
|
|
response: Final = await client.post(
|
|
os.environ["REDACTION_PROBE_URL"], content=_payload(kwargs, response_obj, type(self).__name__, "async")
|
|
)
|
|
response.raise_for_status()
|
|
|
|
|
|
class DualRedactionProbe(CustomLogger):
|
|
log_success_event = SyncRedactionProbe.log_success_event
|
|
async_log_success_event = RedactionProbe.async_log_success_event
|
|
|
|
|
|
probe: Final = RedactionProbe()
|
|
sync_probe: Final = SyncRedactionProbe()
|
|
dual_probe: Final = DualRedactionProbe()
|