Ë
    tPêjŸ,  ã                   ó4  — U d Z ddlmZ ddlmZmZ ddlmZ ddlm	Z	 ddl
mZmZmZ ddlmZmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZmZmZmZmZmZ ddlm Z m!Z!m"Z" ddl#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z* ddl+m,Z, ddl-m.Z. e%j^                  e'e%j`                  e)e%jb                  e(e%jd                  e&e%jf                  e*e%jh                  e*iZ5ee6e%ede7f   f      e8d<   dZ9ee8d<   dede7de7ddfd„Z:dededdfd„Z;dddœdedede<de<de=e7e7f   dz  f
d „Z> G d!„ d"«      Z?y)#zEThe span engine: dedup, start, run the mapper chain, set status, end.é    )ÚOrderedDict)ÚCallableÚSequence)ÚFinal)ÚContext)ÚLinkÚSpanÚTracer)ÚStatusÚ
StatusCode)Úresolve_mappers)ÚAttributeMapperÚSpanData)ÚOpenTelemetryV2Config)ÚGuardrailSpanDataÚLLMCallSpanDataÚMCPListToolsSpanDataÚMCPToolCallSpanDataÚServiceSpanDataÚ	SpanError)ÚErrorÚExceptionEventÚLiteLLMError)ÚSPAN_REGISTRYÚSpanRoleÚguardrail_span_nameÚllm_call_span_nameÚmcp_list_tools_span_nameÚmcp_tool_call_span_nameÚservice_span_name)ÚGenAIEventRecorder)Úto_otel_span_kind.Ú_NAME_BUILDERSi'  Ú_DEDUP_CACHE_MAXÚspanÚ
error_typeÚresolved_messageÚreturnNc                 ó„   — | j                  t        j                  |«       | j                  t        j                  |«       y)zýStamp the OTel-semconv error attributes (``error.type`` + ``error.message``).
    ``error_type`` and ``resolved_message`` are ``finish_span``'s already-computed
    fallback chains, so the pair on the status, event, and attributes stays in
    lockstep.N)Úset_attributer   ÚTYPEÚMESSAGE)r%   r&   r'   s      úf/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/integrations/otel/emitter.pyÚ_stamp_otel_error_attributesr.   7   s-   € ð
 	×Ñ”u—z‘z :Ô.Ø×Ñ”u—}‘}Ð&6Õ7ó    Úerrorc                 óJ  — |j                   r*| j                  t        j                  |j                   «       |j                  r*| j                  t        j
                  |j                  «       |j                  r+| j                  t        j                  |j                  «       yy)zÈStamp litellm-specific error detail attributes. Emitted only when the
    corresponding field is populated so guardrail-shape errors carrying only a
    message aren't polluted with empty detail keys.N)Úcoder*   r   ÚCODEÚstack_traceÚSTACK_TRACEÚllm_providerÚLLM_PROVIDER)r%   r0   s     r-   Ú_stamp_litellm_error_attributesr8   @   st   € ð ‡z‚zØ×Ñœ<×,Ñ,¨e¯j©jÔ9Ø×ÒØ×Ñœ<×3Ñ3°U×5FÑ5FÔGØ×ÒØ×Ñœ<×4Ñ4°e×6HÑ6HÕIð r/   T)Úrecord_eventÚ
set_statusr9   r:   c                ó¤  — |j                   s|j                  sy|j                   xs d}|j                  xs |j                   xs d}t        | ||«       t        | |«       |r)| j	                  t        t        j                  |«      «       |r@| j                  t        j                  t        j                  |t        j                  |i«       ||fS )a7  Stamp the full v2 error attribute set on ``span`` and return the resolved
    ``(error_type, message)`` pair, or ``None`` when the error carries neither a
    type nor a message.

    Shared by the LLM-call span (``finish_span``) and the proxy-level failure
    spans (the FastAPI SERVER span and the ``auth`` phase span) so every v2 error
    span carries identical keys. The semconv ``exception`` event rides alongside
    the attributes so backends that map unknown string attrs to a truncated
    ``keyword`` (e.g. Elasticsearch's 1024-char ``ignore_above``) still see the
    full untruncated message on the recognized event field. ``record_event`` and
    ``set_status`` are opt-outs for callers whose span lifecycle (``use_span``) or
    owner (the FastAPI instrumentor) already records the event or the status.
    Nr0   )r&   Úmessager.   r8   r:   r   r   ÚERRORÚ	add_eventr   ÚNAMEr+   r,   )r%   r0   r9   r:   r&   r<   s         r-   Ústamp_errorr@   L   s®   € ð( ×Ò §¢ØØ×(Ñ(Ò3¨G€JØ—]‘]ÒA e×&6Ñ&6ÒA¸'€GÜ   z°7Ô;Ü# D¨%Ô0ÙØ�‰œœz×/Ñ/°Ó9Ô:ÙØ�‰Ü×ÑÜ× Ñ  *¬n×.DÑ.DÀgÐNô	
ð �wÐÐr/   c                   óN  — e Zd Z	 	 ddededee   dz  dedz  ddf
d„Z	 	 ddddœd	e	d
e
dedz  dedz  dedz  dee   dz  defd„Zde
dz  d	e	ddfd„Zde
dz  d	e	defd„Z	 ddddddœd	e	dededz  dedz  dedz  dedz  dee   dz  dedz  fd„Zddœd	e	dedededz  ddf
d„Zy)ÚSpanEmitterNÚtracerÚconfigÚmappersÚevent_recorderr(   c                 óš   — || _         || _        || _        |�t        |«      nt	        |j
                  «      | _        t        «       | _        y ©N)	Ú_tracerÚ_configÚ_event_recorderÚlistr   Úmapper_namesÚ_mappersr   Ú_emitted)ÚselfrC   rD   rE   rF   s        r-   Ú__init__zSpanEmitter.__init__q   sI   € ð ˆŒØˆŒØ-ˆÔð %Ð0ŒD�ŒM´oÀf×FYÑFYÓ6Zð 	Œô
 BMÃˆ�r/   )rC   ÚlinksÚroleÚnameÚparent_contextÚstart_time_nsrR   c          	      ó¢   — |xs | j                   j                  ||t        t        |   j                  «      ||rt        |«      ¬«      S d¬«      S )a‡  Start a span for ``role`` without dedup or attribute mapping.

        For callers that own and manage their own span lifecycle. ``tracer``
        overrides the bound tracer for this span only, used for per-request
        multi-tenant credential routing. ``links`` records related-but-not-parent
        spans (e.g. the trace context an MCP client propagated in ``params._meta``).
        N)ÚcontextÚkindÚ
start_timerR   )rI   Ú
start_spanr"   r   rY   rL   )rP   rS   rT   rU   rV   rC   rR   s          r-   r[   zSpanEmitter.start_span†   s^   € ð" Ò&˜$Ÿ,™,×2Ñ2ØØ"Ü"¤=°Ñ#6×#;Ñ#;Ó<Ø$Ù!&”$�u“+ð 3ó 
ð 	
ð
 -1ð 3ó 
ð 	
r/   Ú	dedup_keyc                 ó(   — | j                  ||«       y)zÓRegister a span emitted outside :meth:`emit` (the boundary-opened
        LLM-call span closed via :meth:`finish_span`) so a later :meth:`emit`
        for the same ``(dedup_key, role)`` deduplicates against it.N)Ú_seen)rP   r\   rS   s      r-   Úmark_emittedzSpanEmitter.mark_emittedŸ   s   € ð 	�
‰
�9˜dÕ#r/   c                 óô   — |sy||f}|| j                   v r| j                   j                  |«       yd| j                   |<   t        | j                   «      t        kD  r| j                   j	                  d¬«       y)zÌReturn True once a ``(dedup_key, role)`` pair has been emitted.

        Guards against emitting the same span twice when a streaming call
        fires both a sync and an async logging callback.
        FTN)Úlast)rO   Úmove_to_endÚlenr$   Úpopitem)rP   r\   rS   Úmarkers       r-   r^   zSpanEmitter._seen¥   sm   € ñ ØØ" DÐ)ˆØ�T—]‘]Ñ"Ø�M‰M×%Ñ% fÔ-ØØ $ˆ�‰�fÑÜˆt�}‰}ÓÔ 0Ò0Ø�M‰M×!Ñ! uÐ!Ô-Ør/   )rV   Úend_time_nsrC   rR   Údatarf   c                ó  — t        |t        t        t        f«      r|j                  j
                  nd}| j                  ||«      ry| j                  |t        |   |«      ||||¬«      }	| j                  ||	||¬«       |	S )ao  Emit one complete span: dedup, start, map attributes, status, end.

        Return the span, or ``None`` if it was deduplicated away. ``tracer``
        overrides the bound tracer for this span, used for per-request routing.
        ``links`` records related-but-not-parent spans (e.g. the trace context an
        MCP client propagated in ``params._meta``).
        N)rU   rV   rC   rR   ©rf   )
Ú
isinstancer   r   r   ÚidentityÚcall_idr^   r[   r#   Úfinish_span)
rP   rS   rg   rU   rV   rf   rC   rR   r\   r%   s
             r-   ÚemitzSpanEmitter.emit¸   sŽ   € ô. ˜$¤Ô2EÔG[Ð \Ô]ð �M‰M×!Ò!àð 	ð
 �:‰:�i Ô&ØØ—o‘oØÜ˜4Ñ  Ó&Ø)Ø'ØØð &ó 
ˆð 	×Ñ˜˜t T°{ÐÔCØˆr/   ri   r%   c                ó2  — |j                  t        |   |«      «       | j                  D ];  }|j                  |«      j	                  «       D ]  \  }}|j                  ||«       Œ Œ= t        |t        t        t        t        t        f«      r|j                  nd}|rit        ||«      }	|	�[| j                  �O|t        j                   u r=|	\  }
}| j                  j#                  |j%                  «       |
||j&                  |¬«       |j)                  |¬«       y)u#  Stamp attributes + status on an already-started ``span`` and end it.

        The counterpart to :meth:`start_span` for callers that own a span's
        lifecycle â€” the LLM-call span is opened at the request's ``pre_call``
        boundary (so it parents to the live server span via real ambient context,
        never a span threaded through a metadata dict) and closed here once the
        typed payload is available. The span name is (re)built from the now-known
        data, since the boundary opener only has a provisional name.
        N)Úspan_contextr&   r<   r4   Útimestamp_ns)Úend_time)Úupdate_namer#   rN   ÚmapÚitemsr*   rj   r   r   r   r   r   r0   r@   rK   r   ÚLLM_CALLÚrecord_operation_exceptionÚget_span_contextr4   Úend)rP   rS   r%   rg   rf   ÚmapperÚkeyÚvaluer0   Ústampedr&   r<   s               r-   rm   zSpanEmitter.finish_spanß   s  € ð" 	×Ñœ¨Ñ-¨dÓ3Ô4Ø—m‘mò 	/ˆFØ$Ÿj™j¨Ó.×4Ñ4Ó6ò /‘
��UØ×"Ñ" 3¨Õ.ñ/ð	/ô
 Øä#Ü'Ü(Ü#Ü%ðô	ð �JŠJð ð 	ñ Ü(¨¨uÓ5ˆGØÐ" t×';Ñ';Ð'GÈDÔT\×TeÑTeÑLeØ&-Ñ#�
˜GØ×$Ñ$×?Ñ?Ø!%×!6Ñ!6Ó!8Ø)Ø#Ø %× 1Ñ 1Ø!,ð @ô ð 	�‰˜+ˆÕ&r/   )NNrH   )Ú__name__Ú
__module__Ú__qualname__r
   r   r   r   r!   rQ   r   Ústrr   Úintr   r	   r[   r_   Úboolr^   r   rn   rm   © r/   r-   rB   rB   p   sÊ  „ ð
 59Ø48ñOàðOð &ðOð ˜/Ñ*¨TÑ1ð	Oð
 +¨TÑ1ðOð 
óOð2 *.Ø$(ð
ð !%Ø'+ò
àð
ð ð
ð   $™ð	
ð
 ˜T‘zð
ð ˜‘ð
ð ˜‰~ Ñ$ð
ð 
ó
ð2$ c¨D¡jð $¸ð $ÀTó $ð˜s T™zð °ð ¸dó ð. *.ð	%ð %)Ø"&Ø $Ø'+ò%àð%ð ð%ð   $™ð	%ð ˜T‘zð%ð ˜4‘Zð%ð ˜‘ð%ð ˜‰~ Ñ$ð%ð 
�‰ó%ðZ #'ò2'àð2'ð ð2'ð ð	2'ð ˜4‘Zð2'ð 
ô2'r/   rB   )@Ú__doc__Úcollectionsr   Úcollections.abcr   r   Útypingr   Úopentelemetry.contextr   Úopentelemetry.tracer   r	   r
   Úopentelemetry.trace.statusr   r   Ú!litellm.integrations.otel.mappersr   Ú&litellm.integrations.otel.mappers.baser   r   Ú&litellm.integrations.otel.model.configr   Ú(litellm.integrations.otel.model.payloadsr   r   r   r   r   r   Ú'litellm.integrations.otel.model.semconvr   r   r   Ú%litellm.integrations.otel.model.spansr   r   r   r   r   r   r    Ú)litellm.integrations.otel.plumbing.eventsr!   Ú,litellm.integrations.otel.plumbing.providersr"   rv   ÚMCP_TOOL_CALLÚMCP_LIST_TOOLSÚ	GUARDRAILÚDB_CALLÚSERVICEr#   Údictr�   Ú__annotations__r$   r.   r8   rƒ   Útupler@   rB   r„   r/   r-   ú<module>rœ      sf  ðÚ Kå #ß .Ý å )ß 2Ñ 2ß 9å =ß LÝ H÷÷ ÷ XÑ W÷÷ ñ õ IÝ Jð ×ÑÐ)Ø×ÑÐ3Ø×ÑÐ5Ø×ÑÐ+ð ×ÑÐ'Ø×ÑÐ'ð	=€��d˜8 X¨c°3¨hÑ%7Ð7Ñ8Ñ9ó 	ð !Ð �%Ó  ð8 tð 8¸ð 8ÐPSð 8ÐX\ó 8ð	J¨$ð 	J°yð 	JÀTó 	Jð  Øò!Ø
ð!àð!ð ð	!ð
 ð!ð ˆ3�ˆ8�_�tÑó!÷Ha'ò a'r/   