o
    ưi	                    @   s  d dl Z d dlmZ d dlmZ d dlmZmZmZmZm	Z	m
Z
mZ d dl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 d d
lmZ d dlmZmZmZmZmZm Z  erd dl!m"Z# d dl$m%Z& d dl$m'Z( d dl$m)Z* d dl+m,Z- d dl.m/Z0 e
e(ef Z'e
e*ef Z)e
e&ef Z%e
e#ef Z"e
e0ef Z/e
e-ef Z,neZ'eZ)eZ"eZ/eZ,eZ%e 1ddZ2e 1ddZ3e 1ddZ4dZ5dZ6dZ7eG dd dZ8G dd deZ9dS )    N)	dataclass)datetime)TYPE_CHECKINGAnyDictListOptionalUnioncast)verbose_logger)OpenInferenceSpanKindValuesSpanAttributes)CustomLogger)
safe_dumps)get_secret_bool)ServiceLoggerPayload)ChatCompletionMessageToolCallCostBreakdownFunctionLLMResponseTypesStandardCallbackDynamicParamsStandardLoggingPayload)SpanExporter)Context)Span)Tracer) ManagementEndpointLoggingPayload)UserAPIKeyAuthZOTEL_TRACER_NAMElitellmLITELLM_METER_NAMELITELLM_LOGGER_NAMEzReceived Proxy Server RequestZraw_gen_ai_requestZlitellm_requestc                   @   s   e Zd ZU dZeeef ed< dZe	e ed< dZ
e	e ed< dZeed< dZeed< dZe	e ed	< dZe	e ed
< dZe	e ed< dddZedd ZdS )OpenTelemetryConfigconsoleexporterNendpointheadersFenable_metricsenable_eventsservice_namedeployment_environmentmodel_idreturnc                 C   sh   | j rt| jtr| jdkrd| _| jstdd| _| js%tdd| _| js2td| j| _d S d S )Nr"   	otlp_httpOTEL_SERVICE_NAMEr   OTEL_ENVIRONMENT_NAME
productionOTEL_MODEL_ID)	r$   
isinstancer#   strr(   osgetenvr)   r*   )self r6   Y/home/app/Keep/.python/lib/python3.10/site-packages/litellm/integrations/opentelemetry.py__post_init__H   s   

z!OpenTelemetryConfig.__post_init__c           
   
   C   s   ddl m} tdtdd}tdtd}tdtd	}td
d dk}tdd dk}tdd}tdd}td|}	|dkrR| | dS | ||||||||	dS )z
        OTEL_HEADERS=x-honeycomb-team=B85YgLm9****
        OTEL_EXPORTER="otlp_http"
        OTEL_ENDPOINT="https://api.honeycomb.io/v1/traces"

        OTEL_HEADERS gets sent as headers = {"x-honeycomb-team": "B85YgLm96******"}
        r   )InMemorySpanExporterZOTEL_EXPORTER_OTLP_PROTOCOLOTEL_EXPORTERr"   ZOTEL_EXPORTER_OTLP_ENDPOINTOTEL_ENDPOINTZOTEL_EXPORTER_OTLP_HEADERSOTEL_HEADERSZ'LITELLM_OTEL_INTEGRATION_ENABLE_METRICSfalsetrueZ&LITELLM_OTEL_INTEGRATION_ENABLE_EVENTSr-   r   r.   r/   r0   Z	in_memory)r#   )r#   r$   r%   r&   r'   r(   r)   r*   )Z6opentelemetry.sdk.trace.export.in_memory_span_exporterr9   r3   r4   lower)
clsr9   r#   r$   r%   r&   r'   r(   r)   r*   r6   r6   r7   from_env]   s>   	
zOpenTelemetryConfig.from_env)r+   N)__name__
__module____qualname__r#   r	   r2   r   __annotations__r$   r   r%   r&   boolr'   r(   r)   r*   r8   classmethodrA   r6   r6   r6   r7   r!   =   s   
 
r!   c                       s  e Zd Z					ddee dee dee dee dee f
 fddZedefd	d
Z	dd Z
	ddedefddZdd Zdd Zdd Zdd Zdd Zdd Zdd Z				dd ed!ee d"eeeef  d#eeeef  d$ee f
d%d&Z	'				dd ed(ee d!ee d"eeeef  d#eeeef  d$ee fd)d*Z	dd+ed,ed-ed.ee fd/d0Zd1ed-ed2efd3d4Z d5ed6e!fd7d8Z"d6ee fd9d:Z#d;efd<d=Z$d>e%d6ee fd?d@Z&dAdB Z'dCdD Z(dEdF Z)dGdH Z*edIeeeeef  d6ee fdJdKZ+d5edLefdMdNZ,d5edOee d#edPedLef
dQdRZ-d5ed#eeef dLefdSdTZ.dUefdVdWZ/edUee dXee dYee d6ee fdZd[Z0d5ee d\ee1 fd]d^Z2d_d` Z3dUed5efdadbZ4dUefdcddZ5d6eeee6ef fdedfZ7edge8e9 d6e:eef fdhdiZ;dUedOee fdjdkZ<d6eeee6ef fdldmZ=dUednedoefdpdqZ>dree8e ef d6e8e fdsdtZ?due8e d6e8e fdvdwZ@dUefdxdyZAdzd{ ZBd|d} ZCd~d ZDddee fddZEdd;ee fddZFdd ZGdd ZHdee ded6ee fddZIedeeeef  d6e:eef fddZJ	ddeKd!ee fddZL	ddeKd!ee fddZMd"eded6ee fddZN  ZOS )OpenTelemetryNconfigcallback_nametracer_providerlogger_providermeter_providerc           
         s   |d u rt  }|| _|| _| jj| _| jj| _| jj| _	i | _
| | ttdd }|dkrNdd l}|j|jd |t |d}	|	|j t jdi | | | | | |   d S )NZ
DEBUG_OTELFalser>   r   )levelzopentelemetry.sdk.trace.exportr6   )r!   rA   rI   rJ   r#   r:   r$   r;   r%   r<   _tracer_provider_cache_init_tracingr2   r3   r4   r?   loggingbasicConfigDEBUG	getLoggerrB   setLevelsuper__init___init_metrics
_init_logs"_init_otel_logger_on_litellm_proxy)
r5   rI   rJ   rK   rL   rM   kwargsZ_debug_otelrR   Zotel_exporter_logger	__class__r6   r7   rX      s(   








zOpenTelemetry.__init__c                 C   sJ   ddl m}m} | j| j| jp| jd}||}| }| }||S )z>Create an OpenTelemetry Resource using config-driven defaults.r   )OTELResourceDetectorResource)zservice.namezdeployment.environmentr*   )	Zopentelemetry.sdk.resourcesr_   r`   r(   r)   r*   createdetectmerge)rI   r_   r`   Zbase_attributesZbase_resourceZotel_resource_detectorZenv_resourcer6   r6   r7   _get_litellm_resource   s   


z#OpenTelemetry._get_litellm_resourcec                 C   sj   zddl m} W n ty   td Y dS w dtjvr-tdd tjD r-tj|  t	|d|  dS )	z
        Initializes OpenTelemetry for litellm proxy server

        - Adds Otel as a service callback
        - Sets `proxy_server.open_telemetry_logger` to self
        r   )proxy_serverzEProxy Server is not installed. Skipping OpenTelemetry initialization.NZotelc                 s   s    | ]	}t |t V  qd S N)r1   rH   ).0cbr6   r6   r7   	<genexpr>   s    
zCOpenTelemetry._init_otel_logger_on_litellm_proxy.<locals>.<genexpr>Zopen_telemetry_logger)
Zlitellm.proxyre   ImportErrorr   warningr   Zservice_callbackallappendsetattr)r5   re   r6   r6   r7   r[      s   z0OpenTelemetry._init_otel_logger_on_litellm_proxyFprovider_nameskip_set_globalc           
   
   C   s   |durt dt|j |S z2| }t||r't d|t|j |}W |S t d| | }|s9|| W |S t d| W |S  tym }	 z t d|t|	 | }|sb|| W Y d}	~	|S W Y d}	~	|S d}	~	ww )a  
        Generic helper to get or create an OpenTelemetry provider (Tracer, Meter, or Logger).

        Args:
            provider: The provider instance passed to the init function (can be None)
            provider_name: Name for logging (e.g., "TracerProvider")
            get_existing_provider_fn: Function to get the existing global provider
            sdk_provider_class: The SDK provider class to check for (e.g., TracerProvider from SDK)
            create_new_provider_fn: Function to create a new provider instance
            set_provider_fn: Function to set the provider globally
            skip_set_global: If True, don't set the provider globally (for dynamic-only providers)

        Returns:
            The provider to use (either existing, new, or explicitly provided)
        Nz0OpenTelemetry: Using provided TracerProvider: %sz$OpenTelemetry: Using existing %s: %szOpenTelemetry: Creating new %sz^OpenTelemetry: Created %s but NOT setting it globally (will use dynamic providers per-request)zCOpenTelemetry: Exception checking existing %s, creating new one: %s)r   debugtyperB   r1   info	Exceptionr2   )
r5   providerro   get_existing_provider_fnsdk_provider_classcreate_new_provider_fnset_provider_fnrp   Zexisting_providerer6   r6   r7   _get_or_create_provider   sP   


z%OpenTelemetry._get_or_create_providerc              	      sx   ddl m} ddlm  ddlm}  fdd}tdo"jdk}j|d	|j	 ||j
|d
}|t_|_d S )Nr   traceTracerProvider)SpanKindc                     s$     jd} |   | S Nresource)rd   rI   add_span_processor_get_span_processor)ru   r   r5   r6   r7   create_tracer_provider(  s   z;OpenTelemetry._init_tracing.<locals>.create_tracer_providerrJ   langfuse_otelr   )ru   ro   rv   rw   rx   ry   rp   )opentelemetryr}   opentelemetry.sdk.tracer   opentelemetry.tracer   hasattrrJ   r{   Zget_tracer_providerZset_tracer_provider
get_tracerLITELLM_TRACER_NAMEtracer	span_kind)r5   rK   r}   r   r   Zskip_globalr6   r   r7   rQ   #  s"   
zOpenTelemetry._init_tracingc                    s   j jsd _d _d _d _d _d _d S ddlm	} ddl
m   fdd}j|d|j ||jd}|t}|jdd	d
d_|jdddd_|jdddd_|jddd
d_|jddd
d_|jddd
d_d S )Nr   )metrics)MeterProviderc                     s     }  | gjdS )N)Zmetric_readersr   )_get_metric_readerrd   rI   )Zmetric_readerr   r5   r6   r7   create_meter_providerN  s
   
z:OpenTelemetry._init_metrics.<locals>.create_meter_providerr   ru   ro   rv   rw   rx   ry   z gen_ai.client.operation.durationzGenAI operation durations)namedescriptionunitzgen_ai.client.token.usagezGenAI token usagez{token}zgen_ai.client.token.costzGenAI request costUSDz*gen_ai.client.response.time_to_first_tokenz*Time to first token for streaming requestsz,gen_ai.client.response.time_per_output_tokenzCAverage time per output token (generation time / completion tokens)zgen_ai.client.response.durationz9Total LLM API generation time (excludes LiteLLM overhead))rI   r&   _operation_duration_histogram_token_usage_histogram_cost_histogram_time_to_first_token_histogram _time_per_output_token_histogram_response_duration_histogramr   r   opentelemetry.sdk.metricsr   r{   Zget_meter_providerZset_meter_providerZ	get_meterrB   Zcreate_histogram)r5   rM   r   r   Zmeterr6   r   r7   rY   A  sd   
	zOpenTelemetry._init_metricsc                    s^   j jsd S ddlm}m} ddlm ddlm   fdd}j	|d|||d d S )	Nr   )get_logger_providerset_logger_provider)LoggerProvider)BatchLogRecordProcessorc                     s,    jd}  }|  | | S r   )rd   rI   _get_log_exporterZadd_log_record_processor)ru   Zlog_exporterr   ZOTLoggerProviderr5   r6   r7   create_logger_provider  s   
z8OpenTelemetry._init_logs.<locals>.create_logger_providerr   r   )
rI   r'   opentelemetry._logsr   r   opentelemetry.sdk._logsr   opentelemetry.sdk._logs.exportr   r{   )r5   rL   r   r   r   r6   r   r7   rZ     s   

zOpenTelemetry._init_logsc                 C      |  |||| d S rf   _handle_successr5   r\   response_obj
start_timeend_timer6   r6   r7   log_success_event     zOpenTelemetry.log_success_eventc                 C   r   rf   _handle_failurer   r6   r6   r7   log_failure_event  r   zOpenTelemetry.log_failure_eventc                       |  |||| d S rf   r   r   r6   r6   r7   async_log_success_event     z%OpenTelemetry.async_log_success_eventc                    r   rf   r   r   r6   r6   r7   async_log_failure_event  r   z%OpenTelemetry.async_log_failure_eventpayloadparent_otel_spanr   r   event_metadatac              	      s:  ddl m} ddlm}m} d}	d}
t|trt|d }	n| |}	t|tr0t|d }
n| |}
|d ur|j	}| j
j||||	d}| j|d|jd | j|d|j	jd |r| D ])\}}|d u rkd	}t|trzt|}W n ty   d
}Y nw | j|||d qa|||j |j|
d d S d S )Nr   r|   Status
StatusCode    eAr   contextr   	call_typespankeyvalueserviceNonez0litellm logging error - could_not_json_serializer   )r   r}   r   r   r   r1   floatint_to_nsr   r   
start_spanset_span_in_contextsafe_set_attributer   r   itemsdictr2   rt   
set_statusOKend)r5   r   r   r   r   r   r}   r   r   _start_time_ns_end_time_ns
_span_nameservice_logging_spanr   r   r6   r6   r7   async_service_success_hook  s\   




z(OpenTelemetry.async_service_success_hook errorc              	      sJ  ddl m} ddlm}m}	 d}
d}t|tr!tt|d }
n| |}
t|tr4tt|d }n| |}|d ur|j	}| j
j||||
d}| j|d|jd | j|d|j	jd |ri| j|d	|d |r| D ]#\}}t|trzt|}W n ty   d
}Y nw | j|||d qo|||	j |j|d d S d S )Nr   r|   r   r   r   r   r   r   r   z/litllm logging error - could_not_json_serializer   )r   r}   r   r   r   r1   r   r   r   r   r   r   r   r   r   r   r   r   r2   rt   r   ERRORr   )r5   r   r   r   r   r   r   r}   r   r   r   r   r   r   r   r   r6   r6   r7   async_service_failure_hook  sd   	




z(OpenTelemetry.async_service_failure_hookrequest_dataoriginal_exceptionuser_api_key_dicttraceback_strc                    s   ddl m} ddlm}m} |j}|d urU|||j d}	| jj	|	|
|d}
| j|
dt|d |
||j |
j| t d |j| t d d S d S )	Nr   r|   r   zFailed Proxy Server Request)r   r   	exceptionr   r   )r   r}   r   r   r   r   r   r   r   r   r   r   r2   r   r   r   now)r5   r   r   r   r   r}   r   r   r   r   Zexception_logging_spanr6   r6   r7   async_post_call_failure_hook"  s(   z*OpenTelemetry.async_post_call_failure_hookdataresponsec           
         sZ   ddl m} |d}|d ur+t||r+|j}|j}| j||d\}}	| j||d |S )Nr   )Logginglitellm_logging_obj)default_spanr\   r   )Z*litellm.litellm_core_utils.litellm_loggingr   getr1   Zmodel_call_detailsr   _get_span_context_create_guardrail_span)
r5   r   r   r   ZLiteLLMLoggingr   r\   parent_spanctx_r6   r6   r7   async_post_call_success_hookA  s   

z*OpenTelemetry.async_post_call_success_hookr\   r+   c                 C   s   |  |}|dur| |}td| |S t| drC| jdkrC| jr)| | jni }|r9| |}td |S | j}td |S | j}td |S )a  
        Get the tracer to use for this request

        If dynamic headers are present, a temporary tracer is created with the dynamic headers.
        Otherwise, the default tracer is used.

        Returns:
            Tracer: The tracer to use for this request
        Nz2[OTEL DEBUG] Using DYNAMIC tracer with headers: %srJ   r   zM[OTEL DEBUG] Using env var credentials for langfuse_otel (master key request)z7[OTEL DEBUG] No credentials available for langfuse_otelz5[OTEL DEBUG] Using GLOBAL tracer (no dynamic headers))	%_get_dynamic_otel_headers_from_kwargs _get_tracer_with_dynamic_headersr   rq   r   rJ   r<   _get_headers_dictionaryr   )r5   r\   dynamic_headersZtracer_to_useZenv_var_headersr6   r6   r7   get_tracer_to_use_for_request[  s<   


	z+OpenTelemetry.get_tracer_to_use_for_requestc                 C   s*   | d}|s	dS | j|d}|r|S dS )z1Extract dynamic headers from kwargs if available. standard_callback_dynamic_paramsN)r   )r   construct_dynamic_otel_headers)r5   r\   r   r   r6   r6   r7   r     s   z3OpenTelemetry._get_dynamic_otel_headers_from_kwargsr   c                 C   sn   ddl m} tt| }|| jv r| j| tS || | j	d}|
| j|d || j|< |tS )zECreate a temporary tracer with dynamic headers for this request only.r   r~   r   )r   )r   r   r2   sortedr   rP   r   r   rd   rI   r   r   )r5   r   r   	cache_keyZtemp_providerr6   r6   r7   r     s   




z.OpenTelemetry._get_tracer_with_dynamic_headersr   c                 C   s   dS )a  
        Construct dynamic headers from standard callback dynamic params

        Note: You just need to override this method in Arize, Langfuse Otel if you want to allow team/key based logging.

        Returns:
            dict: A dictionary of dynamic headers
        Nr6   )r5   r   r6   r6   r7   r     s   z,OpenTelemetry.construct_dynamic_otel_headersc                 C   s`  t d|| j | |\}}t| do| jdk}|rd }d }|d u p&td}|r<| |||||}	| |||||	 n'ddl	m
}
m} d }	t|drZ||
|j | ||| | ||||| | j|	||d}| j||d	 | |||| | jjr|	d ur|	n|}|d ur| ||| |d urt|d
r|jtkr|j| |d d S d S d S d S )NzAOpenTelemetry Logger: Logging kwargs: %s, OTEL config settings=%srJ   r   USE_OTEL_LITELLM_REQUEST_SPANr   r   r   r   r   fallback_ctxr   r   r   )r   rq   rI   r   r   rJ   r   _start_primary_span_maybe_log_raw_requestr   r   r   r   r   set_attributes_resolve_guardrail_contextr   _record_metricsr'   _emit_semantic_logsr   LITELLM_PROXY_REQUEST_SPAN_NAMEr   r   )r5   r\   r   r   r   r   r   is_langfuse_otelshould_create_primary_spanr   r   r   guardrail_ctxZlog_spanr6   r6   r7   r     sZ   


	


zOpenTelemetry._handle_successc           
      C   sj   ddl m}m} | |}|j| || ||d}	|	||j | 	|	|| |	j
| |d |	S )Nr   r   r   r   r   r   )r   r   r   r   r   _get_span_namer   r   r   r  r   )
r5   r\   r   r   r   r   r   r   otel_tracerr   r6   r6   r7   r    s   
z!OpenTelemetry._start_primary_spanc                 C   s   ddl m} ddlm}m} tjs| jsd S |di }	|	dp"i }
|
d}|r,|nt	}| 
|}|j|| |||d}|||j | ||| |j| |d d S )	Nr   r|   r   litellm_paramsmetadatageneration_namer  r   )r   r}   r   r   r   r   turn_off_message_loggingmessage_loggingr   RAW_REQUEST_SPAN_NAMEr   r   r   r   r   r   set_raw_request_attributesr   )r5   r\   r   r   r   r   r}   r   r   r  r  r  Zraw_span_namer  Zraw_spanr6   r6   r7   r  (  s"   

z$OpenTelemetry._maybe_log_raw_requestc                 C   s  ||   }|dpi }|dd}d||ddd}|d}	t|	d	d p/|	p+i d	i }
d
D ]}|
|d urFt|
| |d| < q2t|	dd pT|	pPi di }|r]t||d< | jr| jj||d |r|d }r| jri |ddi}i |ddi}| jj|dd|d | jj|dd|d |d}| jr|r| jj||d | 	|| | 
||||| | ||| d S )Nr  custom_llm_providerUnknownchatmodelr   )zgen_ai.operation.namegen_ai.systemzgen_ai.request.modelzgen_ai.frameworkstandard_logging_objectr  )Zuser_api_key_hashZuser_api_key_aliasZuser_api_key_team_idZuser_api_key_org_idZuser_api_key_user_idZuser_api_key_team_aliasZuser_api_key_user_emailZspend_logs_metadataZrequester_ip_addressZrequester_metadataZuser_api_key_end_user_idZprompt_management_metadataZapplied_guardrailsZmcp_tool_call_metadataZvector_store_request_metadataz	metadata.hidden_params
attributesusagezgen_ai.token.typeinputoutputprompt_tokensr   completion_tokensZresponse_cost)total_secondsr   getattrr2   r   r   recordr   r   "_record_time_to_first_token_metric$_record_time_per_output_token_metric _record_response_duration_metric)r5   r\   r   r   r   
duration_sparamsru   common_attrsZstd_logmdr   r  r  Zin_attrsZ	out_attrsZcostr6   r6   r7   r  B  sZ   



zOpenTelemetry._record_metricsvalc                 C   s   | du rdS t | tr|  S t | ttfrt| S z	t| d W S  tyA   zt| d W  Y S  ty@   Y Y dS w w )z+Convert datetime/float/string to timestamp.Nz%Y-%m-%d %H:%M:%S.%fz%Y-%m-%d %H:%M:%S)r1   r   	timestampr   r   strptime
ValueError)r.  r6   r6   r7   _to_timestamp  s   
zOpenTelemetry._to_timestampr,  c           
      C   s   | di }| dd}| jr|sdS | dd}| dd}|durI|durK| |}| |}|du s9|du r;dS || }	| jj|	|d dS dS dS )z@Record Time to First Token (TTFT) metric for streaming requests.optional_paramsstreamFNapi_call_start_timecompletion_start_timer  )r   r   r2  r&  )
r5   r\   r,  r3  Zis_streamingr5  r6  api_call_start_tscompletion_start_tsZtime_to_first_token_secondsr6   r6   r7   r'    s    



z0OpenTelemetry._record_time_to_first_token_metricr   r*  c                 C   s  | j sdS d}|r|d }r|d}|du s|dkrdS |dd}|dd}	| |}
|
du rH|}|dkrF|| }| j j||d dS |dur]| |}|du rX|}n|
| }n|	durr| |	}|du rm|}n|
| }n|}|dkr|| }| j j||d dS dS )a2  Record Time Per Output Token (TPOT) metric.

        Calculated as: generation_time / completion_tokens
        - For streaming: uses end_time - completion_start_time (time to generate all tokens after first)
        - For non-streaming: uses end_time - api_call_start_time (total generation time)
        Nr  r#  r   r6  r5  r  )r   r   r2  r&  )r5   r\   r   r   r*  r,  r#  r  r6  r5  end_time_tsZgeneration_time_secondsZtime_per_output_token_secondsr8  r7  r6   r6   r7   r(    sH   






z2OpenTelemetry._record_time_per_output_token_metricc           	      C   s   | j sdS |dd}|du rdS |dp|}|du r t }| |}| |}|du s2|du r4dS || }|dkrF| j j||d dS dS )a  Record Total Generation Time (response duration) metric.

        Measures pure LLM API generation time: end_time - api_call_start_time
        This excludes LiteLLM overhead and measures only the LLM provider's response time.
        Works for both streaming and non-streaming requests.

        Mirrors Prometheus's litellm_llm_api_latency_metric.
        Uses kwargs.get("end_time") with fallback to parameter for consistency with Prometheus.
        Nr5  r   r   r  )r   r   r   r   r2  r&  )	r5   r\   r   r,  r5  Z	_end_timer7  r9  Zresponse_duration_secondsr6   r6   r7   r)    s$   


z.OpenTelemetry._record_response_duration_metricr   c                 C   s  | j jsd S ddlm}m} zddlm} W n ty%   ddlm} Y nw |t	}|
 }|dp4i dd}	|dg D ]F}
|
dd	}d
|	d}|dkr[|
dr[|
d |d< | jri|
dri|
d |d< || t |j|j|j|jd|
 |d}|| q?t|dg D ][\}}d|	||dd}|di }| jr|dr|d |d< ||dd|ddid}| jr|dr|d |d d< || t |j|j|j|jd||d}|| qd S )Nr   )SeverityNumber
get_logger)	LogRecordr  r  r  messagesroleuserzgen_ai.content.prompt)
event_namer  toolidcontentzgen_ai.promptINFO)r/  trace_idspan_idtrace_flagsZseverity_numberZseverity_textbodyr  choiceszgen_ai.content.completionfinish_reason)r@  r  indexrJ  messagezmessage.contentZ	assistant)rK  rJ  rL  )rI   r'   r   r:  r;  r   r<  rj   Z!opentelemetry.sdk._logs._internalr    get_span_contextr   r  r   r   r   rE  rF  rG  rD  copyemit	enumerate)r5   r\   r   r   r:  r;  ZSdkLogRecordZotel_loggerZ
parent_ctxru   msgr>  attrsZ
log_recordidxchoiceZbody_msgrH  r6   r6   r7   r  '  sx   

z!OpenTelemetry._emit_semantic_logsr   r  c                 C   s4   ddl m} | dur|| S |dur||S |S )u1  
        Return a valid OTEL context for guardrail child spans so they are
        never orphaned (Issue #5).  Priority:
          1. The litellm_request span that was just created
          2. The parent proxy-request span
          3. The original fallback context (may be None — last resort)
        r   r|   N)r   r}   r   )r   r   r  _tracer6   r6   r7   r  }  s   

z(OpenTelemetry._resolve_guardrail_contextr   c                 C   sH  |pi }| d}|du rdS | d}|sdS dd |D }|s#dS | |}|D ]w}| d}| d}	t }
|durCt|}
t }|	durPt|	}|jd| |
|d	}| j|tj	t
jjd
 | j|d| dd
 | j|d| dd
 | d}|dur|dt| | j|d| dd
 |j| |d q*dS )zr
        Creates a span for Guardrail, if any guardrail information is present in standard_logging_object
        r  Nguardrail_informationc                 S   s   g | ]	}t |tr|qS r6   )r1   r   )rg   informationr6   r6   r7   
<listcomp>  s    z8OpenTelemetry._create_guardrail_span.<locals>.<listcomp>r   r   Z	guardrailr  r   Zguardrail_nameZguardrail_modemasked_entity_countZguardrail_responser   )r   r   r   r   fromtimestampr   r   r   r   ZOPENINFERENCE_SPAN_KINDr   Z	GUARDRAILr   set_attributer   r   )r5   r\   r   standard_logging_payloadZguardrail_information_dataZguardrail_information_listr  rV  Zstart_time_floatZend_time_floatZstart_time_datetimeZend_time_datetimeZguardrail_spanrY  r6   r6   r7   r     st   





z$OpenTelemetry._create_guardrail_spanc                 C   s\  ddl m}m} td|| j | |\}}t| do | jdk}	|	r'd }d }|d u p.t	d}
d }|
rf| 
|}|j| || ||d}|||j | ||| | j||d |j| |d	 n| r|||j | ||| | j||d | j|||d
}| j||d |d urt|dr|jtkr|j| |d	 d S d S d S d S )Nr   r   zPOpenTelemetry Logger: Failure HandlerLogging kwargs: %s, OTEL config settings=%srJ   r   r   r  )r   r\   r   r   r   r   )r   r   r   r   rq   rI   r   r   rJ   r   r   r   r  r   r   r   r  _record_exception_on_spanr   is_recordingr  r   r   r  )r5   r\   r   r   r   r   r   _parent_contextr   r	  r
  r   r  r  r6   r6   r7   r     sT   


zOpenTelemetry._handle_failurec           	   
   C   s\  zddl m} |d}|dur|| |d}|du r!W dS |d}|du r=|d}|r:| j||j|d W dS |d	rM| j||j|d	 d |d
r]| j||j|d
 d |drm| j||j|d d |dr}| j||j|d d |dr| j||j	|d d W dS W dS  t
y } ztdt| W Y d}~dS d}~ww )aQ  
        Record exception information on the span using OTEL standard methods.

        This extracts error information from StandardLoggingPayload and:
        1. Uses span.record_exception() for the actual exception object (OTEL standard)
        2. Sets structured error attributes from StandardLoggingPayloadErrorInformation
        r   )ErrorAttributesr   Nr  error_information	error_strr   Z
error_codeZerror_classerror_messageZllm_provider	tracebackz4OpenTelemetry: Error recording exception on span: %s)*litellm.integrations._types.open_inferencer`  r   Zrecord_exceptionr   ZERROR_MESSAGEZ
ERROR_CODEZ
ERROR_TYPEZERROR_LLM_PROVIDERZERROR_STACK_TRACErt   r   r   r2   )	r5   r   r\   r`  r   r\  ra  rb  rz   r6   r6   r7   r]  %  sr   








z'OpenTelemetry._record_exception_on_spanc           
   
   C   s   dd l }ddlm} |sd S zJt|D ]B\}}|d}|sq|jj d| }| j|| d|dd | j|| d|d	d | j|| d
||dd qW d S  t	ys }	 zt
dt|	 W Y d }	~	d S d }	~	ww )Nr   r   function.z.namer   r   z.descriptionr   z.parameters
parametersz1OpenTelemetry: Error setting tools attributes: %s)jsonlitellm.proxy._typesr   rP  r   ZLLM_REQUEST_FUNCTIONSr   r   dumpsrt   r   r   r2   )
r5   r   toolsrj  r   irA  rg  prefixrz   r6   r6   r7   set_tools_attributesx  sB   
z"OpenTelemetry.set_tools_attributesc                 C   B   |du rdS t |ttttfr|S zt|W S  ty    Y dS w z
        Casts the value to a primitive OTEL type if it is not already a primitive type.

        OTEL supports - str, bool, int, float

        If it's not a primitive type, then it's converted to a string
        Nr   r1   r2   rF   r   r   rt   r5   r   r6   r6   r7   cast_as_primitive_value_type     
z*OpenTelemetry.cast_as_primitive_value_type
tool_callsc           	   	   C   st   ddl m} i }t| D ]+\}}|d}|sqtj }|D ]}||}|r6|||jj d| d| < qq|S )Nr   rf  rg  rh  z.function_call.)	rk  r   rP  r   r   rE   keysZLLM_COMPLETIONSr   )	rw  r   kv_pairsrS  Z	tool_callZ	_functionrx  r   _valuer6   r6   r7   _tool_calls_kv_pair  s"   


z!OpenTelemetry._tool_calls_kv_pairc              
   C   s  z| j dkrddlm} | ||| W d S | j dkr-ddlm} |||| W d S | j dkrAddlm} |||| W d S ddl	m
} |d	i }|d
i pTi }	|d}
|
d u rbtd|
d }| D ]\}}| j|d||d qjt|
dd p|
pi di }|r| j|dt|d |
d}|r| D ]\}}|d ur| j|d| |d q|dr| j||jj|dd | j||jj|
d d | j||jj|	ddd |dr| j||jj|dd |dr| j||jj|dd |dr| j||jj|dd | j||jjt|ddd |dr:| j||jj|dd |rB|dnd pI|
d}|rU| j|d|d |rk|drk| j||jj|dd |or|d}|r| j||jj|d d | j||jj|d!d | j||jj|d"d t j!d#u rW d S | j"d#urW d S |d$r|d$ }| #|| |d%r| $|d%}| j||j%jt|d |d&r| $|d&}| j||j&jt|d | j||j'j|
dd'krd(n|
dp
d(d |
d)r | j||j(j|
d)d |d ur|d*r| )|d*}| j||j*jt|d g }t+|d*D ]\}}|d+rZ|,|d+ qH|rk| j||j-jt|d t+|d*D ]5\}}|d+r|d,}|d-}|rt./|}| D ]\}}| j|||d qqrW d S W d S W d S  t0y } z| j1| j pd.d/ t23d0t| W Y d }~d S d }~ww )1NZ	langtracer   )LangtraceAttributesr   )LangfuseOtelLoggerZ
weave_otel)set_weave_otel_attributesrf  r3  r  r  z+standard_logging_object not found in kwargsr  zmetadata.{}r   r  cost_breakdownzgen_ai.cost.r  r   r  r  Z
max_tokensZtemperatureZtop_pr4  Fr?  rB  zgen_ai.response.idr  Ztotal_tokensr#  r"  Trm  r=  Zsystem_instructions
completionr  Z
request_idrI  rJ  rL  rw  r   )rJ   z0OpenTelemetry logging error in set_attributes %s)4rJ   Zlitellm.integrations.langtracer|  Zset_langtrace_attributesZ+litellm.integrations.langfuse.langfuse_otelr}  Zset_langfuse_otel_attributesZ%litellm.integrations.weave.weave_otelr~  rk  r   r   r1  r   r   formatr%  r   ZLLM_REQUEST_MODELr   ZLLM_REQUEST_TYPEZ
LLM_SYSTEMZLLM_REQUEST_MAX_TOKENSZLLM_REQUEST_TEMPERATUREZLLM_REQUEST_TOP_PZLLM_IS_STREAMINGr2   ZLLM_USERZLLM_RESPONSE_MODELZGEN_AI_USAGE_TOTAL_TOKENSZGEN_AI_USAGE_OUTPUT_TOKENSZGEN_AI_USAGE_INPUT_TOKENSr   r  r  rp  0_transform_messages_to_otel_semantic_conventionsZGEN_AI_INPUT_MESSAGESZGEN_AI_SYSTEM_INSTRUCTIONSZGEN_AI_OPERATION_NAMEZGEN_AI_REQUEST_ID/_transform_choices_to_otel_semantic_conventionsZGEN_AI_OUTPUT_MESSAGESrP  rm   ZGEN_AI_RESPONSE_FINISH_REASONSrH   r{  rt   Zhandle_callback_failurer   r   )r5   r   r\   r   r|  r}  r~  r   r3  r  r\  r  r   r   r  r  Zresponse_idr  rm  Ztransformed_messagesZtransformed_system_instructionsZtransformed_choicesZfinish_reasonsrS  rT  rL  rw  ry  rz   r6   r6   r7   r    s  














zOpenTelemetry.set_attributesc                 C   rq  rr  rs  rt  r6   r6   r7   _cast_as_primitive_value_type  rv  z+OpenTelemetry._cast_as_primitive_value_typer   r   c                 C   s   |  |}||| dS )z_
        Safely sets an attribute on the span, ensuring the value is a primitive type.
        N)r  r[  )r5   r   r   r   Zprimitive_valuer6   r6   r7   r     s   
z OpenTelemetry.safe_set_attributer=  c           	      C   s   t |trdd|dgdgS g }|D ]e}|dd}|dd}g }t |tr1|d|d nt |trP|D ]}t |trE|| q8|dt|d q8||d}d	|v r_|d	 |d	< d
|v ri|d
 |d
< d|v rs|d |d< || q|S )z
        Transforms LiteLLM/OpenAI style messages into OTEL GenAI 1.38 compliant format.
        OTEL expects a 'parts' array instead of a single 'content' string.
        systemtext)rr   rC  )r>  partsr>  r?  rC  r   rB  rw  Ztool_call_id)r1   r2   r   rm   listr   )	r5   r=  transformedrQ  r>  rC  r  parttransformed_msgr6   r6   r7   r    s4   





z>OpenTelemetry._transform_messages_to_otel_semantic_conventionsrI  c                 C   sP   g }|D ]!}| dpi }| d}| |gd }|r ||d< || q|S )z_
        Transforms choices into OTEL GenAI 1.38 compliant format for output.messages.
        rL  rJ  r   )r   r  rm   )r5   rI  r  rT  rL  rJ  r  r6   r6   r7   r    s   
z=OpenTelemetry._transform_choices_to_otel_semantic_conventionsc              
   C   sX  z| di pi }| dd}| d}| di pi }| d}|r?t|tr?| D ]\}	}
| j|d| d|	 |
d	 q,|rt|trd
d l}z ||}| D ]\}	}
| j|d| d|	 |
d	 qTW W d S  |jy   t	
d| | j|d| d|d	 Y W d S w W d S W d S  ty } zt	dt| W Y d }~d S d }~ww )Nr  r  r  original_responseZadditional_argscomplete_input_dictzllm.rh  r   r   zglitellm.integrations.opentelemetry.py::set_raw_request_attributes() - raw_response not json string - {}z.stringified_raw_responsez<OpenTelemetry logging error in set_raw_request_attributes %s)r   r1   r   r   r   r2   rj  loadsJSONDecodeErrorr   rq   r  rt   r   )r5   r   r\   r   r  r  Z_raw_responseZ_additional_argsr  paramr.  rj  rz   r6   r6   r7   r  3  sX   

	

z(OpenTelemetry.set_raw_request_attributesc                 C   s   t | d S )Nr   )r   r/  )r5   dtr6   r6   r7   r   m  s   zOpenTelemetry._to_nsc                 C   s0   | di }| dpi }| d}|r|S tS )Nr  r  r  )r   LITELLM_REQUEST_SPAN_NAME)r5   r\   r  r  r  r6   r6   r7   r  p  s   
zOpenTelemetry._get_span_namec                 C   sN   |d u rd S | dd }|d u rd S ddlm} | }d|i}|j|d}|S )Ntraceparentr   TraceContextTextMapPropagatorcarrier)r   ,opentelemetry.trace.propagation.tracecontextr  extract)r5   r%   Z_traceparentr  Z
propagatorr  r_  r6   r6   r7   get_traceparent_from_headerz  s   z)OpenTelemetry.get_traceparent_from_headerr   c              
   C   sZ  ddl m}m} ddlm} |di pi }|di pi }|di p%i }|dd }	|di p3i }
|
d	d }|d urJtd
 |||fS |	d ur`td d|	i}| j	|dd fS z+|
 }|d ur| }|jrtd|t|jdt|jd|  | |fW S W n ty } ztdt| W Y d }~nd }~ww td dS )Nr   )r   r}   r  r  proxy_server_requestr%   r  r  Zlitellm_parent_otel_spanz7OpenTelemetry: Using explicit parent span from metadataz?OpenTelemetry: Using traceparent header for context propagationr  zcOpenTelemetry: Using active span from global context: %s (trace_id=%s, span_id=%s, is_recording=%s)Z032xZ016xz-OpenTelemetry: Error getting current span: %sz:OpenTelemetry: No parent context found, creating root span)NN)r   r   r}   r  r  r   r   rq   r   r  Zget_current_spanrM  Zis_validr  rE  rF  r^  Zget_currentrt   r2   )r5   r\   r   r   r}   r  r  r  r%   r  	_metadatar   r  Zcurrent_spanZspan_contextrz   r6   r6   r7   r     sZ   

zOpenTelemetry._get_span_contextc              
   C   s  ddl m}m}m}m} td| j| j| j	 t
j|p| j	d}|r0tddd | D  ntd t| jd	rJtd
| j |t|| jS | jdkr[td| j || S | jdksj| jdksj| jdkrzddlm} W n ty } ztd|d }~ww td| j | | jd}	|||	|dS | jdks| jdkrzddlm}
 W n ty } ztd|d }~ww td| j | | jd}	||
|	|dS td| j || S )Nr   )BatchSpanProcessorConsoleSpanExporterSimpleSpanProcessorr   zvOpenTelemetry Logger, initializing span processor 
self.OTEL_EXPORTER: %s
self.OTEL_ENDPOINT: %s
self.OTEL_HEADERS: %sr%   z=[OTEL DEBUG] Creating span processor with DYNAMIC headers: %sc                 S   s6   i | ]\}}|t t|d kr|dd  d n|qS )   Nz...)lenr2   )rg   kvr6   r6   r7   
<dictcomp>  s    $z5OpenTelemetry._get_span_processor.<locals>.<dictcomp>z8[OTEL DEBUG] Creating span processor with GLOBAL headersexportzDOpenTelemetry: intiializing SpanExporter. Value of OTEL_EXPORTER: %sr"   zHOpenTelemetry: intiializing console exporter. Value of OTEL_EXPORTER: %sr,   http/protobuf	http/json)OTLPSpanExporterzmOpenTelemetry OTLP HTTP exporter is not available. Install `opentelemetry-exporter-otlp` to enable OTLP HTTP.zEOpenTelemetry: intiializing http exporter. Value of OTEL_EXPORTER: %stracesr$   r%   	otlp_grpcgrpcz{OpenTelemetry OTLP gRPC exporter is not available. Install `opentelemetry-exporter-otlp` and `grpcio` (or `litellm[grpc]`).zEOpenTelemetry: intiializing grpc exporter. Value of OTEL_EXPORTER: %s)opentelemetry.sdk.trace.exportr  r  r  r   r   rq   r:   r;   r<   rH   r   r   r   r
   Z5opentelemetry.exporter.otlp.proto.http.trace_exporterr  rj   _normalize_otel_endpointZ5opentelemetry.exporter.otlp.proto.grpc.trace_exporter)r5   r   r  r  r  r   _split_otel_headersZOTLPSpanExporterHTTPexcnormalized_endpointZOTLPSpanExporterGRPCr6   r6   r7   r     s   





z!OpenTelemetry._get_span_processorc              
   C   sf  t d| j| j| j t| j}| | jd}t d| j| t| jdr0t d| j | jS t	
d}| jdks>|dkrNdd	lm} t d
| j | S | jdks]| jdks]| jdkrqddlm} t d| j| |||dS | jdks{| jdkrzddlm} W n ty } ztd|d}~ww t d| j| |||dS t d| j dd	lm} | S )zN
        Get the appropriate log exporter based on the configuration.
        ztOpenTelemetry Logger, initializing log exporter 
self.OTEL_EXPORTER: %s
self.OTEL_ENDPOINT: %s
self.OTEL_HEADERS: %slogsz4OpenTelemetry: Log endpoint normalized from %s to %sr  zDOpenTelemetry: Using custom log exporter. Value of OTEL_EXPORTER: %sZOTEL_LOGS_EXPORTERr"   r   )ConsoleLogExporterzEOpenTelemetry: Using console log exporter. Value of OTEL_EXPORTER: %sr,   r  r  )OTLPLogExporterzPOpenTelemetry: Using HTTP log exporter. Value of OTEL_EXPORTER: %s, endpoint: %sr  r  r  zOpenTelemetry OTLP gRPC log exporter is not available. Install `opentelemetry-exporter-otlp` and `grpcio` (or `litellm[grpc]`).NzPOpenTelemetry: Using gRPC log exporter. Value of OTEL_EXPORTER: %s, endpoint: %sziOpenTelemetry: Unknown log exporter '%s', defaulting to console. Supported: console, otlp_http, otlp_grpc)r   rq   r:   r;   r<   rH   r   r  r   r3   r4   r   r  Z4opentelemetry.exporter.otlp.proto.http._log_exporterr  Z4opentelemetry.exporter.otlp.proto.grpc._log_exporterrj   rk   )r5   r  r  Zotel_logs_exporterr  r  r  r6   r6   r7   r   *  s   



zOpenTelemetry._get_log_exporterc           
   
   C   s>  ddl m} ddlm}m}m} td| j| j	| j
 t| j
}| | j	d}| jdkr6| }||ddS | jd	ksE| jd
ksE| jdkr[ddlm} |||||jid}||ddS | jdkse| jdkrzddlm} W n ty~ }	 ztd|	d}	~	ww |||||jid}||ddS td| j | }||ddS )zO
        Get the appropriate metric reader based on the configuration.
        r   )	Histogram)AggregationTemporalityConsoleMetricExporterPeriodicExportingMetricReaderztOpenTelemetry Logger, initializing metric reader
self.OTEL_EXPORTER: %s
self.OTEL_ENDPOINT: %s
self.OTEL_HEADERS: %sr   r"   i  )Zexport_interval_millisr,   r  r  )OTLPMetricExporter)r$   r%   Zpreferred_temporalityr  r  zOpenTelemetry OTLP gRPC metric exporter is not available. Install `opentelemetry-exporter-otlp` and `grpcio` (or `litellm[grpc]`).NzlOpenTelemetry: Unknown metric exporter '%s', defaulting to console. Supported: console, otlp_http, otlp_grpc)r   r  Z opentelemetry.sdk.metrics.exportr  r  r  r   rq   r:   r;   r<   rH   r   r  Z6opentelemetry.exporter.otlp.proto.http.metric_exporterr  ZDELTAZ6opentelemetry.exporter.otlp.proto.grpc.metric_exporterrj   rk   )
r5   r  r  r  r  r  r  r#   r  r  r6   r6   r7   r   ~  s`   



z OpenTelemetry._get_metric_readerr$   signal_typec                 C   s   |s|S h d}||vrt d|| |S |d}d| }||r&|S ||h }|D ]}d| }||rJ|ddd d|  }|  S q-|dsV|| }|S |d|  }|S )a  
        Normalize the endpoint URL for a specific OpenTelemetry signal type.

        The OTLP exporters expect endpoints to use signal-specific paths:
        - traces: /v1/traces
        - metrics: /v1/metrics
        - logs: /v1/logs

        This method ensures the endpoint has the correct path for the given signal type.

        Args:
            endpoint: The endpoint URL to normalize
            signal_type: The telemetry signal type ('traces', 'metrics', or 'logs')

        Returns:
            Normalized endpoint URL with the correct signal path

        Examples:
            _normalize_otel_endpoint("http://collector:4318/v1/traces", "logs")
            -> "http://collector:4318/v1/logs"

            _normalize_otel_endpoint("http://collector:4318", "traces")
            -> "http://collector:4318/v1/traces"

            _normalize_otel_endpoint("http://collector:4318/v1/logs", "metrics")
            -> "http://collector:4318/v1/metrics"
        >   r  r  r   znInvalid signal_type '%s' provided to _normalize_otel_endpoint. Valid values: %s. Returning endpoint unchanged./z/v1/   r   z/v1)r   rk   rstripendswithrsplit)r5   r$   r  valid_signalstarget_pathZother_signalsZother_signal
other_pathr6   r6   r7   r    s4   






z&OpenTelemetry._normalize_otel_endpointr%   c                 C   sT   i }| r(t | tr!| d}|D ]}|dd\}}|||< q|S t | tr(| }|S )zY
        Convert a string or dictionary of headers into a dictionary of headers.
        ,=r  )r1   r2   splitr   )r%   r  r  r  r   r   r6   r6   r7   r   	  s   



z%OpenTelemetry._get_headers_dictionarylogging_payloadc                    s,  ddl m} ddlm}m} d}d}|j}|j}	t|tr%t	|d }n| 
|}t|	tr6t	|	d }n| 
|	}|d ur|j}
| jj|
|||d}|j}|d uri| D ]\}}| j|d| |d qY|j}|d ur| D ]\}}| j|d| |d qt|||j |j|d	 d S d S )
Nr   r|   r   r   r   request.r   z	response.r   )r   r}   r   r   r   r   r   r1   r   r   r   router   r   r   r   r   r   r   r   r   r   )r5   r  r   r}   r   r   r   r   r   r   r   management_endpoint_span_request_datar   r   	_responser6   r6   r7   &async_management_endpoint_success_hook	  sN   



z4OpenTelemetry.async_management_endpoint_success_hookc                    s  ddl m} ddlm}m} d}d}|j}|j}	t|tr't	t	|d }n| 
|}t|	tr:t	t	|	d }n| 
|	}|d ur|j}
| jj|
|||d}|j}|d urm| D ]\}}| j|d| |d q]|j}| j|dt|d |||j |j|d	 d S d S )
Nr   r|   r   r   r   r  r   r   r   )r   r}   r   r   r   r   r   r1   r   r   r   r  r   r   r   r   r   r   r   r2   r   r   r   )r5   r  r   r}   r   r   r   r   r   r   r   r  r  r   r   
_exceptionr6   r6   r7   &async_management_endpoint_failure_hookP	  sJ   



z4OpenTelemetry.async_management_endpoint_failure_hookc                 C   s&   | j jt| || j|d| jjdS )zF
        Create a span for the received proxy server request.
        r  )r   r   r   kind)r   r   r  r   r  r   ZSERVER)r5   r   r%   r6   r6   r7   )create_litellm_proxy_request_started_span	  s   	
z7OpenTelemetry.create_litellm_proxy_request_started_span)NNNNN)F)NNNN)r   NNNNrf   )PrB   rC   rD   r   r!   r2   r   rX   staticmethodrd   r[   rF   r{   rQ   rY   rZ   r   r   r   r   r   r   r	   r   r   r   r   r   rt   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r2  r'  r(  r)  r  r  r   r   r   r]  rp  r   ru  r   r   r   r{  r  r  r   r  r  r  r   r  r  r   r   r   r   r  r   r   r  r  r  __classcell__r6   r6   r]   r7   rH      s   (
I>
>
E

0
NF
F

+V
ODS$

  
+
:
8gTE
D

8
2rH   ):r3   dataclassesr   r   typingr   r   r   r   r   r	   r
   r   Zlitellm._loggingr   re  r   r   Z"litellm.integrations.custom_loggerr   Z*litellm.litellm_core_utils.safe_json_dumpsr   Zlitellm.secret_managers.mainr   Zlitellm.types.servicesr   Zlitellm.types.utilsr   r   r   r   r   r   r  r   Z_SpanExporterr   r   Z_Contextr   _Spanr   Z_Tracerrk  r   Z!_ManagementEndpointLoggingPayloadZlitellm.proxy.proxy_serverr   Z_UserAPIKeyAuthr4   r   r   r    r  r  r  r!   rH   r6   r6   r6   r7   <module>   sP    $ M