
    jj                     z   d dl Z d dlZd dlmZmZmZmZmZmZ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 d dlmZmZ d d	lmZmZmZmZmZmZmZm Z  er*d d
l!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. e
e#ef   Z"neZ"eZ&eZ(eZ*eZ+eZ,eZ/eZ0eZ. e jb                  de jd                        Z3 G d d      Z4y)    N)TYPE_CHECKINGAnyAsyncGeneratorDictListOptionalTupleUnion)	BaseModelverbose_logger)	DualCache)/DEFAULT_MAX_RECURSE_DEPTH_SENSITIVE_DATA_MASKER)ArgillaItem)AllMessageValuesChatCompletionRequest)AdapterCompletionStreamWrapper	CallTypesCallTypesLiteralLLMResponseTypesModelResponseModelResponseStreamStandardCallbackDynamicParamsStandardLoggingPayload)Span)Logging)UserAPIKeyAuth)MCPPostCallResponseObjectMCPPreCallRequestObjectMCPPreCallResponseObject)PreRoutingHookResponsezOdata:(?:application|image|audio|video)/[a-zA-Z0-9.+-]+;base64,[A-Za-z0-9+/=\s]+c                   ^   e Zd Z	 	 dgdededdfdZd Zd Zd Zd	 Zd
 Z	d Z
d Zd Zd Z	 	 	 dhdedee   dedee   dee   dededeee      dee   dee   deeee   ef   fdZ	 	 didedee   dedee   dee   dedee   dee   deeee   ef   fdZ	 	 	 	 djdededeeeeef         deeeef      dee   dee   fdZ	 	 didededeee      dee   d ee   dee   fd!Zd"eeef   d#ee    dee   fd$Z!d%ed ee   dee   fd&Z"d%edee   fd'Z#d(ed)e$d#ee    dee$   fd*Z%d(ed+ed#ee    dee   fd,Z&d-e'd.ee   d"efd/Z(d.ed"ed0e'fd1Z)d.ed"ed0e'fd2Z*dee+   fd3Z,d)e-dee.   fd4Z/d5edee0   fd6Z1d7e2d8ee3   dee2   fd9Z4	 d:e5d;e6d<ed#e7deee'eef      f
d=Z8	 dkd(ed0e'd:e5d>ee   fd?Z9d<ed:e5d)e$defd@Z:d"edAed#edeeef   fdBZ;d"edAed#edeeef   fdCZ<d<ed:e5d#e7defdDZ=d:e5d)edefdEZ>d:e5d)ed(ede?e@df   fdFZAdG ZBdH ZCdI ZDdJ ZEdKeFdeeF   fdLZGdMe3fdNZHdMe3dOedPeddfdQZIdRedPedefdSZJ	 dkdee   dee   fdTZKdUedefdVZLdWedee   fdXZMdYefdZZNeOfd[d\d]edd\fd^ZPeOfd[d\d]edd\fd_ZQd`eOfdaedbed]edefdcZRddedefdeZSeOfdee   d]edeeeef      fdfZTy)lCustomLoggerturn_off_message_loggingmessage_loggingreturnNc                      || _         || _        y)a  
        Args:
            turn_off_message_logging: bool - if True, the message logging will be turned off. Message and response will be redacted from StandardLoggingPayload.
            message_logging: bool - deprecated param, use `turn_off_message_logging` instead
        N)r%   r$   )selfr$   r%   kwargss       {/Users/manta/Documents/Projects/TheRoad-I1/backend/.venv/lib/python3.12/site-packages/litellm/integrations/custom_logger.py__init__zCustomLogger.__init__C   s      /(@%    c                      y N r(   modelmessagesr)   s       r*   log_pre_api_callzCustomLogger.log_pre_api_callS       r,   c                      y r.   r/   r(   r)   response_obj
start_timeend_times        r*   log_post_api_callzCustomLogger.log_post_api_callV   r4   r,   c                      y r.   r/   r6   s        r*   log_stream_eventzCustomLogger.log_stream_eventY   r4   r,   c                      y r.   r/   r6   s        r*   log_success_eventzCustomLogger.log_success_event\   r4   r,   c                      y r.   r/   r6   s        r*   log_failure_eventzCustomLogger.log_failure_event_   r4   r,   c                    K   y wr.   r/   r6   s        r*   async_log_stream_eventz#CustomLogger.async_log_stream_eventd   	        c                    K   y wr.   r/   r0   s       r*   async_log_pre_api_callz#CustomLogger.async_log_pre_api_callg   rC   rD   c                    K   y wr.   r/   r6   s        r*   async_log_success_eventz$CustomLogger.async_log_success_eventj   rC   rD   c                    K   y wr.   r/   r6   s        r*   async_log_failure_eventz$CustomLogger.async_log_failure_eventm   rC   rD   r1   r2   non_default_params	prompt_idprompt_variablesdynamic_callback_paramslitellm_logging_objtoolsprompt_labelprompt_versionc                    K   |||fS wax  
        Returns:
        - model: str - the model to use (can be pulled from prompt management tool)
        - messages: List[AllMessageValues] - the messages to use (can be pulled from prompt management tool)
        - non_default_params: dict - update with any optional params (e.g. temperature, max_tokens, etc.) to use (can be pulled from prompt management tool)
        r/   )r(   r1   r2   rK   rL   rM   rN   rO   rP   rQ   rR   s              r*    async_get_chat_completion_promptz-CustomLogger.async_get_chat_completion_promptr   s     & h 222s   c	                     |||fS rT   r/   )	r(   r1   r2   rK   rL   rM   rN   rQ   rR   s	            r*   get_chat_completion_promptz'CustomLogger.get_chat_completion_prompt   s    " h 222r,   request_kwargsinputspecific_deploymentc                    K   yw)z
        This hook is called before the routing decision is made.

        Used for the litellm auto-router to modify the request before the routing decision is made.
        Nr/   )r(   r1   rX   r2   rY   rZ   s         r*   async_pre_routing_hookz#CustomLogger.async_pre_routing_hook   s      rD   healthy_deploymentsparent_otel_spanc                    K   |S wr.   r/   )r(   r1   r]   r2   rX   r^   s         r*   async_filter_deploymentsz%CustomLogger.async_filter_deployments   s      #"s   r)   	call_typec                    K   yw)a  
        Allow modifying the request just before it's sent to the deployment.

        Use this instead of 'async_pre_call_hook' when you need to modify the request AFTER a deployment is selected, but BEFORE the request is sent.

        Used in managed_files.py
        Nr/   )r(   r)   ra   s      r*   async_pre_call_deployment_hookz+CustomLogger.async_pre_call_deployment_hook   s      	rD   
deploymentc                    K   y wr.   r/   )r(   rd   r^   s      r*   async_pre_call_checkz!CustomLogger.async_pre_call_check         	rD   c                      y r.   r/   )r(   rd   s     r*   pre_call_checkzCustomLogger.pre_call_check   r4   r,   request_dataresponsec                    K   yw)zh
        Allow modifying / reviewing the response just after it's received from the deployment.
        Nr/   )r(   rj   rk   ra   s       r*   'async_post_call_success_deployment_hookz4CustomLogger.async_post_call_success_deployment_hook         	rD   response_chunkc                    K   yw)z
        Allow modifying streaming chunks just before they're returned to the user.

        This is called for each streaming chunk in the response.
        Nr/   )r(   rj   ro   ra   s       r*   )async_post_call_streaming_deployment_hookz6CustomLogger.async_post_call_streaming_deployment_hook   s      	rD   	exceptionoriginal_model_groupc                    K   y wr.   r/   )r(   rr   rs   r)   s       r*    log_model_group_rate_limit_errorz-CustomLogger.log_model_group_rate_limit_error   rg   rD   original_exceptionc                    K   y wr.   r/   r(   rs   r)   rv   s       r*   log_success_fallback_eventz'CustomLogger.log_success_fallback_event   rg   rD   c                    K   y wr.   r/   rx   s       r*   log_failure_fallback_eventz'CustomLogger.log_failure_fallback_event   rg   rD   c                      y)zt
        Translates the input params, from the provider's native format to the litellm.completion() format.
        Nr/   )r(   r)   s     r*   !translate_completion_input_paramsz.CustomLogger.translate_completion_input_params        	r,   c                      y)z\
        Translates the output params, from the OpenAI format to the custom format.
        Nr/   )r(   rk   s     r*   "translate_completion_output_paramsz/CustomLogger.translate_completion_output_params   r~   r,   completion_streamc                      y)z^
        Translates the streaming chunk, from the OpenAI format to the custom format.
        Nr/   )r(   r   s     r*   ,translate_completion_output_params_streamingz9CustomLogger.translate_completion_output_params_streaming  r~   r,   logged_itemstandard_logging_payloadc                     K   t        d      w)z
        - Decide if the result should be logged to Argilla.
        - Modify the result before logging to Argilla.
        - Return None if the result should not be logged to Argilla.
        z"async_dataset_hook not implemented)NotImplementedError)r(   r   r   s      r*   async_dataset_hookzCustomLogger.async_dataset_hook  s      ""FGGs   user_api_key_dictcachedatac                    K   y wr.   r/   )r(   r   r   r   ra   s        r*   async_pre_call_hookz CustomLogger.async_pre_call_hook!  rn   rD   traceback_strc                    K   y wr.   r/   )r(   rj   rv   r   r   s        r*   async_post_call_failure_hookz)CustomLogger.async_post_call_failure_hook,        	rD   c                    K   y wr.   r/   )r(   r   r   rk   s       r*   async_post_call_success_hookz)CustomLogger.async_post_call_success_hook5        	rD   resultc                    K   ||fS wzUFor masking logged request/response. Return a modified version of the request/result.r/   r(   r)   r   ra   s       r*   async_logging_hookzCustomLogger.async_logging_hook=  s      v~s   c                 
    ||fS r   r/   r   s       r*   logging_hookzCustomLogger.logging_hookC  s     v~r,   c                    K   y wr.   r/   )r(   r   r   ra   s       r*   async_moderation_hookz"CustomLogger.async_moderation_hookI  r   rD   c                    K   y wr.   r/   )r(   r   rk   s      r*   async_post_call_streaming_hookz+CustomLogger.async_post_call_streaming_hookQ  s     
 	rD   c                4   K   |2 3 d {   }| 7 
6 y wr.   r/   )r(   r   rk   rj   items        r*   'async_post_call_streaming_iterator_hookz4CustomLogger.async_post_call_streaming_iterator_hookX  s      # 	$J	(s   c                     	 ||d<   ||d<   d|d<    ||        |d|        y # t         $ r   |dt        j                                 Y y w xY wNr1   r2   pre_api_calllog_event_typez$Custom Logger - model call details: Custom Logger Error - 	Exception	traceback
format_excr(   r1   r2   r)   print_verbosecallback_funcs         r*   log_input_eventzCustomLogger.log_input_eventc  sn    		M#F7O!)F:'5F#$ @IJ 	M293G3G3I2JKL	Ms   "% &AAc                    K   	 ||d<   ||d<   d|d<    ||       d {     |d|        y 7 # t         $ r   |dt        j                                 Y y w xY wwr   r   r   s         r*   async_log_input_eventz"CustomLogger.async_log_input_evento  s     		M#F7O!)F:'5F#$   @IJ  	M293G3G3I2JKL	Ms1   A1 /1 A1 &AAAAc                 ~    	 d|d<    |||||       y # t         $ r   |dt        j                                 Y y w xY wNpost_api_callr   r   r   r(   r)   r7   r8   r9   r   r   s          r*   	log_eventzCustomLogger.log_event}  sT    
	'6F#$	  	293G3G3I2JKL	s    &<<c                    K   	 d|d<    |||||       d {    y 7 # t         $ r   |dt        j                                 Y y w xY wwr   r   r   s          r*   async_log_eventzCustomLogger.async_log_event  sa     
	'6F#$	    	293G3G3I2JKL	s1   A  A &AAAAr7   c                    K   yw)z
        This log gets called after the MCP tool call is made.

        Useful if you want to modiy the standard logging payload after the MCP tool call is made.
        Nr/   r6   s        r*   async_post_mcp_tool_call_hookz*CustomLogger.async_post_mcp_tool_call_hook  s      rD   standard_logging_objectc                 F    d}g d}|D ]  }| j                  |||        y)a  
        Truncate error strings and message content in logging payload

        Some loggers like DataDog/ GCS Bucket have a limit on the size of the payload. (1MB)

        This function truncates the error string and the message content if they exceed a certain length.
        i'  )	error_strr2   rk   )r   
field_name
max_lengthN)_truncate_field)r(   r   MAX_STR_LENGTHfields_to_truncatefields        r*   )truncate_standard_logging_payload_contentz6CustomLogger.truncate_standard_logging_payload_content  s8       C'E  (? ) !  (r,   r   r   c                     |j                  |      }|r1t        |      }t        |      |kD  r| j                  ||      ||<   yyy)aP  
        Helper function to truncate a field in the logging payload

        This converts the field to a string and then truncates it if it exceeds the max length.

        Why convert to string ?
        1. User was sending a poorly formatted list for `messages` field, we could not predict where they would send content
            - Converting to string and then truncating the logged content catches this
        2. We want to avoid modifying the original `messages`, `response`, and `error_str` in the logging payload since these are in kwargs and could be returned to the user
        )textr   N)getstrlen_truncate_text)r(   r   r   r   field_value	str_values         r*   r   zCustomLogger._truncate_field  sX      .11*=K(I9~
*6:6I6I"z 7J 7'
3 + r,   r   c                 2    t        |      |kD  r|d| dz   S |S )z&Truncate text if it exceeds max_lengthNzC...truncated by litellm, this logger does not support large content)r   )r(   r   r   s      r*   r   zCustomLogger._truncate_text  s4    
 4y:% *ST	
 		
r,   c                 (    ddl m}m} |y||v r|S |S )z
        Select the metadata field to use for logging

        1. If `litellm_metadata` is in the request kwargs, use it
        2. Otherwise, use `metadata`
        r   )LITELLM_METADATA_FIELDOLD_LITELLM_METADATA_FIELDN)litellm.constantsr   r   )r(   rX   r   r   s       r*   _select_metadata_fieldz#CustomLogger._select_metadata_field  s%     	Y!!^3))))r,   model_call_detailsc                    ddl m } ddlm}m}m} t        | dd      }|du r|S  ||      }d}|j                  d      }	|	|S  ||	      }
|
j                  d       ||	      j                         g|
d<   |
j                  d
      |
d
   }t        |t              rd|v rddl m
}  ||      }t        |j                  d      t              rY|d   D ]Q  }t        |t              sd|v st        |d   t              s-|d   D ]  }t        |t              sd|v s||d<    S ||
d
<   n- | | ||	            g      }|j                         }||
d
<   |
|d<   |S )aJ  
        Only redacts messages and responses when self.turn_off_message_logging is True


        By default, self.turn_off_message_logging is False and this does nothing.

        Return a redacted deepcopy of the provided logging payload.

        This is useful for logging payloads that contain sensitive information.
        r   )copy)ChoicesMessager   r$   Fzredacted-by-litellmr   r2   contentrk   output)deepcopyr   r   )message)choices)r   litellmr   r   r   getattrr   
model_dump
isinstancedictr   list)r(   r   r   r   r   r   r$   model_call_details_copyredacted_strr   standard_logging_object_copyrk   r   response_copyoutput_itemcontent_itemmodel_responsemodel_response_dicts                     r*   7redact_standard_logging_payload_from_model_call_detailszDCustomLogger.redact_standard_logging_payload_from_model_call_details  s    	;;)07QSX)Y #u,%% #''9":,"4"8"89R"S"*** (,,C'D$'++J7C-88:8(4 (++J7C3J?H(D)h(.B) ( 2m//94@'4X'>%k48Y+=U)+i*@$G4?	4JL'1,'E&T`J`?KV(< 5K	 (? <I,Z8 "/$W\-JKL" '5&?&?&A#;N,Z8 ) 	  9: '&r,   
object_keyc                    K   yw)z_
        Get the proxy server request from cold storage using the object key directly.
        Nr/   )r(   r   s     r*   :get_proxy_server_request_from_cold_storage_with_object_keyzGCustomLogger.get_proxy_server_request_from_cold_storage_with_object_key8  r   rD   callback_namec           	      l   	 ddl }ddlm} |j                  j	                         }|D ]7  }t        |d      s |j                  d|        |j                  |        y  |j                  d| d       y# t        $ r1}ddlm}  |j                  d	| d
t        |              Y d}~yd}~ww xY w)z
        Handle callback logging failures by incrementing Prometheus metrics.
        
        Call this method in exception handlers within your callback when logging fails.
        r   Nr   "increment_callback_logging_failurez)Incrementing callback failure metric for )r   zENo callback with increment_callback_logging_failure method found for z2. Ensure 'prometheus' is in your callbacks config.z%Error in handle_callback_failure for z: )
r   litellm._loggingr   logging_callback_manager_get_all_callbackshasattrdebugr   r   r   )r(   r   r   r   all_callbackscallback_objes          r*   handle_callback_failurez$CustomLogger.handle_callback_failureA  s    	d7#<<OOQM -<)MN(N((+TUbTc)de CCR_C`	 !. !N  WXeWf gC C
  	d7 N  #HWYZ]^_Z`Ya!bcc	ds"   5A9 (A9 !A9 9	B3'B..B3payloadr   	max_depthc                   K   |j                  dg       }t        |t              r|ng }t        j                  dt        |       d       |r| j                  ||      |d<   d}|j                  dg       xs g D ]D  }t        |t              s|j                  dg       }t        |t              s7|t        |      z  }F t        j                  d| d       |S w	u  
        Removes or redacts base64-encoded file data (e.g., PDFs, images, audio)
        from messages and responses before sending to SQS.

        Behavior:
          • Drop entries with a 'file' key.
          • Drop entries with type == 'file' or any non-text type.
          • Keep untyped or text content.
          • Recursively redact inline base64 blobs in *any* string field, at any depth.
        r2   z%[CustomLogger] Stripping base64 from z	 messages)r2   r   r   r   z0[CustomLogger] Completed base64 strip; retained z content itemsr   r   r   r   r   r   _process_messagesr   r(   r   r   raw_messagesr2   total_itemsmr   s           r*   _strip_base64_from_messagesz(CustomLogger._strip_base64_from_messages\  s      $KK
B7.8t.LlRTDS]OS\]^"&"8"8(V_"8"`GJZ,22A!T"%%	2.gt,3w</K	 3 	>{m>Z	
 s   BC"C2+Cc                    |j                  dg       }t        |t              r|ng }t        j                  dt        |       d       |r| j                  ||      |d<   d}|j                  dg       xs g D ]D  }t        |t              s|j                  dg       }t        |t              s7|t        |      z  }F t        j                  d| d       |S r   r   r  s           r*    _strip_base64_from_messages_syncz-CustomLogger._strip_base64_from_messages_sync~  s     $KK
B7.8t.LlRTDS]OS\]^"&"8"8!Y #9 #GJ Z,22A!T"%%	2.gt,3w</K	 3 	>{m>Z	
 r,   r   valuedepthc           
         ||kD  rt        j                  d| d       yt        |t              rIt        j                  |      r2t        j                  d|dd  d       t        j                  d|      S |S t        |t              r%|D cg c]  }| j                  ||d	z   |
       c}S t        |t              r9|j                         D ci c]  \  }}|| j                  ||d	z   |
       c}}S |S c c}w c c}}w )z\Recursively redact inline base64 from any nested structure with a max recursion depth limit.z#[CustomLogger] Max recursion depth z reached while redacting base64z[MAX_DEPTH_REACHED]z.[CustomLogger] Redacted inline base64 string: N(   z...z[BASE64_REDACTED]   )r	  r
  r   )r   warningr   r   _BASE64_INLINE_PATTERNsearchr   subr   _redact_base64r   items)r(   r	  r
  r   vks         r*   r  zCustomLogger._redact_base64  s&    9""5i[@_` )eS!%,,U3$$DU3BZLPST .112EuMMLeT" A ##!519	#R 
 eT" "KKM)DAq 4&&Qeai9&UU) 
 s   C9"C>r   c                     t        |t              syd|v ry|j                  d      }t        |t              xr |dk7   S )z4Return True if this content item should be retained.TfileFtyper   )r   r   r   r   )r(   r   ctypes      r*   _should_keep_contentz!CustomLogger._should_keep_content  sA    '4(WF#uc*>u??r,   c                    g }|D ]  }t        |t              s|j                  d      }t        |t              rDg }|D ]7  }| j	                  |      s|j                  | j                  ||             9 ||d<   n| j                  ||      |d<   t        |j                               D ]!  \  }}	|dk7  s| j                  |	|      ||<   # |j                  |        |S )Nr   r   )r	  r   )r   r   r   r   r  appendr  r  )
r(   r2   r   filtered_messagesmsgcontentscleanedckeyvals
             r*   r  zCustomLogger._process_messages  s    24Cc4(GGI.H(D)%'!A000; //a9/M "
 ")I!%!4!4"i "5 "I !-S)##22	2RCH . $$S)) * ! r,   )FT)NNN)NN)NNFr.   )U__name__
__module____qualname__boolr+   r3   r:   r<   r>   r@   rB   rF   rH   rJ   r   r   r   r   r   r   LiteLLMLoggingObjr   intr	   rU   rW   r
   r!   r\   r   r`   r   r   rc   rf   ri   r   rm   rq   r   ru   ry   r{   r   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r/   r,   r*   r#   r#   A   si    */ $	"& 	 
 
 '+&*(,33 '(3 !	3
 C=3 #4.3 "?3 /3 T
#3 sm3 !3 
sD)*D0	13: '+(,33 '(3 !	3
 C=3 #4.3 "?3 sm3 !3 
sD)*D0	13( 48,0.3  4S#X/0	
 c4i() &d^ 
(	)( *.+/## "# 4 012	#
 !# #4.# 
d#
38n
19)1D
	$
2:4.	$
 (4. 		 #	 I&		
 
"	#	  I&	
 
#":B3-QU
$'15KT
$'15KT	'	(%	)	!$	0	1
H 
H #++A"B
H 
+		
H	)	 	 		
 $	 
id"#
	  (, & *	
  } * #	
 
$'47	tSy	$'47	tSy	 * $	
 
)  
	)  	
 
+T1	2
MM ($=	+	,!7,!7  	
 
0
3 
C 
C 
 04*&tn*	#*"A'"&A'	A'F 
$dS d< I )    
"	 F Gv 3 @C 	! J H	!! ! 	!
 
!F@C @D @ Gv !$s) ! !z~  @D  EH  JM  EM  @N  {O !r,   r#   )5rer   typingr   r   r   r   r   r   r	   r
   pydanticr   r   r   litellm.caching.cachingr   r   r   "litellm.types.integrations.argillar   litellm.types.llms.openair   r   litellm.types.utilsr   r   r   r   r   r   r   r   opentelemetry.tracer   _Span*litellm.litellm_core_utils.litellm_loggingr   r(  litellm.proxy._typesr   litellm.types.mcpr   r   r    litellm.types.routerr!   MCPDuringCallRequestObjectMCPDuringCallResponseObjectcompile	MULTILINEr  r#   r/   r,   r*   <module>r;     s    
 	 	 	  + - M : M	 	 	 1W3 
 <DDN #!"!$"%  $VLL b
! b
!r,   