
    ^h                       S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SKrS SK	r	S SK
J
r
Jr  S SKJr  S SKJr  S SKJrJrJrJrJrJrJr  S SKJr  S SKJrJrJr   S SKrS S	K J!r!J"r"  S SK#r#S SK$r#S SK%r#S S
K#J&r&J'r'J(r(J)r)  S SK*J+r+  S SK,J-r-J.r.  S SK/J0r0J1r1  S SK2J3r3  S SK4J5r5  S SK6J7r7  S SK8J9r9  S SK:J;r;  S SK%J<r<  S SK=J>r>  S SKJ?r?J@r@JArAJBrBJCrCJDrD  S SKEJFrFJGrG  S SKHJIrI  S SKJJKrK  S SKLJMrM  S SKNJOrO  S SKPJQrQ  S SKRJSrS  S SKTJUrU  S SKVJWrW  S SKXJYrYJZrZ  \(       a	  S S K[J\r]  \]r\O\r\S! r^S" r_ " S# S$5      r` " S% S&5      raS' rb " S( S)5      rcSHS*\dS+\\d   S,\4S- jjreS.\dS/\0S0\c4S1 jrfS2 rgS3\d4S4 jrhS3\dS,\d4S5 jriS6\c4S7 jrjS6\cS8\\>   S9\a4S: jrkS;\lS<\mS9\a4S= jrnS>\mS?\\m   4S@ jroS>\mS?\\m   S,\\p   4SA jrqSISB jrrSC rsS;\lS,\d4SD jrtS,\d4SE jruS,\\d   4SF jrvS;\lS,\4SG jrwg! \ a	    \" S5      ef = f)J    N)datetime	timedelta)MIMEMultipart)MIMEText)TYPE_CHECKINGAnyListLiteralOptionalUnionoverload)duration_in_seconds)DB_CONNECTION_ERROR_TYPESProxyErrorTypesProxyExceptionzEbackoff is not installed. Please install it via 'pip install backoff')HTTPExceptionstatus)EmbeddingResponseImageResponseModelResponseRouter)verbose_proxy_logger)ServiceLoggingServiceTypes)	DualCache
RedisCache)RejectedRequestError)CustomGuardrail)CustomLogger)SlackAlerting)_add_langfuse_trace_id_to_alert)Logging)HTTPHandler)	AlertTypeCallInfoLiteLLM_VerificationTokenViewMemberResetTeamBudgetRequestUserAPIKeyAuth)create_missing_viewsshould_create_missing_views)log_db_metrics)PrismaWrapper)_PROXY_CacheControlCheck)_PROXY_MaxBudgetLimiter)!_PROXY_MaxParallelRequestsHandler)LiteLLMProxyRequestSetup)str_to_bool)DEFAULT_ALERT_TYPES)	CallTypesLoggedLiteLLMParams)Spanc                     SSK n[        R                  " SR                  XR                  " 5       5      5        [
        R                  (       a  [        SU  35        gg)a  
Prints the given `print_statement` to the console if `litellm.set_verbose` is True.
Also logs the `print_statement` at the debug level using `verbose_proxy_logger`.

:param print_statement: The statement to be printed and logged.
:type print_statement: Any
r   Nz{}
{}zLiteLLM Proxy: )	tracebackr   debugformat
format_exclitellmset_verboseprint)print_statementr8   s     M/home/james-whalen/.local/lib/python3.13/site-packages/litellm/proxy/utils.pyprint_verboserA   N   sE     x@T@T@VWX012     c                    [         R                  SL a  U $ SnSn[        U [        5      (       a#  SU ;   a  SU S   ;   a  U S   R	                  S5      n[
        R                  " U 5      n[        U [        5      (       a  Ub  SU ;   a  XS   S'   U$ )z
Safe Deep Copy

The LiteLLM Request has some object that can-not be pickled / deep copied

Use this function to safely deep copy the LiteLLM Request
TNmetadatalitellm_parent_otel_span)r<   safe_memory_mode
isinstancedictpopcopydeepcopy)datarE   new_datas      r@   safe_deep_copyrN   ]   s     4'.2#$"<Z@P"P'+J'7';';<V'W$}}T"H $":"F;S78OrB   c            	          \ rS rSrS\4S jr SS\\S4   S\S\	4S jjr
 SS\\S4   S\SS4S	 jjr SS
\S\\S4   S\SS4S jjr  SS\S\\   S\4S jjr SS\S\\S4   S\4S jjr SS\SS4S jjr SS\S\	4S jjrSrg)InternalUsageCachex   
dual_cachec                     Xl         g NrR   )selfrR   s     r@   __init__InternalUsageCache.__init__y   s    %/rB   rE   N
local_onlyreturnc                 ^   #    U R                   R                  " SUUUS.UD6I S h  vN $  N7f)N)keyrY   parent_otel_span )rR   async_get_cache)rV   r\   rE   rY   kwargss        r@   r_   "InternalUsageCache.async_get_cache|   s@      __44 
!5
 	
 
 	
 
   $-+-c                 `   #    U R                   R                  " SUUUUS.UD6I S h  vN $  N7f)N)r\   valuerY   rE   r^   )rR   async_set_cacherV   r\   rd   rE   rY   r`   s         r@   re   "InternalUsageCache.async_set_cache   sC      __44 
!%=	

 
 
 	
 
   %.,.
cache_listc                 ^   #    U R                   R                  " SUUUS.UD6I S h  vN $  N7f)N)ri   rY   rE   r^   )rR   async_set_cache_pipeline)rV   ri   rE   rY   r`   s        r@   async_batch_set_cache(InternalUsageCache.async_batch_set_cache   s@      __== 
!!%=
 	
 
 	
 
rb   keysr]   c                 T   #    U R                   R                  UUUS9I S h  vN $  N7f)N)rn   r]   rY   )rR   async_batch_get_cache)rV   rn   r]   rY   s       r@   rp   (InternalUsageCache.async_batch_get_cache   s6      __::-! ; 
 
 	
 
s   (&(rd   c                 `   #    U R                   R                  " SUUUUS.UD6I S h  vN $  N7f)N)r\   rd   rY   r]   r^   )rR   async_increment_cacherf   s         r@   rs   (InternalUsageCache.async_increment_cache   sC      __:: 
!5	

 
 
 	
 
rh   c                 B    U R                   R                  " SUUUS.UD6$ )N)r\   rd   rY   r^   )rR   	set_cache)rV   r\   rd   rY   r`   s        r@   rv   InternalUsageCache.set_cache   s3     (( 
!
 	
 	
rB   c                 @    U R                   R                  " SUUS.UD6$ )N)r\   rY   r^   )rR   	get_cache)rV   r\   rY   r`   s       r@   ry   InternalUsageCache.get_cache   s0     (( 
!
 
 	
rB   rU   F)NF)__name__
__module____qualname____firstlineno__r   rW   r   r6   boolr   r_   re   r	   rl   listr   rp   floatrs   rv   ry   __static_attributes__r^   rB   r@   rP   rP   x   sH   09 0 !	
 #(d
"3
 	
 

& !
 #(d
"3	

 
 

( !	

 #(d
"3
 	
 

" ,0 	



 #4.

 	

" !
 
 #(d
"3	

 
( !	
 	
 

" !

 


 


 

rB   rP   c                      \ rS rSrSr S;S\S\4S jjrS\\	   S\\
   4S jr      S<S
\\   S\\   S\\
   S\\\      S\\   S\\   4S jjrS=S\\	   4S jjrS\S\S   4S jrS r\S\SS	S\S   SS	4S j5       r\S\S\S\S   S\4S j5       rS\S\\   S\S   S\\   4S jrS\S\S\S   4S  jrS!\S"\4S# jrS$\S%   S&\4S' jr S=S(\S)\S*   S+\S,\\   4S- jjr S>S.\S\4S/ jjr  S?S,\S0\S\S1\\    S2\\   4
S3 jjr! S=S0\S1\\    S\4S4 jjr"  S?S,\S\S2\\   S0\\   4S5 jjr#S\S6\$\%\&\'4   S\4S7 jr(S6\$\%\&\'4   S\4S8 jr)S6\S\4S9 jr*S:r+g	)@ProxyLogging   z
Logging/Custom Handlers for proxy.

Implemented mainly to:
- log successful/failed db read/writes
- support the max parallel request integration
user_api_key_cachepremium_userc                    0 U l         XR                   S'   [        [        SS9S9U l        [	        U R                  5      U l        [        5       U l        [        5       U l	        S U l
        SU l        [        U l        S U l        [        U R                  U R                  U R                  R                   S9U l        X l        ['        5       U l        g )Nr      )default_in_memory_ttlrU   i,  )alerting_thresholdalertinginternal_usage_cache)call_detailsrP   r   r   r0   max_parallel_request_limiterr/   max_budget_limiterr.   cache_control_checkr   r   r3   alert_typesalert_to_webhook_urlr    rR   slack_alerting_instancer   r   service_logging_obj)rV   r   r   s      r@   rW   ProxyLogging.__init__   s     #%2D./8J q99
! -N%%-
) #:";#;#= (,),,?48!6C#66]]!%!:!:!E!E7
$
 )#1#3 rB   
llm_routerredis_usage_cachec                    U R                   R                  US9  U R                  US9  U R                  US9  U R                   bI  SU R                   R                  ;   a.  [        R
                  " U R                   R                  US95        ggg)z0Initialize logging and alerting on proxy startup)r   )redis_cacheNdaily_reports)r   update_values_init_litellm_callbacksr   asynciocreate_task_run_scheduled_daily_report)rV   r   r   s      r@   startup_eventProxyLogging.startup_event  s     	$$22j2I 	) 	 	
 	$$! 	% 	

 ((44#?#?#K#KK,,HH) I  L 5rB   Nr   r   r   r   alerting_argsr   c                 B   SnUb  Xl         SnUb  X l        SnUb  X@l        SnUb  X`l        SnUSL a  U R                  R                  U R                   U R                  U R                  UU R                  S9  U R                   b|  SU R                   ;   al  SU R                  ;   a)  [        R                  R                  U R                  5        [        R                  R                  U R                  R                  5        Ub  X0R                  R                  l        g g )NFT)r   r   r   r   r   slackr   )r   r   r   r   r   r   r<   	callbacksappendsuccess_callback!response_taking_too_long_callbackr   rR   r   )rV   r   r   r   r   r   r   updated_slack_alertings           r@   r   ProxyLogging.update_values!  s    (-$M%)")&8#%)""*%)"+(<%%)"!T)((66#'#:#: ,,+%)%>%> 7  }}(W-E #d&6&66%%,,T-I-IJ((//00RR "?J%%00< #rB   c                    [         R                  R                  U R                  5        [         R                  R                  U R                  5        [         R                  R                  U R
                  5        [         R                  R                  U R                  5        [         R                   GH  n[        U[        5      (       aB  [         R                  R                  R                  UU R                  R                  US9nUc  M[  U[         R                  ;  a  [         R                  R                  U5        U[         R                  ;  a  [         R                  R                  U5        U[         R                   ;  a  [         R                   R                  U5        U[         R"                  ;  a  [         R"                  R                  U5        U[         R$                  ;  a  [         R$                  R                  U5        U[         R&                  ;  d  GMq  [         R&                  R                  U5        GM     [)        [         R                  5      S:  d:  [)        [         R                  5      S:  d  [)        [         R                   5      S:  al  [+        [-        [         R                  [         R                  -   [         R                   -   5      5      n[         R                  R                  R/                  US9  g g )N)r   r   r   )callback_list)r<   r   r   r   r   r   r   rG   strlitellm_core_utilslitellm_logging$_init_custom_logger_compatible_classr   rR   input_callbackr   failure_callback_async_success_callback_async_failure_callbackservice_callbacklenr   setset_callbacks)rV   r   callbackr   s       r@   r   $ProxyLogging._init_litellm_callbacksM  s1     !B!BC  !8!89  !9!9:  !9!9:))H(C(("55EEjj)-)B)B)M)M) k 
 #w555&&--h7w777((//9w777((//9w>>>//66x@w>>>//66x@w777((//9) *. &&'!+7++,q07++,q0 **../../M &&66DD+ E  1rB   litellm_call_idr   )successfailc                    #    U R                   c  g U R                  nUS-  nU R                  R                  SR	                  U5      USUS S9I S h  vN   g  N7f)Nd   zrequest_status:{}T)r\   rd   rY   ttlrE   )r   r   r   re   r:   )rV   r   r   r   s       r@   update_request_status"ProxyLogging.update_request_statusx  sl      ==  %)$;$; 	c!''77#**?;"%) 8 
 	
 	
s   AAAAc                    #    [        U[        5      (       a  Ue[        U[        5      (       a  U$ [        U[        5      (       a.  US;   a  [	        UUR                  SS5      SUS9e[        SSU0S9eU$ 7f)N)
completiontext_completionmodel )messager   llm_providerrequest_data  errorstatus_codedetail)rG   	ExceptionrH   r   r   getr   )rV   responserL   	call_types       r@   process_pre_call_hook_response+ProxyLogging.process_pre_call_hook_response  s|     h	**Nh%%Oh$$==*$((7B/!#!%	  $Wh<OPPs   A4A6user_api_key_dictrL   r   )r   r   
embeddingsimage_generation
moderationaudio_transcriptionpass_through_endpointrerankrZ   c                    #    g 7frT   r^   rV   r   rL   r   s       r@   pre_call_hookProxyLogging.pre_call_hook  
       	   c                    #    g 7frT   r^   r   s       r@   r   r     r   r   c                 v  #    [        S5        [        R                  " U R                  R	                  US95        Uc  g [
        R                   GHF  nSn[        U[        5      (       a*  [
        R                  R                  R                  U5      nOUnUb  [        U[        5      (       aj  SSKJn  UR                  X&R                   S9SLa  M  UR#                  UU R$                  S   UUS	9I Sh  vN nUb  U R'                  XrUS
9I Sh  vN nM  M  Uc  M  [        U[(        5      (       d  M  S[+        UR,                  5      ;   d  GM  UR#                  UU R$                  S   UUS	9I Sh  vN nUc  GM.  U R'                  XrUS
9I Sh  vN nGMI     U$  N N N- N! [.         a  nUeSnAff = f7f)z
Allows users to modify/reject the incoming request to the proxy, without having to deal with parsing Request body.

Covers:
1. /chat/completions
2. /embeddings
3. /image/generation
z#Inside Proxy Logging Pre-call hook!r   Nr   GuardrailEventHooksrL   
event_typeTr   )r   cacherL   r   )r   rL   r   async_pre_call_hook)rA   r   r   r   response_taking_too_longr<   r   rG   r   r   r   "get_custom_logger_compatible_classr   litellm.types.guardrailsr   should_run_guardrailpre_callr   r   r   r   vars	__class__r   )	rV   r   rL   r   r   	_callbackr   r   es	            r@   r   r     s    . 	;<((AAtAT	
 <2	#-- 	h,, ' : : J J m m !I !)I(Z	?-S-SL "66!%2N2N 7   $$
 !%.%B%B*;"//0DE!"+	 &C &  H  +%)%H%H%-I &I &   , )"9l;;-i6I6I1JJ%.%B%B*;"//0DE!"+	 &C &  H  +%)%H%H%-I &I &  W .^ K7    
  	G	s   =F9 B5F% 5F6F% F	F% F% 5F% "F% 3F!4F% >F% F#
F% F9F% F% !F% #F% %
F6/F11F66F9)r   r   r   r   r   c                 t  #    [         R                   H  n [        U[        5      (       ap  UR                  c$  [        US5      (       a  UR                  S:X  a    gO$SSKJn  UR                  XR                  S9SLa  Mn  UR                  UUUS9I Sh  vN   M  M     U$  N! [         a  nUeSnAff = f7f)	z4
Runs the CustomGuardrail's async_moderation_hook()
Nmoderation_checkr   r   r   r   T)rL   r   r   )r<   r   rG   r   
event_hookhasattrr   r   r   r   during_callasync_moderation_hookr   )rV   rL   r   r   r   r   r   s          r@   during_call_hookProxyLogging.during_call_hook  s       ))Hh88  **2w "48 8 $44
B" C Q %99%)6U6U :  $((
 %"88!*;"+ 9   - 9 *> 
  sS   B8AB$B8#B$?B8B$B"B$B8"B$$
B5.B00B55B8error_messagefailing_modelc                    #    U R                   c  g U R                  (       a#  U R                  R                  UUS9I S h  vN   g g  N7f)N)r   r   )r   r   failed_tracking_alert)rV   r   r   s      r@   r  "ProxyLogging.failed_tracking_alertH  sQ     
 == ''..DD++ E    (s   =AA Atype)token_budgetuser_budgetteam_budgetproxy_budgetprojected_limit_exceeded	user_infoc                 p   #    U R                   c  g U R                  R                  UUS9I S h  vN   g  N7f)N)r  r
  )r   r   budget_alerts)rV   r  r
  s      r@   r  ProxyLogging.budget_alertsV  s=      == **88 9 
 	
 	
s   ,646r   level)LowMediumHigh
alert_typer   c           
        #    U R                   c  gSSKJn  UR                  " 5       R                  S5      n[        R
                  " SS5      nSU SU SU 3nUb	  US	U S
3-  n0 n	0 n
Ubk  [        US9I Sh  vN nUb  XS'   USR                  U5      -  nSU;   a9  US   R                  SS5      b#  [        US   S   [        5      (       a  US   S   n
U R                    H  nUS:X  a,  U R                  R                  " SUUUSU
S.U	D6I Sh  vN   M5  US:X  d  M=  [        R                  R                  b+  [        R                  R                  R!                  U5        M  [#        S5      e   g N Nd7f)a  
Alerting based on thresholds: - https://github.com/BerriAI/litellm/issues/1298

- Responses taking too long
- Requests are hanging
- Calls are failing
- DB Read/Writes are failing
- Proxy Close to max budget
- Key Close to max budget

Parameters:
    level: str - Low|Medium|High - if calls might fail (Medium) or are failing (High); Currently, no alerts would be 'Low'.
    message: str - what is the alert about
Nr   )r   z%H:%M:%SPROXY_BASE_URLzLevel: `z`
Timestamp: `z`

Message: z

Proxy URL: ``r   u   🪢 Langfuse Traceu   

🪢 Langfuse Trace: {}rD   alerting_metadatar   )r   r  r  r
  r  sentryz#Missing SENTRY_DSN from environmentr^   )r   r   nowstrftimeosgetenvr!   r:   r   rG   rH   r   
send_alertr<   utilssentry_sdk_instancecapture_messager   )rV   r   r  r  r   r   current_time_proxy_base_urlformatted_messageextra_kwargsr  _urlclients                r@   alerting_handlerProxyLogging.alerting_handleri  s    * == %  ||~..z:))$4d;ug_\N.	R 	 &#3O3DA!FF#8lSSD6:23!%B%I%I$%OO!l* ,001DdKW|J78KLdSS$0$<=P$Q!mmF 22== #)"&7 #   8#==44@MM55EEFWX#$IJJ $ Ts,   A6E88E49BE8E6
E8 AE86E8durationc           	      $  #    [         R                  U R                  ;  a  g[        U[        5      (       ax  [        UR
                  [        5      (       a  UR
                  nOW[        UR
                  [        5      (       a!  [        R                  " UR
                  5      nO[        U5      nO[        U5      n[        U[        5      (       a  XTSS -  n[        R                  " U R                  SU 3S[         R                  0 S95        [        U S5      (       a2  U R                  R                  [         R"                  UUUS9I Sh  vN   [$        R&                  R(                  (       a  [$        R&                  R)                  US9  gg NB7f)	zE
Log failed db read/writes

Currently only logs exceptions to sentry
N  zDB read/write call failed: r  r   r  r  r   r   )servicer(  r   r   )r   )r$   db_exceptionsr   rG   r   r   r   rH   jsondumpsr   r   r&  r   r   async_service_failure_hookr   DBr<   r  capture_exception)rV   original_exceptionr(  r   traceback_strr   s         r@   failure_handlerProxyLogging.failure_handler  sS     ""$*:*::(-88,33S99 2 9 9.55t<< $

+=+D+D E #$6 7 23MmS))5D11M!!5m_E$22	 " 	
 4.//**EE$!##	 F    ==**MM++2D+E +s   E	FFAFr3  
error_typeroutec           	      $  #    U R                  UR                  SS5      SS9I Sh  vN   [        R                  U R                  ;   am  [        U[        5      (       dX   [        USS5      n[        U5      nUb  Xv-  n[        R                  " U R                  SU S3S	[        R                  US
95        U R                  X$S9(       a  U R                  UUUUS9I Sh  vN   [        R                   H|  n Sn	[        U[        5      (       a*  [        R                   R"                  R%                  U5      n	OUn	U	b2  [        U	[&        5      (       a  U	R)                  UUUS9I Sh  vN   Mz  M|  M~     g GNO N N! [*         a  n
U
eSn
A
ff = f7f)z
Allows users to raise custom exceptions/log when a call fails, without having to deal with parsing Request body.

Covers:
1. /chat/completions
2. /embeddings
3. /image/generation
r   r   r   )r   r   Nlitellm_debug_infozLLM API call failed: `r  r  r+  )r3  r7  )r   r   r8  r3  )r   r   r3  )r   r   r$   llm_exceptionsr   rG   r   getattrr   r   r   r&  _is_proxy_only_error _handle_logging_proxy_only_errorr<   r   r   r   r   r   async_post_call_failure_hookr   )rV   r   r3  r   r7  r8  r:  exception_strr   r   r   s              r@   post_call_failure_hook#ProxyLogging.post_call_failure_hook  s    $ (((,,->CF ) 
 	
 	
 ##t'7'77
A
 A

 "));=QSW!X 23M!-3%%4]O1E (77!-	 &  $$1 % 
 77)"3#5	 8     ))H48	h,, ' : : J J m m !I !)I(Z	<-P-P#@@%1*;+= A    .Q( *" 	k	
:"
  sY   $FE5B8FE8 F8A/E<'E:(E<,
F8F:E<<
FFFFc                 V    [        U[        5      =(       d    U[        R                  :H  $ )z
Return True if the error is a Proxy Only Error

Prevents double logging of LLM API exceptions

e.g should only return True for:
    - Authentication Errors from user_api_key_auth
    - HTTP HTTPException (rate limit errors)
)rG   r   r   
auth_error)rV   r3  r7  s      r@   r=  !ProxyLogging._is_proxy_only_error  s'     ,m< 
/444	
rB   c                   #    UR                  SS5      nUc  SSKn[        UR                  5       5      US'   [        R
                  " US9n[        R                  R                  " SU=(       d    S[        R                  R                  5       [        R                  " 5       S.UD6u  pXSU;  a  0 US'   US   R                  U5        UGb  0 n	0 n
[        R                  R                  5       nUR!                  5        H$  u  pX;   a  XU'   M  US	:w  d  M  US
:w  d  M   XU'   M&     UR#                  UR                  S	S5      UR                  S
S5      U	U
S9  SnSU;   aK  [%        US   [&        5      (       a3  US   nXR(                  S'   [*        R,                  R.                  Ul        OSU;   aK  [%        US   [        5      (       a3  US   nXR(                  S'   [*        R2                  R.                  Ul        OPSU;   aJ  [%        US   [&        5      (       a2  US   nXR(                  S'   [*        R4                  R.                  Ul        UR7                  USS9  UR9                  U[:        R<                  " 5       S9I Sh  vN   [>        R@                  " URB                  U[:        R<                  " 5       4S9RE                  5         gg NH7f)z
Handle logging for proxy only errors by calling `litellm_logging_obj.async_failure_handler`

Is triggered when self._is_proxy_only_error() returns True
litellm_logging_objNr   r   )r   IGNORE_THIS)original_function	rules_obj
start_timerD   r   userr   )r   rL  optional_paramslitellm_paramsmessagespromptinput)rQ  api_key)	exceptiontraceback_exception)targetargsr^   )#r   uuidr   uuid4r1   'get_sanitized_user_information_from_keyr<   r  function_setupRulesr   r  updater5   __annotations__rn   itemsupdate_environment_variablesrG   r   model_call_detailsr4   acompletionrd   r   atext_completion
aembeddingr   async_failure_handlerr8   r;   	threadingThreadr5  start)rV   r   r   r8  r3  rG  rW  user_api_key_logged_metadatarL   _optional_params_litellm_paramslitellm_param_keyskvrQ  s                  r@   r>  -ProxyLogging._handle_logging_proxy_only_error/  s     2>1A1A!42
 &.1$**,.?L*+(PP&7 ) )0(D(D )"'"8=!----/#<<>) 	)% -+-Z($++,HI*! O!4!D!D!I!I!K$**,*)*A&'\a6k*+Q'	 -  <<"&&w3!%%fb1 0.	 =  -/E\)jZ($/ / %Z0EJ66zB090E0E0K0K#-\)jh9OQT.U.U$X.CH66x@090J0J0P0P#-L(ZW8Mt-T-T$W-BG66w?090D0D0J0J#-(( )  &;;,$-$8$8$: <   
 *::&((* egg +Ps    DKKE$KKA	Kr   c                   #    [         R                   H  n Sn[        U[        5      (       a*  [         R                  R
                  R                  U5      nOUnUb  [        U[        5      (       a?  SSKJ	n  UR                  XR                  S9SLa  M  UR                  UUUS9I Sh  vN   M  [        U[        5      (       a  UR                  UUUS9I Sh  vN   M  M  M     U$  N> N! [         a  nUeSnAff = f7f)zB
Allow user to modify outgoing data

Covers:
1. /chat/completions
Nr   r   r   T)r   rL   r   )r<   r   rG   r   r   r   r   r   r   r   r   	post_callasync_post_call_success_hookr   r   )rV   rL   r   r   r   r   r   r   s           r@   post_call_success_hook#ProxyLogging.post_call_success_hook  s(      ))H'48	h,, ' : : J J m m !I !)I( "(O<<P %99%)6S6S :  $((
 %&CC.?!%%- D    $I|<<'DD.?!%%- E    =/ ) *R !
  se   DA=C-DC-*C)+C-/D1)C-C+C-
D)C-+C--
C>7C99C>>Dc                   #    Sn[        U[        5      (       a  [        R                  " US9nUb  [        R                   Hz  n Sn[        U[
        5      (       a*  [        R                  R                  R                  U5      nOUnUb0  [        U[        5      (       a  UR                  X#S9I Sh  vN   Mx  Mz  M|     U$  N! [         a  nUeSnAff = f7f)zY
Allow user to modify outgoing streaming data -> per chunk

Covers:
1. /chat/completions
N)response_objr   r   )rG   r   r<   get_response_stringr   r   r   r   r   r   async_post_call_streaming_hookr   )rV   r   r   response_strr   r   r   s          r@   rx  +ProxyLogging.async_post_call_streaming_hook  s      '+h.."66HML##--8<I!(C00$+$>$>$N$N$q$q$%	 %-	 ,I|1T1T'FF.? G    2U, .  ! Gs=   ACA-C2C3C7
CC
CCCCc                    #    [         R                  " U5      n[        R                   H2  n [	        U[
        5      (       a  UR                  X#S9I Sh  vN   M2  M4     U$  N! [         a  nUeSnAff = f7f)z
- Check outgoing streaming response uptil that point
- Run through moderation check
- Reject request if it fails moderation check
rv  N)rJ   rK   r<   r   rG   r   rx  r   )rV   r   r   new_responser   r   s         r@   post_call_streaming_hook%ProxyLogging.post_call_streaming_hook  s      }}X.))Hh55"AA*; B    6 *   s:   *A7'A#A!A#A7!A##
A4-A//A44A7)r   r   r   r   r   r   r   r   r   r   r   r   r{   )NNNNNNrT   )r   )NN),r|   r}   r~   r   __doc__r   r   rW   r   r   r   r   r	   r   r$   rH   r   r   r   r
   r   r   r   r)   r   r   r  r%   r  r&  r5  r   r   rA  r=  r>  r   r   r   r   rr  rx  r}  r   r^   rB   r@   r   r      s    #4%4 48V$ $J/< $(.2,015(,/3*K4.*K %UO*K j)	*K
 d9o.*K  ~*K 'tn*KX)(62B )V
"
,34E,F
,$ )  	
	 
 " )  	
	 
 "R)R tnR 	
	R 
$Rh.. *. #
	.` 
(

 
0 (,?K?K ./?K 	?K
 tn?KD RT(F,1(F>A(F^ 15#GG &G *	G
 _-G }GX 15
%
 _-
 
	
,  $26VV *V }	V
 %Y/Vp66 '8-GH6 *	6p'8-GH *@ *rB   r   c                 &    [        SU S    35        g )Nz!Backing off... this was attempt #tries)rA   )detailss    r@   
on_backoffr    s    5gg6F5GHIrB   c                       \ rS rSr% 0 r\\S'   0 r\\S'   0 r\\S'   0 r	\\S'   0 r
\\S'   0 r\\S'   / r\\S'    S?S
\S\S\\   4S jjrS\4S jrS\S\4S jr\R,                  " \R.                  \SS\S9S 5       r\\R,                  " \R.                  \SS\S9S\S\S\S   4S j5       5       r\R,                  " \R.                  \SS\S9\              S@S\\\\4      S\\   S\\   S \\   S!\\   S"\\   S\\S#      S$\S%   S&\\    S'\\    S(\\!   S)\\!   S*\\"   S\\   4S+ jj5       5       r#S,\4S- jr$\R,                  " \R.                  \SS\S9S\S\S.   4S/ j5       r%\R,                  " \R.                  \SS\S9S	0 S	S	S	S0S	S	S	4	S\\   S\S1\\   S\\   S \\   S$\S2   S\\S3      S4\\   S5\\   4S6 jj5       r&\R,                  " \R.                  \SS\S9    SAS7\\   S!\\   S\\S3      S\\   4S8 jj5       r'\R,                  " \R.                  \SS\S9S9 5       r(\R,                  " \R.                  \SS\S9S: 5       r)S; r*S\!4S< jr+SBS= jr,S>r-g	)CPrismaClienti  user_list_transactonsend_user_list_transactonskey_list_transactonsteam_list_transactonsteam_member_list_transactonsorg_list_transactonsspend_log_transactionsNdatabase_urlproxy_logging_objhttp_clientc                    X l         [        [        R                  " S5      5      U l        [
        R                  " S5         SSKJn  Ub-  [        U" US9U R                  b  U R                  OSS9U l        O-[        U" 5       U R                  b  U R                  OSS9U l        [
        R                  " S	5        g ! [         a    [        S5      ef = f)
NIAM_TOKEN_DB_AUTHzCreating Prisma Client..r   )PrismazUnable to find Prisma binaries.)httpF)original_prismaiam_token_db_authzSuccess - Created Prisma Client)r  r2   r  r  r  r   r9   prismar  r   r-   db)rV   r  r  r  r  s        r@   rW   PrismaClient.__init__  s     "31<II)*2
 	""#=>	?% "# &K 8 --9 **DG $ & --9 **DG 	""#DE)  	?=>>	?s   B< <Ctokenc                 j    [         R                  " UR                  5       5      R                  5       nU$ rT   hashlibsha256encode	hexdigest)rV   r  hashed_tokens      r@   
hash_tokenPrismaClient.hash_token*  s%    ~~elln5??ArB   rL   rZ   c                     [         R                  " U5      nUR                  5        H5  u  p4[        U[        5      (       d  M   [
        R                  " U5      X#'   M7     U$ ! [         a    SX#'    ML  f = f)Nzfailed-to-serialize-json)rJ   rK   r^  rG   rH   r.  r/  r   )rV   rL   db_datarl  rm  s        r@   jsonify_objectPrismaClient.jsonify_object0  sb    --%MMODA!T""<!%AGJ $  ! <!;GJ<s   A""A43A4   
   )	max_triesmax_timer  c                 f  #     / SQnSnSR                  S U 5       5      n[        R                  " SS5      nU R                  R	                  SU SU S	35      I S
h  vN n[        U5      nUS   S   U:X  a  [        R                  " S5        g
US   S   (       a]  X%S   S   ;  aR  U R                  5       I S
h  vN   U R                  R                  S5      I S
h  vN   [        R                  " S5        g
[        U R                  S9I S
h  vN nU(       a  [        U R                  S9I S
h  vN   g
US   S   (       a  [        US   S   5      O	[        5       n[        U5      n	X-
  n
[        R                  " SR                  U
5      5         g
 GN9 N N N Nl! [         a    e f = f7f)aT  
Checks if the LiteLLM_VerificationTokenView and MonthlyGlobalSpend exists in the user's db.

LiteLLM_VerificationTokenView: This view is used for getting the token + team data in user_api_key_auth

MonthlyGlobalSpend: This view is used for the admin view to see global spend for this month

If the view doesn't exist, one will be created.
)r&   MonthlyGlobalSpendLast30dKeysBySpendLast30dModelsBySpendMonthlyGlobalSpendPerKeyMonthlyGlobalSpendPerUserPerKeyLast30dTopEndUsersSpendDailyTagSpendr&   z, c              3   .   #    U  H  nS U S 3v   M     g7f)'Nr^   ).0views     r@   	<genexpr>1PrismaClient.check_view_exists.<locals>.<genexpr>]  s     *R>4QtfA;>s   DATABASE_SCHEMApublicz
                WITH existing_views AS (
                    SELECT viewname
                    FROM pg_views
                    WHERE schemaname = 'z,' AND viewname IN (
                        z
                    )
                )
                SELECT
                    (SELECT COUNT(*) FROM existing_views) AS view_count,
                    ARRAY_AGG(viewname) AS view_names
                FROM existing_views
                Nr   
view_countzAll necessary views exist!
view_namesa"  
                            CREATE VIEW "LiteLLM_VerificationTokenView" AS
                            SELECT
                            v.*,
                            t.spend AS team_spend,
                            t.max_budget AS team_max_budget,
                            t.tpm_limit AS team_tpm_limit,
                            t.rpm_limit AS team_rpm_limit
                            FROM "LiteLLM_VerificationToken" v
                            LEFT JOIN "LiteLLM_TeamTable" t ON v.team_id = t.team_id;
                        z,LiteLLM_VerificationTokenView Created in DB!)r  z

[93mNot all views exist in db, needed for UI 'Usage' tab. Missing={}.
Run 'create_views.py' from https://github.com/BerriAI/litellm/tree/main/db_scripts to create missing views.[0m
)joinr  r  r  	query_rawr   r   infohealth_checkexecute_rawr+   r*   r   warningr:   r   )rV   expected_viewsrequired_viewexpected_views_str	pg_schemaretexpected_total_viewsshould_create_viewsret_view_names_setexpected_views_setmissing_viewss              r@   check_view_existsPrismaClient.check_view_exists<  s    *K		N <M!%*R>*R!R		"3X>I))) *3 4+, - C $'~#6 1vl#';;$))*FG q6,'MQAU,U++---''--
   )--F2 	+ 1Ltww0W*W'*2dgg>>>& 	 :=Q9MCA| 45SVSX + .1-@*(:(O,44 b  i  i - 	}, .$ +X>"  		s   F1AF" F1F" F1+F" <F="F" F F" :F1;F" F!F" 3F 4F" 8F19AF" F1F" F" F" F"  F" "F..F1r      r\   rd   
table_name)usersrn   configspendc           
        #    [         R                  " SU SU 35        [        R                  " 5       n US:X  a.  U R                  R                  R                  X0S9I Sh  vN nU$ US:X  a.  U R                  R                  R                  X0S9I Sh  vN nU$ US:X  a.  U R                  R                  R                  X0S9I Sh  vN nU$ US:X  a,  U R                  R                  R                  X0S9I Sh  vN nW$  N Np N> N! [         a  nS	SK
nS
[        U5       3n[         R                  " U5        USR                  [        U5      5      -   nUS-   UR                  " 5       -   n	[        R                  " 5       n
X-
  n[         R"                  " U R$                  R'                  UUU	SS95        UeSnAff = f7f)z$
Generic implementation of get data
z PrismaClient: get_generic_data: z, table_name: r  whereNrn   r  r  r   z2LiteLLM Prisma Client Exception get_generic_data: z
Exception Type: {}
get_generic_data)r3  r(  r4  r   )r   r9   timer  litellm_usertable
find_firstlitellm_verificationtokenlitellm_configlr   r8   r   r   r:   r  r;   r   r   r  r5  )rV   r\   rd   r  rK  r   r   r8   	error_msgerror_tracebackend_time	_durations               r@   r  PrismaClient.get_generic_data  s    " 	"".se>*N	
 YY[
$	W$!%!:!:!E!E, "F "  O v%!%!B!B!M!M, "N "  O x'!%!7!7!B!B, "C "  O	 w&!%!5!5, "6 "  O  	LSQRVHUI &&y1!$:$A$A$q'$JJI'$.1E1E1GGOyy{H -I&&66'(&"10	 7  G%	s   2G-D "D#D (G)-D DD G-D 
D	D G-D >D?D GD D 	D D 
GB'F>>GGuser_iduser_id_listteam_idteam_id_listkey_val)rL  r\   r  r  teamuser_notificationcombined_view
query_type)find_uniquefind_allexpiresreset_atoffsetlimitr]   c           
      T  #    [        5       n[        R                  " 5       nS n S nUb  Ub  UGb  US:X  Ga  Ub7  [        U[        5      (       a"  [	        US9n[
        R                  " SU 35        US:X  a  Ub  Uc  [        SSSU 30S9eU R                  R                  R                  S	U0S
S0S9I S h  vN nUbM  UR                  b>  [        UR                  [        5      (       a  UR                  R                  5       Ul        GO[        [        R                  SU 3S9eUS:X  a  Ub  U R                  R                  R!                  SU0S
S0S9I S h  vN nUbX  [#        U5      S:  aI  U HC  n[        UR                  [        5      (       d  M$  UR                  R                  5       Ul        ME     GO'US:X  a  Ub  U R                  R                  R!                  SU0S
S0S9I S h  vN nUbX  [#        U5      S:  aI  U HC  n[        UR                  [        5      (       d  M$  UR                  R                  5       Ul        ME     GOUS:X  a  U	b  U
b  U R                  R                  R!                  SS 0SSU	00/SU
0S.S9I S h  vN nUbX  [#        U5      S:  aI  U HC  n[        UR                  [        5      (       d  M$  UR                  R                  5       Ul        ME     OUS:X  a  0 nUb  0 US	'   [        U[        5      (       a  [	        US9nU/US	   S'   O[        U[$        5      (       as  / nU Hc  n[        U[        5      (       d   eUR'                  S5      (       a"  U R)                  US9nUR+                  U5        MR  UR+                  U5        Me     UUS	   S'   U R                  R                  R!                  SS0US
S0S9I S h  vN nUb  U$ [        [        R                  SS9eUb  Ub  UGbV  US:X  GaO  US:X  a4  Uc  SU0nU R                  R,                  R                  US9I S h  vN nU$ US:X  a0  Ub-  U R                  R,                  R!                  US9I S h  vN nU$ US:X  a4  U
b1  U R                  R,                  R!                  SSU
00S9I S h  vN nU$ US:X  a4  Ub1  U R                  R,                  R!                  SSU00S9I S h  vN nU$ US:X  ac  U	b:  U R                  R,                  R!                  SS0SSS 0SSU	00/0S 9I S h  vN nU$ S!nU R                  R/                  UX5      I S h  vN nU$ US:X  a  [
        R                  " S"5        Ubv  US:X  a5  U R                  R0                  R                  US   US#   0S9I S h  vN nU$ US:X  a3  U R                  R0                  R!                  US   US#   0S9I S h  vN nU$ U R                  R0                  R!                  S$S0S%9I S h  vN nU$ US&:X  Ga  US:X  a2  U R                  R2                  R                  SU0S'S0S9I S h  vN nU$ US:X  a4  U
b1  U R                  R2                  R!                  SSU
00S9I S h  vN nU$ US:X  a7  Ub4  U R                  R2                  R!                  S(S)U00S
S0S9I S h  vN nU$ US:X  a4  Ub1  U R                  R2                  R!                  SSU00S9I S h  vN nU$ US:X  a.  Uc+  U R                  R2                  R!                  S*S+9I S h  vN nU$ US,:X  ai  US:X  a/  U R                  R4                  R                  SU0S9I S h  vN nU$ US:X  a,  U R                  R4                  R!                  5       I S h  vN nU$ US-:X  Gav  Ub7  [        U[        5      (       a"  [	        US9n[
        R                  " SU 35        US:X  Ga4  Uc  [        SSSU 30S9eS.U S/3n[7        S0R9                  U5      5        U R                  R;                  US19I S h  vN nUb  US2   c  / US2'   US3   c  S4US3'   S nUS5   bL  US   bF   US5    H<  nUR=                  S5      c  M  US   UR=                  S5      :X  d  M1  [?        S<0 UD6nM>     UUS6'   [A        S<0 UDS7[        R                  " 5       0D6nUR                  b>  [        UR                  [        5      (       a  UR                  R                  5       Ul        U$ g g  GN GN GNM GN GNe GN GN GN GNa GN! GN GN GNm GNA GN GN GN GN] GN* GN GN GN'! [B         a  nSS K"nS8U 3nU[        U5      -   n[7        U5        US9-   URF                  " 5       -   n[
        R                  " U5        [        R                  " 5       n U U-
  n![H        RJ                  " U RL                  RO                  UU!S:US;95        UeS nAff = f7f)=Nr\   r  z%PrismaClient: find_unique for token: r  r   r   zNo token passed in. Token=r   r  litellm_budget_tableT)r  includezQAuthentication Error: invalid user key - user key does not exist in db. User Key=r  r  r   r  r  gtlt)ORbudget_reset_atr  insk-r  desc)orderr  r  z=Authentication Error: invalid user key - token does not existrL  r  r  )r  r  a  
                        SELECT
                            u.*,
                            json_agg(v.key_alias) AS key_aliases
                        FROM
                            "LiteLLM_UserTable" u
                        LEFT JOIN "LiteLLM_VerificationToken" v ON u.user_id = v.user_id
                        GROUP BY
                            u.user_id
                        ORDER BY u.spend DESC
                        LIMIT $1
                        OFFSET $2
                        z-PrismaClient: get_data: table_name == 'spend'rd   	startTime)r  r  litellm_model_tablemembershas   )taker  r  a  
                    SELECT 
                    v.*,
                    t.spend AS team_spend, 
                    t.max_budget AS team_max_budget, 
                    t.tpm_limit AS team_tpm_limit,
                    t.rpm_limit AS team_rpm_limit,
                    t.models AS team_models,
                    t.metadata AS team_metadata,
                    t.blocked AS team_blocked,
                    t.team_alias AS team_alias,
                    t.metadata AS team_metadata,
                    t.members_with_roles AS team_members_with_roles,
                    tm.spend AS team_member_spend,
                    m.aliases as team_model_aliases
                    FROM "LiteLLM_VerificationToken" AS v
                    LEFT JOIN "LiteLLM_TeamTable" AS t ON v.team_id = t.team_id
                    LEFT JOIN "LiteLLM_TeamMembership" AS tm ON v.team_id = tm.team_id AND tm.user_id = v.user_id
                    LEFT JOIN "LiteLLM_ModelTable" m ON t.model_id = m.id
                    WHERE v.token = 'z'
                    zsql_query being made={}queryteam_modelsteam_blockedFteam_members_with_rolesteam_memberlast_refreshed_atzHLiteLLM Prisma Client Exception: Error with `get_data`. Args passed in: r  get_datar3  r(  r   r4  r^   )(localsr  rG   r   _hash_token_if_neededr   r9   r   r  r  r  r  r   	isoformatr   HTTP_401_UNAUTHORIZED	find_manyr   r   
startswithr  r   r  r  litellm_spendlogslitellm_teamtablelitellm_usernotificationsrA   r:   query_firstr   r'   r&   r   r8   r;   r   r   r  r5  )"rV   r  r  r  r  r  r  r  r  r  r  r  r  r]   r  args_passed_inrK  r  r   rwhere_filterhashed_tokenst	new_token	sql_queryr
  tmr   r8   prisma_query_infor  r  r  r  s"                                     r@   r  PrismaClient.get_data  s    J  YY[
&*t	 H!j&8&:+> $!%--'<5'I,22CL>R .<3K}+(+$+/I%-Q#R  &*WW%F%F%R%R&5!7 > &S &  H  +#++7J$,,h= = 08/?/?/I/I/KH, ,(.(D(D%vw|v}#~   :-'2E%)WW%F%F%P%P('2!7 > &Q &  H  +H0A!)A)!))X>>,-II,?,?,A	 "*  :-'2E%)WW%F%F%P%P('2!7 > &Q &  H  +H0A!)A)!))X>>,-II,?,?,A	 "* *,+ ,%)WW%F%F%P%P "+D 1!*T7O <# 15h/? &Q &  H  +H0A!)A)!))X>>,-II,?,?,A	 "*  :-)+L(02W-%eS11$9$FE;@'L1$7't44,.M%*'1!S'9'9 9'9#$<<#6#604a0HI$1$8$8$C$1$8$8$; &+ ;HL1$7%)WW%F%F%P%P&/*!7 > &Q &  H
 '#O ($*$@$@^  %**<&:+?.#,g"6%)WW%>%>%J%J% &K &  HX  S  :-'2E%)WW%>%>%H%H% &I &  HP  K  :-(2F%)WW%>%>%H%H-h/? &I &  HH  ?  :-,2J%)WW%>%>%H%H(4*>? &I &  H<  7  :-*)-)B)B)L)L#*F"3 $%.$5%.w$@'"# *M * $2  %	 *.):):9e)T#Tw&$**C &!]2)-)B)B)N)N '0@# *O * $ $O $z1)-)B)B)L)L '0@# *M * $
 $O%)WW%>%>%H%H*F3 &I &  H $Ov%.%)WW%>%>%J%J('2!6 = &K &  H.  '  :-(2F%)WW%>%>%H%H-h/? &I &  H$    :-'2E%)WW%>%>%H%H%w'7 "8 >	 &I &  H    :-,2J%)WW%>%>%H%H(4*>? &I &  H
    :-,2F%)WW%>%>%H%Hb%H%QQH22.%)WW%F%F%R%R('2 &S &  H
    :-%)WW%F%F%P%P%RRH.$!%--'<5'I,22CL>R .}+(+$+/I%-Q#R 
%&& ',W -'!I, "";"B"B9"MN%)WW%8%8y%8%IIH+#M2:68H]3#N3;7<H^48<$%>?K ( 3 ?  '//H&I#%66)#4#@X$-F"%'VVI%6F7 39,2,K	 'J
 3>/#@ $&$:>))+$ $++7J$,,h= = 08/?/?/I/I/KH,#OQ / /} "   < &    
$0 $U$$  
     R   SP  JV  	"jkyjz {)CF2I)$'$.1E1E1GGO &&7yy{H :-I&&66'(&("1	 7  G'	s  "h(Be; 8d99B#e; d<8e; Ae; 2d?38e; /A$e; e8e; De;  e!e; )h(*Ae; ee; h(/e; <e=e; h(3e; 6e7e; <h(=3e; 0e1e; 6h(7<e; 3e4e; 9h(:!e; ee; !h("Ae; 5e6e; ;h(<4e; 0e1e; 6h(7(e; e  e; %h(&8e; e#e; $h(%3e; e&e; h(6e; e)e; h(3e; e,e; h(/e; e/e; h(4e;  e2e; h(-e; 4e55e; :h(;Be; e8Ae; e; 4Be; 6h(9e; <e; ?e; e; e; e; e; e; e; e; e; e; e;  e; #e; &e; )e; ,e; /e; 2e; 5e; 8e; ;
h%Bh  h%%h(r  c                     U R                  US9nUR                  SS 5      b4  [        US   [        5      (       a  [        R
                  " US   5      US'   U$ )NrL   members_with_roles)r  r   rG   r   r.  r/  )rV   r  s     r@   jsonify_team_object PrismaClient.jsonify_team_object8  sa    %%7%3;;+T2>:()4D
 D
 -1JJw?S7T,UG()rB   )rL  r\   r  r  r  r  c           
        #    [         R                   " 5       n [        R                  " SU5        US:X  a}  US   nU R                  US9nU R	                  US9nXVS'   [        S5        U R                  R                  R                  SU00 UE0 S.S9I S	h  vN n[        R                  " S
5        U$ US:X  a^  U R	                  US9n U R                  R                  R                  SUS   00 UE0 S.S9I S	h  vN n[        R                  " S5        U$ US:X  a  U R	                  US9nUR                  SS	5      b4  [        US   [         5      (       a  ["        R$                  " US   5      US'   U R                  R&                  R                  SUS   00 UE0 S.S9I S	h  vN n
[        R                  " S5        U
$ US:X  a   / nUR)                  5        H[  u  pUn["        R$                  " U5      nU R                  R*                  R                  SU0XS.SU0S.S9nUR-                  U5        M]     [.        R0                  " U6 I S	h  vN   [        R                  " S5        g	US:X  a]  U R	                  US9nU R                  R2                  R                  SUS   00 UE0 S.S9I S	h  vN n[        R                  " S 5        U$ US!:X  a]  U R	                  US9nU R                  R4                  R                  SUS   00 UE0 S.S9I S	h  vN n[        R                  " S"5        U$ g	 GN GN;! [         a)  n	S[        U	5      ;   a  [        SSSUS    S30S9eU	eS	n	A	ff = f GN GN" N Na! [         a  n	S#S	KnS$[        U	5       3n[        U5        US%-   UR8                  " 5       -   n[         R                   " 5       nUU-
  n[.        R:                  " U R<                  R?                  U	US&US'95        U	eS	n	A	ff = f7f)(z>
Add a key to the database. If it already exists, do nothing.
zPrismaClient: insert_data: %sr\   r  r  r#  z:PrismaClient: Before upsert into litellm_verificationtokencreater\  r  rL   NzData Inserted into Keys TablerL  r  z\Foreign key constraint failed on the field: `LiteLLM_UserTable_organization_id_fkey (index)`r   r   z/Foreign Key Constraint failed. Organization ID=organization_idzM does not exist in LiteLLM_OrganizationTable. Create via `/organization/new`.r   zData Inserted into User Tabler  r$  r  zData Inserted into Team Tabler  
param_name)r,  param_valuer-  zData Inserted into Config Tabler  
request_idzData Inserted into Spend Tabler  z&Data Inserted into Model Request Tabler   z0LiteLLM Prisma Client Exception in insert_data: r  insert_datar  ) r  r   r9   r  r  rA   r  r  upsertr  r  r   r   r   r   rG   r   r.  r/  r  r^  r  r   r   gatherr  r  r8   r;   r   r  r5  )rV   rL   r  rK  r  r  r  new_verification_tokennew_user_rowr   new_team_rowtasksrl  rm  updated_dataupdated_table_rownew_spend_rownew_user_notification_rowr8   r  r  r  r  s                          r@   r/  PrismaClient.insert_dataA  s    " YY[
	 &&'FMU"W#U;--4-8#/ P 04ww/P/P/W/W #.W+"$	 0X 0 *& %))*IJ--v%--4-8)-)B)B)I)I($y/:&1k&( *J * $L& %))*IJ##v%--4-8;;3T:F:014L L 59JJ 455G01 &*WW%>%>%E%E$d9o6"-W+"$ &F &   %))*IJ##x'  JJLDA#$L#'::l#;L(,(>(>(E(E+Q/56&T'4l&C )F )% LL!23 ) nne,,,$))*KLw&--4-8&*gg&?&?&F&F'l);<"-W+"$ 'G ' ! %))*JK$$22--4-8'';;BB+T,-?@&1k&( C   * %))*RS00 3o*$ ! vq6" ,(+ '+Z[bct[uZv  wD  *E$  G, > -!  	J3q6(SI)$'$.1E1E1GGOyy{H :-I&&66'(&+"1	 7  G!	s   P
A=M8 L2M8 2P
3M8 	1L8 :L5;L8 ?M8 P
BM8 $M.%M8  P
BM8 M1M8 *P
+AM8 1M42M8 P
AM8 M6M8 0P
2M8 5L8 8
M+$M&&M++M8 1M8 4M8 6M8 8
PB PPP
r\  	data_list)r\  update_many)rL  r\   r  r  r  update_key_valuesupdate_key_values_custom_queryc
           
        #    [         R                  " SU 35        [        R                  " 5       n
 U R                  US9nUb  U R                  US9nUb  [	        SU 35        [        US9nXS'   U R                  R                  R                  SU00 UES9I Sh  vN n[         R                  " SS	U 3-   S
-   5        0 nUb   UR                  5       nXS.$ Uc  Ubx  US:X  ar  US:X  al   Uc  US   nUc  U	b  U	nOUnU R                  R                  R                  SU00 UE0 UES.S9I Sh  vN n[         R                  " SSU 3-   S
-   5        XNS.$ Uc  Ub  US:X  a  US:X  a   Uc  US   nUc  UnSU;  a  Ub  X[S'   SU;   a4  [        US   [         5      (       a  ["        R$                  " US   5      US'   SU;   a4  [        US   [         5      (       a  ["        R$                  " US   5      US'   U R                  R&                  R                  SU00 UE0 UES.S9I Sh  vN n[         R                  " SSU 3-   S
-   5        X_S.$ Ub  US:X  a  US:X  a  Ub  [        U[         5      (       a   U R                  R)                  5       n[+        U5       H  u  nnUR,                  R/                  S5      (       a  U R1                  UR,                  S9Ul         U R                  UR                  SS9S9nUR                  R                  SUR,                  00 UES9  M     UR3                  5       I Sh  vN   [	        S5        gUb  US:X  a  US:X  a  Ub  [        U[         5      (       a   U R                  R)                  5       n[+        U5       HP  u  nn U R                  UR                  SS9S9nUR                  R                  SUR4                  00 UE0 UES.S9  MR     UR3                  5       I Sh  vN   [         R                  " S5        gUb  US:X  a  US:X  a  Ub  [        U[         5      (       a  U R                  R)                  5       n[+        U5       HP  u  nn U R                  UR                  SS9S9nUR&                  R                  SUR6                  00 UE0 UES.S9  MR     UR3                  5       I Sh  vN   [         R                  " S5        gggggg GNW! [         a    UR                  5       n GN=f = f GN GN! [         a     U R                  UR                  SS9S9n GNGf = f GN! [         a!    U R                  UR                  5       S9n GNf = f GNx! [         a     U R                  UR                  SS9S9n GNf = f N! [         a  nSSKnS [;        U5       3n[	        U5        US!-   UR<                  " 5       -   n[        R                  " 5       nUU
-
  n[>        R@                  " U RB                  RE                  UUS"US#95        UeSnAff = f7f)$z
Update existing data
z'PrismaClient: update_data, table_name: r#  Nztoken: r  r  r*  z[91mz DB Token Table update succeeded z[0m)r  rL   rL  r\  r  r(  z!DB User Table - update succeeded )r  rL   r  r  r$  z!DB Team Table - update succeeded )r  rL   r\   r<  r  T)exclude_nonez([91mDB Token Table update succeeded[0mz-[91mDB User Table Batch update succeeded[0mz-[91mDB Team Table Batch update succeeded[0mr   z/LiteLLM Prisma Client Exception - update_data: r  update_datar  )#r   r9   r  r  rA   r  r  r  r\  
model_dumpr   rH   r  r0  r  rG   r   r.  r/  r  batch_	enumerater  r  r  commitr  r  r8   r   r;   r   r   r  r5  )rV   r  rL   r;  r  r  r  r  r=  r>  rK  r  r   _dataupdate_user_rowupdate_team_rowbatcheridxr  	data_jsonrL  r  r   r8   r  r  r  r  s                               r@   rA  PrismaClient.update_data  sT    , 	""5j\B	
 YY[
L	))t)4G ,$($7$7=N$7$O! w/0-E:#( !%!B!B!I!I"E*$G "J "  %**8
CD 
 !'0 ( 3 3 5 "'66#*zV/C(* ?%i0G$,5A,J),3)(,(A(A(H(H$g."-W+#/# )I ) # %))9/9JKL 
 $+DD#*zV/C(* ?%i0G$,(/%G+0C)0I&'72z0148 8 59JJ 455G01 (+<<%&:;TB B ?Cjj)*>??%&:; )-(A(A(H(H$g."-W+#/# )I ) # %))9/9JKL 
 $+DD&%'-/)y$// ''..*'	2FCww))%00"&///"@X$($7$7!"4!@ %8 %	
 55<<&0*	] =  3 nn&&&N &&(-/)y$// ''..*!*9!5ICJ$($7$7!%d!C %8 %	
 --44($,,7&3m'"+' 5  "6  nn&&&$))S &&(-/)y$// ''..*!*9!5IC$($7$7!%d!C %8 %	 --44($,,7&3m'"+' 5  "6$ nn&&&$))S/ 0 * 0 ) 'i % 0 (0$#R#D % X$($7$7QVVQUV=V$7$W	X '( % J$($7$7TYY[$7$I	J '$ % $($7$7!%!= %8 %	 '
  	I#a&RI)$'$.1E1E1GGOyy{H :-I&&66'(&+"1	 7  G!	sQ  /X?A*V- S3(V- S6 V- X?AV- 0T1&V- X?CV- )T*&V- X?BV- #T??V- >U
?V- X?AV- #U?AV- U;V- X?AV- 2U>AV- V+V- -X?3V- 6TV- TV- V- &UV- UV- 'U84V- 7U88V- >&V($V- 'V((V- -
X<7B X77X<<X?tokensc           
      F  #    [         R                   " 5       n Ub  [        U[        5      (       a  / nU HQ  n[        U[        5      (       a&  UR	                  S5      (       a  U R                  US9nOUnUR                  U5        MS     0 n	Ub  SSSU00SU0/0n	OSSU00n	U R                  R                  R                  U	S9I Sh  vN n
[        R                  " S	U
5        S
U
0$ US:X  aK  UbH  [        U[        5      (       a3  U R                  R                  R                  SSU00S9I Sh  vN   SU0$ US:X  aJ  UbF  [        U[        5      (       a0  U R                  R                  R                  SSU00S9I Sh  vN   gggg N N[ N! [         a  nSSKnS[        U5       3n[        U5        US-   UR                   " 5       -   n[         R                   " 5       nX-
  n["        R$                  " U R&                  R)                  UUSUS95        UeSnAff = f7f)zI
Allow user to delete a key(s)

Ensure user owns that key, unless admin.
Nr  r  ANDr  r  r  r  zdeleted_tokens: %sdeleted_keysr  r  deleted_teamsr\   r   z/LiteLLM Prisma Client Exception - delete_data: r  delete_datar  )r  rG   r	   r   r  r  r   r  r  delete_manyr   r9   r  r   r8   rA   r;   r   r   r  r5  )rV   rM  r  r  r  rK  r  r  r  filter_querydeleted_tokensr   r8   r  r  r  r  s                    r@   rR  PrismaClient.delete_data  s[    & YY[
9	!j&>&> "#E!%--%2B2B52I2I'+U'C',!((6 $ &(&4*? @9gBVW$L %,dM-B#CL'+ww'H'H'T'T& (U ( " %**+?P&77f$ ,|T22 gg//;;$t\&:; <    (66e# ,|T22 gg77CC$t\&:; D    3 - $!"  	I#a&RI)$'$.1E1E1GGOyy{H -I&&66'(&+"1	 7  G!	sz   H!B/F F
	F 'H!(AF 0F1F 8H!9AF FF H!
F F F 
HA?HHH!c           
      6  #    [         R                   " 5       n [        R                  " S5        U R                  R	                  5       SL a9  [        R                  " S5        U R                  R                  5       I S h  vN   g g  N! [         a  nSS KnS[        U5       3n[        U5        US-   UR                  " 5       -   n[         R                   " 5       nXa-
  n[        R                  " U R                  R                  UUSUS95        UeS nAff = f7f)	Nz:PrismaClient: connect() called Attempting to Connect to DBFz;PrismaClient: DB not connected, Attempting to Connect to DBr   z+LiteLLM Prisma Client Exception connect(): r  connectr  )r  r   r9   r  is_connectedrX  r   r8   r   rA   r;   r   r   r  r5  rV   rK  r   r8   r  r  r  r  s           r@   rX  PrismaClient.connect  s      YY[
	 &&L ww##%.$**Q ggoo'''	 / ( 	Ec!fXNI)$'$.1E1E1GGOyy{H -I&&66'(&'"1	 7  G!	s<   DA&B ?B B DB 
DA?DDDc           
        #    [         R                   " 5       n U R                  R                  5       I S h  vN   g  N! [         a  nSS KnS[        U5       3n[        U5        US-   UR                  " 5       -   n[         R                   " 5       nXa-
  n[        R                  " U R                  R                  UUSUS95        UeS nAff = f7f)Nr   .LiteLLM Prisma Client Exception disconnect(): r  
disconnectr  )r  r  r^  r   r8   r   rA   r;   r   r   r  r5  rZ  s           r@   r^  PrismaClient.disconnect3  s      YY[
	''$$&&& 	HQQI)$'$.1E1E1GGOyy{H -I&&66'(&*"1	 7  G!	s2   C> <> C> 
CA?CCCc           
        #    [         R                   " 5       n SnU R                  R                  U5      I Sh  vN nU$  N! [         a  nSSKnS[        U5       3n[        U5        US-   UR                  " 5       -   n[         R                   " 5       nX-
  n	[        R                  " U R                  R                  UU	SUS95        UeSnAff = f7f)z-
Health check endpoint for the prisma client
zSELECT 1Nr   r]  r  r  r  )r  r  r  r   r8   r   rA   r;   r   r   r  r5  )
rV   rK  r  r   r   r8   r  r  r  r  s
             r@   r  PrismaClient.health_checkP  s      YY[
	"I "WW..y99HO : 	HQQI)$'$.1E1E1GGOyy{H -I&&66'(&,"1	 7  G!	s8   C A A A C A 
CA?CCCc                    #     SnU R                   R                  US9I S h  vN nUS   S   $  N! [         a#  n[        R                  " SU 35         S nAgS nAff = f7f)Nz
            SELECT reltuples::BIGINT
            FROM pg_class
            WHERE oid = '"LiteLLM_SpendLogs"'::regclass;
            r  r   	reltuplesz+Error getting LiteLLM_SpendLogs row count: )r  r  r   r   r   )rV   r  resultr   s       r@   _get_spend_logs_row_count&PrismaClient._get_spend_logs_row_countn  sm     	I
  77,,9,==F!9[)) > 	 &&=aSA 		s6   A!1 /1 A!1 
AAA!AA!c                 l   #    SSK Jn  U R                  5       I Sh  vN nUR                  SUS9  g N7f)z
Set the `LiteLLM_SpendLogs`row count in proxy state.

This is used later to determine if we should run expensive UI Usage queries.
r   )proxy_stateNspend_logs_row_count)variable_namerd   )litellm.proxy.proxy_serverrh  re  set_proxy_state_variable)rV   rh  _num_spend_logs_rowss      r@   (_set_spend_logs_row_count_in_proxy_state5PrismaClient._set_spend_logs_row_count_in_proxy_state}  s;      	;%)%C%C%EE,,0& 	- 	
  Fs   424)r  r  r  rT   )NNNNNNNr  NNNNNN)NNNN)rZ   N).r|   r}   r~   r   r  rH   r]  r  r  r  r  r  r  r	   r   r   r   r   rW   r  r  backoffon_exceptionexpor   r  r  r,   r
   r  r   r   r   intr6   r  r%  r/  rA  rR  rX  r^  r  re  rn  r   r^   rB   r@   r  r    s   "$4$&(t(!#$#"$4$)+ $+!#$##%D% &*	"F"F ("F c]	"FH 
4 
D 
 ZZx 11 1 >?	1 1f   -1!%'+!%'+"& 9F&*'+ $ +/487Tc4i()T #T tn	T
 #T tnT $T !

T& 56'T( (#)T* 8$+T, -T. 
/T4 #4.5T6 $L17T Tl
4  JJ I
JJZ   $$(!%!%7?RV,09=_}_ _ D>	_
 #_ #_ 34_ W%MNO_ $D>_ )1__D  "&'+RV!%FF tnF W%MNO	F
 #FFR < ,< 
rB   r  rd   config_file_pathrZ   c                    U nS n U R                  S5      nSR                  US S 5      nUS   nUb  [        R                  R	                  U5      n[        R                  R                  " U/UR                  S5      Q76 nUS-  n[
        R                  R                  X&5      nUc  [        SU 35      e[
        R                  R                  U5      nUR                  R                  U5        O[
        R                  " U5      n[        X5      n	U	$ ! [         a'  n
U(       a  U(       a  [        SU SU 35      U
eU
eS n
A
f[         a  n
U
eS n
A
ff = f)N.z.pyz*Could not find a module specification for zCould not import z from )splitr  r  pathdirname	importlibutilspec_from_file_locationImportErrormodule_from_specloaderexec_moduleimport_moduler<  r   )rd   rt  module_nameinstance_nameparts	directorymodule_file_pathspecmoduleinstancer   s              r@   get_instance_fnr    sN   KM&C  hhuSbz*b	 '(89I!ww||IO8I8I#8NO%>>99+XD|!@AQ@RS  ^^44T:FKK##F+ ,,[9F 61 [#M?&F G s$   DD 
E"EEEEr  r   r  c                 <  #    U  S3nUR                  US9nUc  UR                  U S9I Sh  vN nUbe  [        SU S[        U5       35        [	        US5      (       a:  [        [        US5      5      (       a   UR                  5       nUR                  X6SS	9  g Nm7f)
z9
Check if a user_id exists in cache,
if not retrieve it.
_user_api_key_user_id)r\   N)r  z
User Row: z	, type = model_dump_jsoniX  )r\   rd   r   )	ry   r  rA   r  r   callabler<  r  rv   )r  r   r  	cache_keyr   user_rowcache_values          r@   _cache_user_rowr    s     
 )01I9-HW55Jxj	$x.9IJKx!233"349 9 '668!#     6s   *BBA.Bc                 V  #    [         R                  " S5      n[        [         R                  " SS5      5      n[         R                  " S5      n[         R                  " S5      n[         R                  " SS5      nUc  [        S5      e[	        5       nXxS	'   XS
'   XS'   [
        R                  " SXp5        Uc  [        S5      eUc  [        S5      eUc  [        S5      eUR                  [        US5      5         [        R                  " X45       n	[         R                  " SS5      S:w  a  U	R                  5         U	R                  XV5        U	R                  U5        SSS5        g! , (       d  f       g= f! [         a!  n
[        S[!        U
5      -   5         Sn
A
gSn
A
ff = f7f)zP
smtp_host,
smtp_port,
smtp_username,
smtp_password,
sender_name,
sender_email,
	SMTP_HOST	SMTP_PORT587SMTP_USERNAMESMTP_PASSWORDSMTP_SENDER_EMAILNz4Trying to use SMTP, but SMTP_SENDER_EMAIL is not setFromToSubjectzsending email from %s to %sz,Trying to use SMTP, but SMTP_HOST is not setz0Trying to use SMTP, but SMTP_USERNAME is not setz0Trying to use SMTP, but SMTP_PASSWORD is not sethtmlSMTP_TLSTrueFalsez*An error occurred while sending the email:)r  r  rs  
ValueErrorr   r   r9   attachr   smtplibSMTPstarttlsloginsend_messager   rA   r   )receiver_emailsubjectr  	smtp_host	smtp_portsmtp_usernamesmtp_passwordsender_emailemail_messageserverr   s              r@   
send_emailr    sn     		+&IBIIk512IIIo.MIIo.M990$7LOPP "OM(&($&)%| GHHKLLKLL $/0M\\)/6yyV,7! LL6 . 0//  MBSVKLLMsU   C:F)=E; AE*!E; )F)*
E84E; 7F)8E; ;
F&F!F)!F&&F)r  c                 j    SS K nUR                  " U R                  5       5      R                  5       nU$ )Nr   r  )r  r  r  s      r@   r  r  	  s*     >>%,,.1;;=LrB   c                 D    U R                  S5      (       a	  [        U S9$ U $ )zT
Hash the token if it's a string and starts with "sk-"

Else return the token as is
r  r  )r  r  r  s    r@   r  r  	  s%     &&rB   prisma_clientc           
        #    U Gb  [         R                  " 5       nU R                  SSXS9I Sh  vN nUb\  [        U5      S:  aM  U H.  nSUl        [        UR                  S9nU[        US9-   Ul        M0     U R                  S	USS
9I Sh  vN   [         R                  " 5       nU R                  SSUS9I Sh  vN nUb\  [        U5      S:  aM  U H.  nSUl        [        UR                  S9nU[        US9-   Ul        M0     U R                  S	USS
9I Sh  vN   [         R                  " 5       nU R                  SSUS9I Sh  vN nUby  [        U5      S:  ai  / nU HG  n	[        U	R                  S9n[        U	R                  SU[        US9-   US9n
UR                  U
5        MI     U R                  S	USS
9I Sh  vN   gggg GN GNA GN N N N7f)zf
Gets all the non-expired keys for a db, which need spend to be reset

Resets their spend

Updates db
Nr\   r  )r  r  r  r  r   g        )r(  secondsr<  )r  r;  r  rL  )r  r  r  r  )r  r  r  
updated_at)r   utcnowr  r   r  r   budget_durationr   r  rA  r(   r  r   )r  r  keys_to_resetr\   
duration_susers_to_resetrL  teams_to_resetteam_reset_requestsr  reset_team_budget_requests              r@   reset_budgetr  	  s3      oo+44S 5 
 
 $]);a)?$	0#:M:MN
&)Ij,I&I# %
  ++(Me ,   
 oo,55*s  6  
 
 %#n*=*A& 
0$:N:NO
'*Yz-J'J$ '
  ++(Nv ,   
 oo,55!  6  
 
 %#n*=*A"$&0$:N:NO
,B LL$')J*G$G"	-) $**+DE '  ++(-! ,    +B%S !


"sl   .GGAGG-G=G>AGG-G
GA9GG	GGGGGGdb_writer_clientr  c                   #    SnSn[        U R                  R                  5       5      S:  a  [        US-   5       H  n[        R                  " 5       n U R
                  R                  [        SS9S9 ISh  vN nUR                  5        ISh  vN nU R                  R                  5        H&  u  nn	UR                  R                  SU0S	S
U	00S9  M(     SSS5      ISh  vN   SSS5      ISh  vN   0 U l          O   ["        R$                  " SR'                  [        U R(                  R                  5       5      5      5        [        U R(                  R                  5       5      S:  a  [        US-   5       H  n[        R                  " 5       n U R
                  R                  [        SS9S9 ISh  vN nUR                  5        ISh  vN nU R(                  R                  5        H?  u  nn	[*        R,                  b   UR.                  R1                  SU0UU	SS.S	S
U	00S.S9  MA     SSS5      ISh  vN   SSS5      ISh  vN   0 U l          O   ["        R$                  " SR'                  [        U R2                  R                  5       5      5      5        [        U R2                  R                  5       5      S:  a  [        US-   5       H  n[        R                  " 5       n U R
                  R                  [        SS9S9 ISh  vN nUR                  5        ISh  vN nU R2                  R                  5        H&  u  nn	UR4                  R                  SU0S	S
U	00S9  M(     SSS5      ISh  vN   SSS5      ISh  vN   0 U l          O   ["        R$                  " SR'                  [        U R6                  R                  5       5      5      5        [        U R6                  R                  5       5      S:  a  [        US-   5       H  n[        R                  " 5       n U R
                  R                  [        SS9S9 ISh  vN nUR                  5        ISh  vN nU R6                  R                  5        HK  u  nn	["        R$                  " SR'                  X5      5        UR8                  R                  SU0S	S
U	00S9  MM     SSS5      ISh  vN   SSS5      ISh  vN   0 U l          O   [        U R:                  R                  5       5      S:  Ga   [        US-   5       H  n[        R                  " 5       n U R
                  R                  [        SS9S9 ISh  vN nUR                  5        ISh  vN nU R:                  R                  5        HN  u  nn	UR=                  S5      S   nUR=                  S5      S   nUR>                  R                  XS.S	S
U	00S9  MP     SSS5      ISh  vN   SSS5      ISh  vN   0 U l          O   [        U R@                  R                  5       5      S:  a  [        US-   5       H  n[        R                  " 5       n U R
                  R                  [        SS9S9 ISh  vN nUR                  5        ISh  vN nU R@                  R                  5        H&  u  nn	URB                  R                  SU0S	S
U	00S9  M(     SSS5      ISh  vN   SSS5      ISh  vN   0 U l           O   ["        R$                  " SR'                  [        U RD                  5      5      5        SnSn[        U RD                  5      S:  Ga  [        US-   5       GH  n[        R                  " 5       n [F        RH                  " SS5      n[        U RD                  5      S:  a  Ub  Ub  URK                  S5      (       d  US-  n["        R$                  " SR'                  U5      5        URM                  US -   [N        RP                  " U RD                  5      S!S"0S#9I Sh  vN nURR                  S$:X  a  / U l"        OU RD                  SU n[        S[        U5      U5       H}  nUUUU-    nU Vs/ s H  nU RU                  0 UE5      PM     nnU R
                  RV                  RY                  US%S&9I Sh  vN   ["        R$                  " S'[        U5       S(35        M     U RD                  [        U5      S U l"        ["        R$                  " [        U5       S)[        U RD                  5       35          g   gg G	N	 GN GN! , ISh  vN  (       d  f       GN= f GN! , ISh  vN  (       d  f       GN= f! [         a=  n
XC:  a
  [        XUS9  [        R                  " SU-  5      I Sh  vN     Sn
A
G	M  Sn
A
f[          a  n
[        XUS9   Sn
A
G	M  Sn
A
ff = f GNn GNX GN! , ISh  vN  (       d  f       GN= f GN! , ISh  vN  (       d  f       GN= f! [         a=  n
XC:  a
  [        XUS9  [        R                  " SU-  5      I Sh  vN     Sn
A
G	M/  Sn
A
f[          a  n
[        XUS9   Sn
A
G	MM  Sn
A
ff = f GN GN GNS! , ISh  vN  (       d  f       GNi= f GNa! , ISh  vN  (       d  f       GNw= f! [         a=  n
XC:  a
  [        XUS9  [        R                  " SU-  5      I Sh  vN     Sn
A
GM{  Sn
A
f[          a  n
[        XUS9   Sn
A
GM  Sn
A
ff = f GN GN	 GN! , ISh  vN  (       d  f       GN= f GN! , ISh  vN  (       d  f       GN= f! [         a=  n
XC:  a
  [        XUS9  [        R                  " SU-  5      I Sh  vN     Sn
A
GM  Sn
A
f[          a  n
[        XUS9   Sn
A
GM  Sn
A
ff = f GN GN GN! , ISh  vN  (       d  f       GN+= f GN#! , ISh  vN  (       d  f       GN9= f! [         a=  n
XC:  a
  [        XUS9  [        R                  " SU-  5      I Sh  vN     Sn
A
GMe  Sn
A
f[          a  n
[        XUS9   Sn
A
GM  Sn
A
ff = f GN' GN GN! , ISh  vN  (       d  f       GN= f GN! , ISh  vN  (       d  f       GN= f! [         a=  n
XC:  a
  [        XUS9  [        R                  " SU-  5      I Sh  vN     Sn
A
GM  Sn
A
f[          a  n
[        XUS9   Sn
A
GM  Sn
A
ff = f GNs  snf  GN! [         aB  n
Uc  SnXC:  a
  [        XUS9  [        R                  " SU-  5      I Sh  vN     Sn
A
GM2  Sn
A
f[          a  n
[        XUS9   Sn
A
GMP  Sn
A
ff = f7f)*z
Batch write updates to db.

Triggered every minute.

Requires:
user_id_list: dict,
keys_list: list,
team_list: list,
spend_logs: list,
r  Nr   r   <   r  )timeoutr  r  	incrementr*  )r   rK  r  r  zEnd-User Spend transactions: {}F)r  r  blockedr(  zKEY Spend transactions: {}r  zTeam Spend transactions: {}z#Updating spend for team id={} by {}r  z::)r  r  r+  zSpend Logs transactions: {}r   r*  SPEND_LOGS_URL/zbase_url: {}zspend/updatezContent-Typezapplication/json)urlrL   headers   T)rL   skip_duplicateszFlushed z logs to the DB.z% logs processed. Remaining in queue: )-r   r  rn   ranger  r  txr   rC  r^  r  r<  r   $_raise_failed_update_spend_exceptionr   sleepr   r   r9   r:   r  r<   max_end_user_budgetlitellm_endusertabler0  r  r  r  r  r  rx  litellm_teammembershipr  litellm_organizationtabler  r  r  endswithpostr.  r/  r   r  r  create_many)r  r  r  n_retry_timesirK  transactionrI  r  response_costr   end_user_idr  r  r\   org_id
BATCH_SIZEMAX_LOGS_PER_INTERVALbase_urlr   logs_to_processjbatchentrybatch_with_datess                            r@   update_spendr  _	  s      MA
=..3356:}q()AJ(++..%b1 /   *1133w +@@FFH#)#55AA'0'&:&-]/K%L B  I	  43   3 % *@ )0077<<>?	

 =22779:Q>}q()AJ%(++..%b1 /   *1133w +DDJJL')&::F $#88??'0+&> 4?1>38/&
 07m8T.U&" @ 
 M	  43 .  7 9 *T $++22779:	

 =--22459}q()AJ(++..%b1 /   *1133w +??EEG!)#==II'.&6&-]/K%L J  H	  43   2 % *@ %,,3388:;	

 =..3356:}q()AJ (++..%b1 /   *1133w +@@FFH#)066 E L L$+!"
 $55AA'0'&:&-]/K%L B  I	  43 $  3 / *J =55::<=A}q()AJ(++..%b1 /   *1133w +GGMMO) '*iioa&8G&)iioa&8G#::FF29&N&-]/K%L G  P	  43 "  : - *H =--22459}q()AJ(++..%b1 /   *1133w +??EEG")#==II'8&&A&-]/K%L J  H	  43   2 % *@ %,,S1U1U-VW J 
=//014}q()AJC99%5t< <<=A ,(4#,,S11 C(..~/D/DX/NO%5%:%:$~5!ZZ(L(LM!/1C D &; &  H
  ++s2?A<&3&J&J..'O #1c/&:JG /A
N C */, */ *88!"&+!"
 */ ) , ,..@@LL!14 M    -22&s5zl2BC% H. &<<S=Q=ST "8 )../00UVYZgZ~Z~V  VA  B k * 5W  4333     - *%8FW mmAqD)))) 4BS   4333   4 - *%8FW mmAqD)))) 4BS   4333     - *%8FW mmAqD)))) 4BS   4333   * - *%8FW mmAqD)))) 4BS   4333   ( - *%8FW mmAqD)))) 4BS   4333     - *%8FW mmAqD)))) 4BS 6  ,  - *9A&8FW
 mmAqD)))) 4BS s  Aw6$g9f:g=f)f
f)Aff)&f'f)+g6f&7gBw6$i.>h,?i.ih/
iAh59ih2i	i.ii. Bw68$lkl k=5k
6k=9Ak>k=	k
k=lk:l%Bw6=$o!n "o%n':n
;n'>A*n	(n'3n4n'8on$oAw6"$q,p*q,
qp-
 q#A-p3qp0q q,+q,q,7Aw6	$t-s.t1s;s
s;
Ass;ss;t*s8+t6Bw68B-v	%u>&Av	6v)v	<v=A?v	<w6gf)f)f#ff#f)&g)g	/f20g	<g
h)+h9g<:h?w6h)
h$w6$h))w6,i./i2i5i;h><iii.i+	ii+	&i..
k8+j0#j&$j0)w60k=
kw6kw6lk=k=k7%k(&k72k=:l=l	ll	l
m="+mmmw6m='
m81w68m==w6 on'n'	n!nn!n'$o'n?	-n0.n?	:o
p'+p7o:8p=w6p'
p"w6"p''w6*q,-q0q3q9p<:qqq,q)	qq)	$q,,
s6+r.!r$"r.'w6.s;
sw6sw6ts;s;s5#s&$s50s;8t;t	tt	t
u; +uuuw6u;%
u6/w66u;;w6>v	v		
w30www	w6w3
w.'w6.w33w6r   rK  c           	          SSK nS[        U 5       3nUS-   UR                  " 5       -   n[        R                  " 5       nXa-
  n[        R
                  " UR                  U USUS95        U e)z
Raise an exception for failed update spend logs

- Calls proxy_logging_obj.failure_handler to log the error
- Ensures error messages says "Non-Blocking"
r   NzC[Non-Blocking]LiteLLM Prisma Client Exception - update spend logs: r  r  r  )r8   r   r;   r  r   r   r5  )r   rK  r  r8   r  r  r  r  s           r@   r  r  
  s      NcRSfXV   $&)=)=)??Oyy{H%I)) $)	 	* 	
 GrB   current_spendsoft_budget_limitc                    SSK Jn  Uc  gUR                  5       nUR                  S:X  a"  U" UR                  S-   SS5      [        SS9-
  nO+U" UR                  UR                  S-   S5      [        SS9-
  nXC-
  R                  nUR                  S:X  a  U nOXR                  S-
  -  nXU-  -   nXq:  a  [        S5        gg)	Nr   )dateF   r   daysz*Projected spend exceeds soft budget limit!T)	r   r  todaymonthyearr   r  dayrA   )r  r  r  r  	end_monthremaining_daysdaily_spend_estimateprojected_spends           r@   _is_projected_spend_over_limitr  
  s      JJLE {{baA.1BB	U[[1_a89!;LL	'--N yyA~,,		A> $n'LMO*BCrB   c                 D   SS K nUc  g UR                  R                  5       nUR                  " UR                  UR                  S-   S5      UR
                  " SS9-
  nXC-
  R                  nU UR                  S-
  -  nXe-  nXq:  a  X-  nX2R
                  " US9-   n	Xy4$ g )Nr   r   r  )r   r  r  r  r  r   r  r  )
r  r  r   r  r  r  daily_spendr  approx_dayslimit_exceed_dates
             r@   _get_projected_spend_over_limitr  
  s      MM!Eejj%++/1=@R@RA I  '--N		AK "2O*'5!$6$6K$HH 11rB   c           	          U b  Ub  Uc  g SU;   a0  UR                  S5      nUS   nXC;  a  [        SU  SU SU S35      eg )Nmodelsr   zInvalid model for team z: z.  Valid models for team are: r  )rI   r   )r  team_configr   valid_modelsmodel_in_requests        r@   _is_valid_team_configsr    sk    +-1E;"x0'0/)'"5E4FFdeqdrrtu  rB   c                 :    [        U R                  5       S-  5      $ )Ng    eA)rs  	timestamp)dts    r@   _to_nsr    s    r||~#$$rB   c                 
   Sn[        U [        5      (       a  [        U R                  [        5      (       a  U R                  nU$ [        U R                  [        5      (       a"  [
        R                  " U R                  5      nU$ [        U S5      (       aS  [        U SS 5      n[        U[        5      (       a  UnU$ [        U[        5      (       a  [
        R                  " U5      nU$ [        U 5      n U$ [        U 5      nU$ )Nr   r   )	rG   r   r   r   rH   r.  r/  r   r<  )r   r   _errors      r@   get_error_message_strr    s    M!]##ahh$$HHM  $'' JJqxx0M  Q	""Q	40F&#&& &  FD)) $

6 2
   FM  ArB   c                  0    [         R                  " SS5      $ )zx
Get the redoc URL from the environment variables.

- If REDOC_URL is set, return it.
- Otherwise, default to "/redoc".
	REDOC_URLz/redocr  r  r^   rB   r@   _get_redoc_urlr  +  s     99[(++rB   c                  |    [         R                  " SS5      n U (       a  U $ [         R                  " SS5      S:X  a  gg)z
Get the docs URL from the environment variables.

- If DOCS_URL is set, return it.
- If NO_DOCS is True, return None.
- Otherwise, default to "/".
DOCS_URLNNO_DOCSr  r  r  r  )docs_urls    r@   _get_docs_urlr  5  s7     yyT*H	yyG$. rB   c           
         SSK Jn  [        U [        5      (       aR  [	        [        U SS[        U 5       S35      [        R                  [        U SS5      [        U SUR                  5      S	9$ [        U [        5      (       a  U $ [	        S
[        U 5      -   [        R                  [        U SS5      UR                  S	9$ )z_
Returns an Exception as ProxyException, this ensures all exceptions are OpenAI API compatible
r   )r   r   zerror()paramNoner   )r   r  r  codezInternal Server Error, )
fastapir   rG   r   r   r<  r   r   internal_server_errorHTTP_500_INTERNAL_SERVER_ERROR)r   r   s     r@   handle_exception_on_proxyr  H  s     !]##Ax6#a&);< 66!Wf-M6+P+PQ	
 	
 
A~	&	&)CF222a&)22	 rB   rT   )NNN)xr   rJ   r  r{  r.  r  r  re  r  r8   r   r   email.mime.multipartr   email.mime.textr   typingr   r   r	   r
   r   r   r   *litellm.litellm_core_utils.duration_parserr   litellm.proxy._typesr   r   r   rp  r~  r  r   r   r<   litellm.litellm_core_utils*litellm.litellm_core_utils.litellm_loggingr   r   r   r   litellm._loggingr   litellm._service_loggerr   r   litellm.caching.cachingr   r   litellm.exceptionsr   %litellm.integrations.custom_guardrailr   "litellm.integrations.custom_loggerr   1litellm.integrations.SlackAlerting.slack_alertingr    (litellm.integrations.SlackAlerting.utilsr!   r"   'litellm.llms.custom_httpx.httpx_handlerr#   r$   r%   r&   r'   r(   r)   litellm.proxy.db.create_viewsr*   r+   litellm.proxy.db.log_db_metricsr,   litellm.proxy.db.prisma_clientr-   'litellm.proxy.hooks.cache_control_checkr.   &litellm.proxy.hooks.max_budget_limiterr/   ,litellm.proxy.hooks.parallel_request_limiterr0   $litellm.proxy.litellm_pre_call_utilsr1   litellm.secret_managers.mainr2   )litellm.types.integrations.slack_alertingr3   litellm.types.utilsr4   r5   opentelemetry.tracer6   _SpanrA   rN   rP   r   r  r  r   r  r  r  r  r  r  r  r   r   r  r  tupler  r  r  r  r  r  r  r^   rB   r@   <module>r;     sV        	     ( . $ O O O J  *  ! 1 K K 1 @ 9 3 A ; K T > ?  ; 8 L J J 4 I >1DD36d
 d
PR RpJ
L
 L
`$)3 )(3- )3 )Z3 y l *5Mpc 	 	 	@l @FHH{+H $HV
#8D8-5e_D-5e_e_:%Y 3 (, ,x} & ~ _Y  
O s    G$ $G3