mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-14 09:03:16 +00:00
fix(otel): publish suppressed GenAI context attributes in async_post_call_success_deployment_hook
This commit is contained in:
parent
6d48de863f
commit
ce81bdf5ee
1 changed files with 52 additions and 0 deletions
|
|
@ -98,7 +98,9 @@ if TYPE_CHECKING:
|
|||
from litellm.types.proxy.auth.user_api_key_auth import UserAPIKeyAuth
|
||||
from litellm.types.services import ServiceLoggerPayload
|
||||
from litellm.types.utils import (
|
||||
CallTypes,
|
||||
CallTypesLiteral,
|
||||
LLMResponseTypes,
|
||||
StandardLoggingGuardrailInformation,
|
||||
StandardLoggingPayload,
|
||||
)
|
||||
|
|
@ -950,6 +952,56 @@ class OpenTelemetryV2(CustomLogger):
|
|||
stamp_error(span, _span_error_from_exception(original_exception, traceback_str=traceback_str))
|
||||
return
|
||||
|
||||
async def async_post_call_success_deployment_hook(
|
||||
self,
|
||||
request_data: Mapping[str, object],
|
||||
response: "LLMResponseTypes",
|
||||
call_type: "CallTypes | None",
|
||||
) -> "LLMResponseTypes | None":
|
||||
"""Publish suppressed GenAI attributes in-line before returning to the caller.
|
||||
|
||||
``async_log_success_event`` is dispatched through ``GLOBAL_LOGGING_WORKER``
|
||||
in a background task after ``acompletion`` returns, by which time an outer
|
||||
framework instrumentation (e.g. Agno, LangChain, DSPy) has already closed
|
||||
its invocation. Publishing here ensures ``ContextData`` is enriched before
|
||||
the outer ``invocation.stop()`` runs.
|
||||
"""
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
||||
|
||||
logging_obj: Final = request_data.get("litellm_logging_obj")
|
||||
if not isinstance(logging_obj, LiteLLMLoggingObj):
|
||||
return None
|
||||
details: Final = logging_obj.model_call_details
|
||||
call: Final = LLMCallEvent.from_dict(details)
|
||||
carrier: Final = self._open_llm_calls.get(call.call_id) if call.call_id is not None else None
|
||||
ctx_data: Final = (
|
||||
carrier.outer_ctx_data
|
||||
if carrier is not None and carrier.outer_ctx_data is not None
|
||||
else get_active_genai_context_data(
|
||||
call.operation,
|
||||
call_type=as_str(details.get("call_type")),
|
||||
context=_llm_call_parent_context(call),
|
||||
)
|
||||
)
|
||||
if ctx_data is None:
|
||||
return None
|
||||
start_time: Final = logging_obj.start_time
|
||||
end_time: Final = datetime.now() # noqa: DTZ005 # matches naive logging_obj.start_time
|
||||
payload: Final = logging_obj._process_hidden_params_and_response_cost(
|
||||
response,
|
||||
start_time,
|
||||
end_time,
|
||||
build_logging_payload=True,
|
||||
publish_logging_payload=False,
|
||||
)
|
||||
if payload is not None:
|
||||
self._close_llm_call_with_suppression(
|
||||
{**details, "standard_logging_object": payload},
|
||||
start_time,
|
||||
end_time,
|
||||
)
|
||||
return None
|
||||
|
||||
def emit_guardrail_span(self, entry: "StandardLoggingGuardrailInformation") -> None:
|
||||
# Emitted by the guardrail-recording code the moment a guardrail finishes,
|
||||
# not from a post-call hook — that hook does not fire on every path (a
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue