
    g                       d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
m
Z
mZ d dlmZ d dlmZ d dlmZmZmZmZmZmZmZ d dlmZ d dlmZmZmZ 	 d dlZd d	l m!Z!m"Z" d dl#Z#d dl$Z#d dl%Z#d d
l#m&Z&m'Z'm(Z(m)Z) d dl*m+Z+ d dl,m-Z-m.Z. d dl/m0Z0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9 d dl:m;Z; d dl%m<Z< d dl=m>Z> d dlm?Z?m@Z@mAZAmBZBmCZCmDZD d dlEmFZFmGZG d dlHmIZI d dlJmKZK d dlLmMZM d dlNmOZO d dlPmQZQ d dlRmSZS d dlTmUZU d dlVmWZW d dlXmYZYmZZZ er	d d l[m\Z] e]Z\neZ\d! Z^d" Z_ G d# d$      Z` G d% d&      Zad' Zbd(ecd)ecfd*Zd G d+ d,      ZedJd-efd.eef   d)efd/Zgd0efd1e0d2eefd3Zhd4 Zid5effd6Zjd5efd)effd7Zkd8eefd9Zld8eed:ee>   d;eafd<Zmd=end>eod;eafd?Zpd@eodAeeo   fdBZqd@eodAeeo   d)eer   fdCZsdKdDZtdE Zud=end)effdFZvd)effdGZwd)eef   fdHZxd=end)efdIZyy# e$ r	  ed      w xY w)L    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                     ddl }t        j                  dj                  |  |j                                      t
        j                  rt        d|         yy)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     H/var/www/openai/venv/lib/python3.12/site-packages/litellm/proxy/utils.pyprint_verboserA   N   sJ     x@T	@T@T@VWX012     c                     t         j                  du r| S d}d}t        | t              rd| v rd| d   v r| d   j	                  d      }t        j                  |       }t        | t              r|d| v r|| d   d<   |S )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;SD78OrB   c            	           e Zd ZdefdZ	 ddeedf   dedefdZ		 ddeedf   deddfdZ
	 dd	edeedf   deddfd
Z	 	 ddedee   defdZ	 ddedeedf   defdZ	 ddeddfdZ	 ddedefdZy)InternalUsageCache
dual_cachec                     || _         y NrQ   )selfrQ   s     r@   __init__zInternalUsageCache.__init__y   s	    %/rB   rE   N
local_onlyreturnc                 ^   K    | j                   j                  d|||d| d {   S 7 w)N)keyrW   parent_otel_span )rQ   async_get_cache)rU   rZ   rE   rW   kwargss        r@   r]   z"InternalUsageCache.async_get_cache|   sC      5T__44 
!5
 	
 
 	
 
   $-+-c                 `   K    | j                   j                  d||||d| d {   S 7 w)N)rZ   valuerW   rE   r\   )rQ   async_set_cacherU   rZ   ra   rE   rW   r^   s         r@   rb   z"InternalUsageCache.async_set_cache   sF      5T__44 
!%=	

 
 
 	
 
   %.,.
cache_listc                 ^   K    | j                   j                  d|||d| d {   S 7 w)N)re   rW   rE   r\   )rQ   async_set_cache_pipeline)rU   re   rE   rW   r^   s        r@   async_batch_set_cachez(InternalUsageCache.async_batch_set_cache   sC      >T__== 
!!%=
 	
 
 	
 
r_   keysr[   c                 Z   K   | j                   j                  |||       d {   S 7 w)N)ri   r[   rW   )rQ   async_batch_get_cache)rU   ri   r[   rW   s       r@   rk   z(InternalUsageCache.async_batch_get_cache   s7      __::-! ; 
 
 	
 
s   "+)+ra   c                 `   K    | j                   j                  d||||d| d {   S 7 w)N)rZ   ra   rW   r[   r\   )rQ   async_increment_cacherc   s         r@   rm   z(InternalUsageCache.async_increment_cache   sF      ;T__:: 
!5	

 
 
 	
 
rd   c                 B     | j                   j                  d|||d|S )N)rZ   ra   rW   r\   )rQ   	set_cache)rU   rZ   ra   rW   r^   s        r@   ro   zInternalUsageCache.set_cache   s5     )t(( 
!
 	
 	
rB   c                 @     | j                   j                  d||d|S )N)rZ   rW   r\   )rQ   	get_cache)rU   rZ   rW   r^   s       r@   rq   zInternalUsageCache.get_cache   s2     )t(( 
!
 
 	
rB   F)NF)__name__
__module____qualname__r   rV   r   r6   boolr   r]   rb   r	   rh   listr   rk   floatrm   ro   rq   r\   rB   r@   rP   rP   x   sC   09 0 !	
 #(d
"3
 	
 

& !
 #(d
"3	

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

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

 


rB   rP   c                      e Zd ZdZ	 d:dedefdZdee   dee	   fdZ
	 	 	 	 	 	 d;d	ee   d
ee   dee	   deee      dee   dee   fdZd<dee   fdZdeded   fdZd Zededdded   ddfd       Zedededed   defd       Zdedee   ded   dee   fdZdededed   fdZd ed!efd"Zd#ed$   d%efd&Z	 d<d'ed(ed)   d*ed+ee   fd,Z	 d=d-edefd.Z	 	 d>d+ed/eded0ee   d1ee   f
d2Z 	 d<d/ed0ee   defd3Z!	 	 d>d+eded1ee   d/ee   fd4Z"ded5e#e$e%e&f   defd6Z'd5e#e$e%e&f   defd7Z(d5edefd8Z)d<dee   fd9Z*y)?ProxyLoggingz
    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                    i | _         || j                   d<   t        t        d            | _        t	        | j                        | _        t               | _        t               | _	        d | _
        d| _        t        | _        d | _        t        | j                  | j                  | j                  j                         | _        || _        t'               | _        y )Nr{      )default_in_memory_ttlrT   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    rQ   slack_alerting_instancer|   r   service_logging_obj)rU   r{   r|   s      r@   rV   zProxyLogging.__init__   s     #%2D./8J q99
! -N%%-
) #:";#;#= (,),,?48!6C#66]]!%!:!:!E!E7
$
 )#1#3 rB   
llm_routerredis_usage_cachec                 .   | j                   j                  |       | j                  |       | j                  |       | j                   Id| j                   j                  v r0t	        j
                  | j                   j                  |             yyy)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)rU   r   r   s      r@   startup_eventz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                 <   d}|	|| _         d}|	|| _        d}|	|| _        d}|	|| _        d}|du r| j                  j                  | j                   | j                  | j                  || j                         | j                   xd| j                   v rjd| j                  v r)t        j                  j                  | j                         t        j                  j                  | j                  j                         ||| j                  j                  _        y y )NFT)r   r   r   r   r   slackr   )r   r   r   r   r   r   r<   	callbacksappendsuccess_callback!response_taking_too_long_callbackr   rQ   r   )rU   r   r   r   r   r   r   updated_slack_alertings           r@   r   zProxyLogging.update_values!  s$    (-$DM%)")&8D#%)""*D%)"+(<D%%)"!T)((66#'#:#: ,,+%)%>%> 7  }}(W-E #d&6&66%%,,T-I-IJ((//00RR "?JD%%00< #rB   c                    t         j                  j                  | j                         t         j                  j                  | j                         t         j                  j                  | j
                         t         j                  j                  | j                         t         j                  D ]~  }t        |t              rCt         j                  j                  j                  || j                  j                  |      }|W|t         j                  vrt         j                  j                  |       |t         j                  vrt         j                  j                  |       |t         j                   vrt         j                   j                  |       |t         j"                  vrt         j"                  j                  |       |t         j$                  vrt         j$                  j                  |       |t         j&                  vs`t         j&                  j                  |        t)        t         j                        dkD  s8t)        t         j                        dkD  st)        t         j                         dkD  rot+        t-        t         j                  t         j                  z   t         j                   z               }t         j                  j                  j/                  |       y y )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   rQ   input_callbackr   failure_callback_async_success_callback_async_failure_callbackservice_callbacklenrw   setset_callbacks)rU   r   callbackr   s       r@   r   z$ProxyLogging._init_litellm_callbacksM  s.     !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                    K   | j                   y | j                  }|dz  }| j                  j                  dj	                  |      |d|d        d {    y 7 w)Nd   zrequest_status:{}T)rZ   ra   rW   ttlrE   )r   r   r   rb   r:   )rU   r   r   r   s       r@   update_request_statusz"ProxyLogging.update_request_statusx  sm      ==  %)$;$; 	c!''77#**?;"%) 8 
 	
 	
s   AAAAc                    K   t        |t              r|t        |t              r|S t        |t              r2|dv rt	        ||j                  dd      d|      t        dd|i      |S w)N)
completiontext_completionmodel )messager   llm_providerrequest_data  errorstatus_codedetail)rG   	ExceptionrH   r   r   getr   )rU   responserL   	call_types       r@   process_pre_call_hook_responsez+ProxyLogging.process_pre_call_hook_response  st     h	*Nh%Oh$==*$((7B/!#!%	  $Wh<OPPs   A)A+user_api_key_dictrL   r   )r   r   
embeddingsimage_generation
moderationaudio_transcriptionpass_through_endpointrerankrX   c                    K   y wrS   r\   rU   r   rL   r   s       r@   pre_call_hookzProxyLogging.pre_call_hook         	   c                    K   y wrS   r\   r   s       r@   r   zProxyLogging.pre_call_hook  r   r   c                   K   t        j                  d       | j                  |       |y	 t        j                  D ]b  }d}t        |t              r*t        j                  j                  j                  |      }n|}|t        |t              rpddlm} |j                  ||j                        durz|j                  || j                   d   ||	       d{   }|| j#                  |||
       d{   }|t        |t$              sdt'        |j(                        v s|j(                  j                  t$        j                  k7  s|j                  || j                   d   ||	       d{   }|G| j#                  |||
       d{   }e |S 7 7 7 -7 # t*        $ r}|d}~ww xY ww)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!rL   Nr   GuardrailEventHooksrL   
event_typeTr{   )r   cacherL   r   )r   rL   r   async_pre_call_hook)r   r9   #_init_response_taking_too_long_taskr<   r   rG   r   r   r   "get_custom_logger_compatible_classr   litellm.types.guardrailsr   should_run_guardrailpre_callr   r   r   r   vars	__class__r   )	rU   r   rL   r   r   	_callbackr   r   es	            r@   r   zProxyLogging.pre_call_hook  s    . 	""#HI00d0;<4	#-- 	h, ' : : J J m m !I !)I(Z	?-SL "66!%2E2N2N 7   $$
 !%.%B%B*;"//0DE!"+	 &C &  H  +%)%H%H%-DI &I &  
 )"9l;-i6I6I1JJ!++??#778 &/%B%B*;"//0DE!"+	 &C &  H  +%)%H%H%-DI &I &  [ .b K;    
  	G	s   +GB/F. F&F. %F. <F(=F. F. F. .'F. %F. <F*=F. F. F,F. %G&F. (F. *F. ,F. .	F>7F99F>>G)r   r   r   r   r   c                 Z  K   t         j                  D ]~  }	 t        |t              rk|j                  t        |d      r|j                  dk(  r( yddlm} |j                  ||j                        durc|j                  |||       d{     |S 7 # t        $ r}|d}~ww xY ww)	zD
        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   )rU   rL   r   r   r   r   r   s          r@   during_call_hookzProxyLogging.during_call_hook  s       ))Hh8  **2w "48 $44
B" Q %99%)6I6U6U :  $((
 %"88!*;"+ 9   1 *> 
  sR   B+7BB+%B5B+6BBBB+B	B(!B##B((B+error_messagefailing_modelc                    K   | j                   y | j                  r&| j                  j                  ||       d {    y y 7 w)N)r   r   )r   r   failed_tracking_alert)rU   r   r   s      r@   r   z"ProxyLogging.failed_tracking_alertH  sR     
 == ''..DD++ E    (s   :AAAtype)token_budgetuser_budgetsoft_budgetteam_budgetproxy_budgetprojected_limit_exceeded	user_infoc                 t   K   | j                   y | j                  j                  ||       d {    y 7 w)N)r   r   )r   r   budget_alerts)rU   r   r   s      r@   r   zProxyLogging.budget_alertsV  s>      == **88 9 
 	
 	
s   .868r   level)LowMediumHigh
alert_typer   c           
        K   | j                   yddlm}  |j                         j                  d      }t	        j
                  dd      }d| d| d| }|	|d	| d
z  }i }	i }
|ft        |       d{   }|||	d<   |dj                  |      z  }d|v r3|d   j                  dd      t        |d   d   t              r|d   d   }
| j                   D ]  }|dk(  r+ | j                  j                  d|||d|
d|	 d{    3|dk(  s9t        j                  j                  *t        j                  j                  j!                  |       }t#        d       y7 7 ^w)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   )rU   r   r   r   r   r   current_time_proxy_base_urlformatted_messageextra_kwargsr  _urlclients                r@   alerting_handlerzProxyLogging.alerting_handlerj  s    * == % $x||~..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$0$<=P$Q!mmF =d22== #)"&7 #   8#==44@MM55EEFWX#$IJJ $ Ts,   A5E(7E$8BE(E&
E(AE(&E(durationc                   K   t         j                  | j                  vryt        |t              rmt        |j
                  t              r|j
                  }nQt        |j
                  t              r t        j                  |j
                        }nt        |      }nt        |      }t        |t              r||dd z  }t        j                  | j                  d| dt         j                  i              t        | d      r5| j                  j                  t         j"                  |||       d{    t$        j&                  j(                  r!t$        j&                  j)                  |       yy7 @w)	z]
        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)rU   original_exceptionr  r   traceback_strr   s         r@   failure_handlerzProxyLogging.failure_handler  sG     ""$*:*::(-8,33S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   D3E85E66AE8r  
error_typeroutec                   K   | j                  |j                  dd      d       d{    t        j                  | j                  v rjt        |t              sZ	 t        |dd      }t        |      }|||z  }t        j                  | j                  d| dd	t        j                  |
             | j                  ||      r| j                  ||||       d{    t        j                  D ]o  }	 d}	t        |t              r*t        j                   j"                  j%                  |      }	n|}	|	,t        |	t&              r|	j)                  |||       d{    q y7 >7 7 # t*        $ r}
|
d}
~
ww xY ww)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  )r  r!  )r   r   r"  r  )r   r   r  )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   )rU   r   r  r   r!  r"  r$  exception_strr   r   r   s              r@   post_call_failure_hookz#ProxyLogging.post_call_failure_hook  s    $ (((,,->CF ) 
 	
 	
 ##t'7'77
A

 "));=QSW!X 23M!-!33%%4]O1E (77!-	 &  $$1j % 
 77)"3#5	 8     ))H48	h, ' : : J J m m !I !)I(Z	<-P#@@%1*;+= A    *" 	k	
:"
  sY   'FE'B5FE* F8A'E.E, E.$F*F,E..	E>7E99E>>Fc                 L    t        |t              xs |t        j                  k(  S )a  
        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)rU   r  r!  s      r@   r'  z!ProxyLogging._is_proxy_only_error  s'     ,m< 
/444	
rB   c                 t  K   |j                  dd      }|ddl}t        |j                               |d<   t	        j
                  |      }t        j                  j                  d|xs dt        j                  j                         t        j                         d|\  }}d|vri |d<   |d   j                  |       |i }	i }
t        j                  j                         }|j!                         D ]   \  }}||v r||
|<   |d	k7  s|d
k7  s||	|<   " |j#                  |j                  d	d      |j                  d
d      |	|
       d}d|v rGt%        |d   t&              r4|d   }||j(                  d<   t*        j,                  j.                  |_        nd|v rGt%        |d   t              r4|d   }||j(                  d<   t*        j2                  j.                  |_        nJd|v rFt%        |d   t&              r3|d   }||j(                  d<   t*        j4                  j.                  |_        |j7                  |d       |j9                  |t;        j<                                d{    t?        j@                  |jB                  |t;        j<                         f      jE                          yy7 Iw)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   r4  optional_paramslitellm_paramsmessagespromptinput)r9  api_key)	exceptiontraceback_exception)targetargsr\   )#r   uuidr   uuid4r1   'get_sanitized_user_information_from_keyr<   r	  function_setupRulesr   r  updater5   __annotations__ri   itemsupdate_environment_variablesrG   rw   model_call_detailsr4   acompletionra   r   atext_completion
aembeddingr   async_failure_handlerr8   r;   	threadingThreadr   start)rU   r   r   r"  r  r/  r?  user_api_key_logged_metadatarL   _optional_params_litellm_paramslitellm_param_keyskvr9  s                  r@   r(  z-ProxyLogging._handle_logging_proxy_only_error0  s     2>1A1A!42
 &.1$**,.?L*+(PP&7 ) )0(D(D )"'"8=!----/#<<>) 	)% -+-Z($++,HI*! O!4!D!D!I!I!K$**,1**)*OA&'\a6k*+$Q'	 -  <<"&&w3!%%fb1 0.	 =  -/E\)jZ($/ %Z0EJ#66zB090E0E0K0K#-\)jh9OQT.U$X.CH#66x@090J0J0P0P#-L(ZW8Mt-T$W-BG#66w?090D0D0J0J#-(( )  &;;,$-$8$8$: <   
 *::&((* egg +Ps    D
J8J8EJ8,J6-A
J8r   c                   K   t         j                  D ]  }	 d}t        |t              r*t         j                  j
                  j                  |      }n|}|t        |t              rCddlm	} |j                  ||j                        durz|j                  |||       d{    n,t        |t              r|j                  |||       d{     |S 7 57 
# t        $ r}|d}~ww xY ww)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   )rU   rL   r   r   r   r   r   r   s           r@   post_call_success_hookz#ProxyLogging.post_call_success_hook  s      ))H'48	h, ' : : J J m m !I !)I( "(O<P %99%)6I6S6S :  $((
 %&CC.?!%%- D    $I|<'DD.?!%%- E   E *R !
  sY   C1A5CC1C$C%,CCCC1CC	C.'C))C..C1c                   K   d}t        |t              rt        j                  |      }|t        j                  D ]n  }	 d}t        |t
              r*t        j                  j                  j                  |      }n|}|+t        |t              r|j                  ||       d{    p |S 7 # t        $ r}|d}~ww xY ww)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   )rU   r   r   response_strr   r   r   s          r@   r^  z+ProxyLogging.async_post_call_streaming_hook  s      '+h."66HML##--8<I!(C0$+$>$>$N$N$q$q$%	 %-	 ,I|1T'FF.?, G    .  ! Gs<   >CA&B2'B0(B2,C0B22	C;B==CCc                    K   t        j                  |      }t        j                  D ].  }	 t	        |t
              r|j                  ||       d{    0 |S 7 # t        $ r}|d}~ww xY ww)z
        - Check outgoing streaming response uptil that point
        - Run through moderation check
        - Reject request if it fails moderation check
        r\  N)rJ   rK   r<   r   rG   r   r^  r   )rU   r   r   new_responser   r   s         r@   post_call_streaming_hookz%ProxyLogging.post_call_streaming_hook  s|      }}X.))Hh5"AA*;l B    *   s:   )A0&AAAA0A	A-&A((A--A0c                     | j                   rG| j                   j                  0t        j                  | j                   j	                  |             yyy)z
        Initialize the response taking too long task if user is using slack alerting

        Only run task if user is using slack alerting

        This handles checking for if a request is hanging for too long
        Nr  )r   r   r   r   response_taking_too_long)rU   rL   s     r@   r   z0ProxyLogging._init_response_taking_too_long_task  sP     ((,,55A,,EESWEX B )rB   rr   )NNNNNNrS   )r   )NN)+rs   rt   ru   __doc__r   rv   rV   r   r   r   r   r	   rx   r$   rH   r   r   r   r
   r   r   r   r)   r   r   r   r%   r   r  r   r   r   r+  r'  r(  r   r   r   r   rY  r^  rb  r   r\   rB   r@   rz   rz      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.. *. #
	.` 
(

 
2 (,?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   rz   c                 &    t        d| d           y )Nz!Backing off... this was attempt #tries)rA   )detailss    r@   
on_backoffri  
  s    5gg6F5GHIrB   rL   rX   c                     t        j                  |       }|j                         D ]/  \  }}t        |t              s	 t        j                  |      ||<   1 |S # t        $ r d||<   Y Dw xY wNzfailed-to-serialize-jsonrJ   rK   rF  rG   rH   r  r  r   )rL   db_datarT  rU  s       r@   jsonify_objectrn    se    mmD!G1a8!ZZ]
   N  87
8   AA+*A+c                       e Zd ZU i Zeed<   i Zeed<   i Zeed<   i Zeed<   i Z	eed<   i Z
eed<   g Zeed<   	 d=d	ed
edee   fdZdefdZdedefdZ ej*                  ej,                  edde      d        Ze ej*                  ej,                  edde      dededed   fd              Z ej*                  ej,                  edde      e	 	 	 	 	 	 	 	 	 	 	 	 	 	 d>deeeef      dee   dee   dee   d ee   d!ee   deed"      d#ed$   d%ee   d&ee   d'ee    d(ee    d)ee!   d
ee   fd*              Z"d+efd,Z# ej*                  ej,                  edde      deded-   fd.       Z$ ej*                  ej,                  edde      di dddd/dddf	dee   ded0ee   dee   dee   d#ed1   deed2      d3ee   d4ee   fd5       Z% ej*                  ej,                  edde      	 	 	 	 d?d6ee   d ee   deed2      dee   fd7       Z& ej*                  ej,                  edde      d8        Z' ej*                  ej,                  edde      d9        Z(d: Z)de fd;Z*d@d<Z+y)APrismaClient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                    || _         t        t        j                  d            | _        t        j                  d       	 ddlm} |2t         ||      | j                  | j                  nd      | _        n/t         |       | j                  | j                  nd      | _        t        j                  d	       y # t        $ r t        d      w xY w)
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)rz  r2   r  r  r  r   r9   prismar~  r   r-   db)rU   ry  rz  r{  r~  s        r@   rV   zPrismaClient.__init__%  s     "31<II)*2
 	""#=>	?% "# &K 8 --9 **DG $ & --9 **DG 	""#DE)  	?=>>	?s   C   Ctokenc                 h    t        j                  |j                               j                         }|S rS   hashlibsha256encode	hexdigest)rU   r  hashed_tokens      r@   
hash_tokenzPrismaClient.hash_tokenI  s%    ~~elln5??ArB   rL   rX   c                     t        j                  |      }|j                         D ]/  \  }}t        |t              s	 t        j                  |      ||<   1 |S # t        $ r d||<   Y Dw xY wrk  rl  )rU   rL   rm  rT  rU  s        r@   rn  zPrismaClient.jsonify_objectO  se    --%MMODAq!T"<!%AGAJ $  ! <!;GAJ<ro     
   )	max_triesmax_timeri  c                 H  K   	 g d}d}dj                  d |D              }t        j                  dd      }| j                  j	                  d| d| d	       d
{   }t        |      }|d   d   |k(  rt        j                  d       y
|d   d   r[||d   d   vrQ| j                          d
{    | j                  j                  d       d
{    t        j                  d       y
t        | j                         d
{   }|rt        | j                         d
{    y
|d   d   rt        |d   d         n	t               }t        |      }	|	|z
  }
t        j                  dj                  |
             	 y
7 ,7 7 7 7 g# t        $ r  w xY ww)a|  
        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   (   K   | ]
  }d | d   yw)'Nr\   ).0views     r@   	<genexpr>z1PrismaClient.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   )rU   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_existszPrismaClient.check_view_exists[  s    *K		N <M!%*R>*R!R		"3X>I))) *3 4+, - C $'~#6 1vl#';;$))*FG q6,'MQAU,U++---''--
   )--F2 	+ 1Ltww0W*W'*2dgg>>>& 	 :=Q9MCA| 45SVSX + .1-@*(:=O(O,44 b  i  i - 	}, .$ +X>"  		s   F"AF F	/F F"%F 3F4"F FF 0F"1F 
FF *F+F /F"0AF F"	F F F F F FF"r~      rZ   ra   
table_name)usersri   configspendc           	        K   t        j                  d| d|        t        j                         }	 |dk(  r2| j                  j                  j                  ||i       d{   }|S |dk(  r2| j                  j                  j                  ||i       d{   }|S |dk(  r2| j                  j                  j                  ||i       d{   }|S |dk(  r0| j                  j                  j                  ||i       d{   }S 7 7 v7 A7 # t        $ r}d	dl
}d
t        |       }t        j                  |       |dj                  t        |            z   }|dz    |j                         z   }	t        j                         }
|
|z
  }t!        j"                  | j$                  j'                  |||	d             |d}~ww xY ww)z4
        Generic implementation of get data
        z PrismaClient: get_generic_data: z, table_name: r  whereNri   r  r  r   z2LiteLLM Prisma Client Exception get_generic_data: z
Exception Type: {}
get_generic_data)r  r  r  r   )r   r9   timer  litellm_usertable
find_firstlitellm_verificationtokenlitellm_configlr   r8   r   r   r:   r   r;   r   r   rz  r   )rU   rZ   ra   r  r3  r   r   r8   	error_msgerror_tracebackend_time	_durations               r@   r  z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'$.1E1E1E1GGOyy{H :-I&&66'(&"10	 7  G%	s   0G0D #D$D )G*0D DD  G!0D DD G0D D	D GD D D D 	G B(GGGuser_iduser_id_listteam_idteam_id_listkey_val)r4  rZ   r  r  teamuser_notificationcombined_view
query_type)find_uniquefind_allexpiresreset_atoffsetlimitr[   c           	        K   t               }t        j                         }d }	 d }||	||dk(  r|4t        |t              r$t	        |      }t        j                  d|        |dk(  r||t        ddd| i      | j                  j                  j                  d	|id
di       d {   }|I|j                  t        |j                  t              r|j                  j                         |_        nt        t        j                  d|       |dk(  r|| j                  j                  j!                  d|id
di       d {   }|Zt#        |      dkD  rK|D ]<  }t        |j                  t              s|j                  j                         |_        > n|dk(  r|| j                  j                  j!                  d|id
di       d {   }|t#        |      dkD  r|D ]<  }t        |j                  t              s|j                  j                         |_        > ny|dk(  r|	|
| j                  j                  j!                  dd idd|	iigd|
id       d {   }|2t#        |      dkD  r#|D ]<  }t        |j                  t              s|j                  j                         |_        > n|dk(  ri }|i |d	<   t        |t              rt	        |      }|g|d	   d<   nyt        |t$              rig }|D ]Z  }t        |t              sJ |j'                  d      r$| j)                  |      }|j+                  |       J|j+                  |       \ ||d	   d<   | j                  j                  j!                  ddi|d
di       d {   }||S t        t        j                  d      ||	|[|dk(  rU|dk(  r6|d|i}| j                  j,                  j                  |       d {   }|S |dk(  r2|0| j                  j,                  j!                  |       d {   }|S |dk(  r6|
4| j                  j,                  j!                  dd|
ii       d {   }|S |dk(  r6|4| j                  j,                  j!                  dd|ii       d {   }|S |dk(  rf|	=| j                  j,                  j!                  ddiddd idd|	iigi        d {   }|S d!}| j                  j/                  |||       d {   }|S |dk(  rt        j                  d"       |z|dk(  r8| j                  j0                  j                  |d   |d#   i       d {   }|S |dk(  r6| j                  j0                  j!                  |d   |d#   i       d {   }|S | j                  j0                  j!                  d$di%       d {   }|S |d&k(  r%|dk(  r5| j                  j2                  j                  d|id'di       d {   }|S |dk(  r6|
4| j                  j2                  j!                  dd|
ii       d {   }|S |dk(  r9|7| j                  j2                  j!                  d(d)|iid
di       d {   }|S |dk(  r6|4| j                  j2                  j!                  dd|ii       d {   }|S |dk(  r0|.| j                  j2                  j!                  d*+       d {   }|S |d,k(  rj|dk(  r2| j                  j4                  j                  d|i       d {   }|S |dk(  r,| j                  j4                  j!                          d {   }|S |d-k(  rd|4t        |t              r$t	        |      }t        j                  d|        |dk(  r'|t        ddd| i      d.| d/}t7        d0j9                  |             | j                  j;                  |1       d {   }||d2   g |d2<   |d3   d4|d3<   d }|d5   E|d   @	 |d5   D ]7  }|j=                  d      |d   |j=                  d      k(  s-t?        d<i |}9 ||d6<   tA        d<i |d7t        j                         i}|j                  9t        |j                  t              r|j                  j                         |_        |S y y 7 S7 7 '7 7 _7 7 7 7 Y7 7 7 7 b7 37 7 7 7 K7 7 7 7 # tB        $ r}dd l"}d8| }|t        |      z   }t7        |       |d9z    |jF                         z   }t        j                  |       t        j                         } | |z
  }!tI        jJ                  | jL                  jO                  ||!d:|;             |d }~ww xY ww)=NrZ   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 existr4  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'ra   	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,
                            -- Added comma to separate b.* columns
                            b.max_budget AS litellm_budget_table_max_budget,
                            b.tpm_limit AS litellm_budget_table_tpm_limit,
                            b.rpm_limit AS litellm_budget_table_rpm_limit,
                            b.model_max_budget as litellm_budget_table_model_max_budget,
                            b.soft_budget as litellm_budget_table_soft_budget
                        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
                        LEFT JOIN "LiteLLM_BudgetTable" AS b ON v.budget_id = b.budget_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r  r  r   r  r\   )(localsr  rG   r   _hash_token_if_neededr   r9   r   r  r  r  r  r   	isoformatr   HTTP_401_UNAUTHORIZED	find_manyr   rw   
startswithr  r   r  r  litellm_spendlogslitellm_teamtablelitellm_usernotificationsrA   r:   query_firstr   r'   r&   r   r8   r;   r   r   rz  r   )"rU   r  r  r  r  r  r  r  r  r  r  r  r  r[   rz  args_passed_inr3  r  r   rwhere_filterhashed_tokenst	new_token	sql_queryr  tmr   r8   prisma_query_infor  r  r  r  s"                                     r@   r  zPrismaClient.get_data  s    J  YY[
&*{	 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$9$FE;@'L1$7't4,.M%*'1!S'9 9'9#$<<#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  %	 *.):):9eV)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 
%*4 +0 15!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,#O_ / /} "   < &    
$0 $U$$  
     R   S^  JV  	"jkyjz {)CF2I)$'$.1E1E1E1GGO &&7yy{H :-I&&66'(&("1	 7  G'	s  !g3Be 2d3B"e d5e Ae $d%5e A"e =d>5e 4C>e 2d3e :g3;Ae de g30e de g34e 	d
e g34e de 
g3=e d 	e g3"e 1d#2e 7g38Ae 
d&e g36e d)e g3+e 9d,:e ?g3 9e 9d/:e ?g3 4e 4d25e :g3;7e 2d53e 8g394e -d8.e 3g340e $d;%e *g3+5e  d>!e &g3',e ee g3Be /e0A e 1e 	A9e g3e e e e e e e e e  e #e &e )e ,e /e 2e 5e 8e ;e >e e e 	g0Bg++g00g3rm  c                     | j                  |      }|j                  dd       .t        |d   t              rt	        j
                  |d         |d<   |S )Nr   members_with_roles)rn  r   rG   rw   r  r  )rU   rm  s     r@   jsonify_team_objectz PrismaClient.jsonify_team_object^  s[    %%7%3;;+T2>:()4D
 -1JJw?S7T,UG()rB   )r4  rZ   r  r  r  r  c           	      :  K   t        j                          }	 t        j                  d|       |dk(  r|d   }| j                  |      }| j	                  |      }||d<   t        d       | j                  j                  j                  d|ii |i ddd	i
       d{   }t        j                  d       |S |dk(  rc| j	                  |      }	 | j                  j                  j                  d|d   ii |i d       d{   }t        j                  d       |S |dk(  r| j	                  |      }|j                  dd      .t        |d   t               rt#        j$                  |d         |d<   | j                  j&                  j                  d|d   ii |i d       d{   }
t        j                  d       |
S |dk(  r	 g }|j)                         D ]^  \  }}|}t#        j$                  |      }| j                  j*                  j                  d|i||dd|id      }|j-                  |       ` t/        j0                  |  d{    t        j                  d        y|d!k(  rb| j	                  |      }| j                  j2                  j                  d"|d"   ii |i d       d{   }t        j                  d#       |S |d$k(  rb| j	                  |      }| j                  j4                  j                  d"|d"   ii |i d       d{   }t        j                  d%       |S y7 7 ># t        $ r*}	dt        |	      v rt        ddd|d    di      |	d}	~	ww xY w7 7 )7 7 `# t        $ r}	d&dl}d't        |	       }t        |       |d(z    |j8                         z   }t        j                          }||z
  }t/        j:                  | j<                  j?                  |	|d)|*             |	d}	~	ww xY ww)+zN
        Add a key to the database. If it already exists, do nothing.
        zPrismaClient: insert_data: %srZ   r  r  r   z:PrismaClient: Before upsert into litellm_verificationtokencreaterD  r  T)r  rL   r  NzData Inserted into Keys Tabler4  r  r  rL   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  rn  rA   r  r  upsertr  r  r   r   r   r   rG   rw   r  r  r  rF  r  r   r   gatherr  r  r8   r;   r   rz  r   )rU   rL   r  r3  r  r  rm  new_verification_tokennew_user_rowr   new_team_rowtasksrT  rU  updated_dataupdated_table_rownew_spend_rownew_user_notification_rowr8   r  r  r  r  s                          r@   r  zPrismaClient.insert_datag  s    " YY[
@	 &&'FMU"W#U;--4-8#/ P 04ww/P/P/W/W #.W+"$ 4T: 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 59JJ 455G01 &*WW%>%>%E%E$d9o6"-W+"$ &F &   %))*IJ##x'  JJLDAq#$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 3q	*$ ! vq6" ,(+ '+Z[bct[uZv  wD  *E$  G, > -!  	J3q6(SI)$'$.1E1E1E1GGOyy{H :-I&&66'(&+"1	 7  G!	s   PBN	  M!N	 ;P<N	 4M	 M	M	 N	 #P$BN	 /M?0N	 
PBN	 NN	 3P4AN	 ?N N	 PAN	 &N'N	 PN	 M	 		M<%M77M<<N	 N	 N	 N	 		PBPPPrD  	data_list)rD  update_many)r4  rZ   r  r  r  update_key_valuesupdate_key_values_custom_queryc
           	      b  K   t        j                  d|        t        j                         }
	 | j                  |      }|| j                  |      }|t	        d|        t        |      }||d<   | j                  j                  j                  d|ii |       d{   }t        j                  dd	| z   d
z          i }|	 |j                         }||dS ||v|dk(  rq|dk(  rl	 ||d   }||	|	}n|}| j                  j                  j                  d|ii |i |d       d{   }t        j                  dd| z   d
z          ||dS |||dk(  r|dk(  r	 ||d   }||}d|vr|||d<   d|v r.t        |d   t               rt#        j$                  |d         |d<   d|v r.t        |d   t               rt#        j$                  |d         |d<   | j                  j&                  j                  d|ii |i |d       d{   }t        j                  dd| z   d
z          ||dS ||dk(  r|dk(  r|t        |t               r	 | j                  j)                         }t+        |      D ]  \  }}|j,                  j/                  d      r!| j1                  |j,                        |_        	 | j                  |j                  d            }|j                  j                  d|j,                  ii |        |j3                          d{    t	        d       y||dk(  r|dk(  r|t        |t               r	 | j                  j)                         }t+        |      D ]X  \  }}	 | j                  |j                  d            }|j                  j                  d|j4                  ii |i |d       Z |j3                          d{    t        j                  d       y||dk(  r|dk(  r|t        |t               r| j                  j)                         }t+        |      D ]X  \  }}	 | j                  |j                  d            }|j&                  j                  d|j6                  ii |i |d       Z |j3                          d{    t        j                  d       yyyyyy7 3# t        $ r |j                         }Y w xY w7 7 # t        $ r& | j                  |j                  d            }Y Fw xY w7 
# t        $ r$ | j                  |j                               }Y w xY w7 z# t        $ r& | j                  |j                  d            }Y $w xY w7 # t        $ r}ddl}d t;        |       }t	        |       |d!z    |j<                         z   }t        j                         }||
z
  }t?        j@                  | jB                  jE                  ||d"|#             |d}~ww xY ww)$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   r4  rD  r  r	  z!DB User Table - update succeeded )r  rL   r  r  r  z!DB Team Table - update succeeded )r  rL   rZ   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  rn  rA   r  r  r  rD  
model_dumpr   rH   r  r  r  rG   rw   r  r  r  batch_	enumerater  r  r  commitr  r  r8   r   r;   r   r   rz  r   )rU   r  rL   r  r  r  r  r  r  r  r3  rm  r   _dataupdate_user_rowupdate_team_rowbatcheridxr   	data_jsonr4  r  r   r8   r  r  r  r  s                               r@   r!  zPrismaClient.update_data  sL    , 	""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 
 $+ODD#*zV/C(* ?%i0G$,(/%G+0C)0GI&'72z0148 59JJ 455G01 (+<<%&:;TB ?Cjj)*>??%&:; )-(A(A(H(H$g."-W+#/# )I ) # %))9/9JKL 
 $+ODD&%'-/)y$/ ''..*'	2FCww))%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)$'$.1E1E1E1GGOyy{H :-I&&66'(&+"1	 7  G!	sR  -X/A5V %S&&V S V !X/"AV 4S;5&V X/B<V S>&V ?X/ BV "T)A V )T3*V 9X/:A
V "T6'AV ,U&-V X/A	V "U)3AV 8V9V X/V S84V 7S88V >V +T0,V /T00V 6)U#V "U##V )+VV VV 	X,&BX''X,,X/tokensc           	        K   t        j                          }	 |t        |t              rg }|D ]I  }t        |t              r$|j	                  d      r| j                  |      }n|}|j                  |       K i }	|ddd|iid|igi}	ndd|ii}	| j                  j                  j                  |	       d{   }
t        j                  d	|
       d
|
iS |dk(  rH|Ft        |t              r6| j                  j                  j                  dd|ii       d{    d|iS |dk(  rG|Dt        |t              r3| j                  j                  j                  dd|ii       d{    yyyy7 7 W7 # t        $ r}ddl}dt        |       }t        |       |dz    |j                          z   }t        j                          }||z
  }t#        j$                  | j&                  j)                  ||d|             |d}~ww xY ww)za
        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_teamsrZ   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   rz  r   )rU   r,  r  r  r  r3  r  r  r  filter_querydeleted_tokensr   r8   r  r  r  r  s                    r@   r1  zPrismaClient.delete_data  sT    & YY[
9	!j&> "#E!%-%2B2B52I'+U'C',!((6 $ &(&4*? @9gBVW$L %,dM-B#CL'+ww'H'H'T'T& (U ( " %**+?P&77f$ ,|T2 gg//;;$t\&:; <    (66e# ,|T2 gg77CC$t\&:; D    3 - $!"  	I#a&RI)$'$.1E1E1E1GGOyy{H :-I&&66'(&+"1	 7  G!	sz   HB"E9 :E3;E9 HAE9 E5E9 %H&AE9 *E7+E9 /H3E9 5E9 7E9 9	HBHHHc           	      0  K   t        j                          }	 t        j                  d       | j                  j	                         du r8t        j                  d       | j                  j                          d {    y y 7 # t        $ r}dd l}dt        |       }t        |       |dz    |j                         z   }t        j                          }||z
  }t        j                  | j                  j                  ||d|             |d }~ww xY ww)	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_connectedr6  r   r8   r   rA   r;   r   r   rz  r   rU   r3  r   r8   r  r  r  r  s           r@   r6  zPrismaClient.connect5  s     YY[
	 &&L ww##%.$**Q ggoo'''	 / ( 	Ec!fXNI)$'$.1E1E1E1GGOyy{H :-I&&66'(&'"1	 7  G!	s<   DA#B ;B<B  DB 	DBDDDc           	        K   t        j                          }	 | j                  j                          d {    y 7 # t        $ r}dd l}dt        |       }t        |       |dz    |j                         z   }t        j                          }||z
  }t        j                  | j                  j                  ||d|             |d }~ww xY ww)Nr   .LiteLLM Prisma Client Exception disconnect(): r  
disconnectr  )r  r  r;  r   r8   r   rA   r;   r   r   rz  r   r8  s           r@   r;  zPrismaClient.disconnectZ  s      YY[
	''$$&&& 	HQQI)$'$.1E1E1E1GGOyy{H :-I&&66'(&*"1	 7  G!	s2   C= ;= C= 	CBCCCc           	        K   t        j                          }	 d}| j                  j                  |       d{   }|S 7 # t        $ r}ddl}dt        |       }t        |       |dz    |j                         z   }t        j                          }||z
  }	t        j                  | j                  j                  ||	d|             |d}~ww xY ww)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   rz  r   )
rU   r3  r  r   r   r8   r  r  r  r  s
             r@   r  zPrismaClient.health_checkw  s      YY[
	"I "WW..y99HO : 	HQQI)$'$.1E1E1E1GGOyy{H :-I&&66'(&,"1	 7  G!	s6   C A ?A CA 	C
BCCCc                    K   	 d}| j                   j                  |       d {   }|d   d   S 7 # t        $ r"}t        j                  d|        Y d }~yd }~ww xY ww)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   )rU   r  resultr   s       r@   _get_spend_logs_row_countz&PrismaClient._get_spend_logs_row_count  sn     	I
  77,,9,==F!9[)) > 	 &&=aSA 		s6   A"!4 24 A"4 	AAA"AA"c                 r   K   ddl m} | j                          d{   }|j                  d|       y7 w)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_namera   )litellm.proxy.proxy_serverrB  r@  set_proxy_state_variable)rU   rB  _num_spend_logs_rowss      r@   (_set_spend_logs_row_count_in_proxy_statez5PrismaClient._set_spend_logs_row_count_in_proxy_state  s<      	;%)%C%C%EE,,0& 	- 	
  Fs   757rS   )NNNNNNNr  NNNNNN)NNNN)rX   N),rs   rt   ru   rr  rH   rE  rs  rt  ru  rv  rw  rx  r	   r   rz   r   r   rV   r  rn  backoffon_exceptionexpor   ri  r  r,   r
   r  r   rw   r   intr6   r  r  r  r!  r1  r6  r;  r  r@  rH  r\   rB   r@   rq  rq    s   "$4$&(t(!#$#"$4$)+ $+!#$##%D% &*	"F"F ("F c]	"FH 
4 
D 
 WZZx W11 1 >?	1 1f W  -1!%'+!%'+"& 9F&*'+ $ +/487[c4i()[ #[ tn	[
 #[ tn[ $[ !

[& 56'[( (#)[* 8$+[, -[. 
/[4 #4.5[6 $L17[ [z
4  WKK I
KK\ W  $$(!%!%7?RV,09=_}_ _ D>	_
 #_ #_ 34_ W%MNO_ $D>_ )1__D W "&'+RV!%FF tnF W%MNO	F
 #FFR W< W,< 
rB   rq  ra   config_file_pathc                    | }d }	 | j                  d      }dj                  |d d       }|d   }|t        j                  j	                  |      }t        j                  j                  |g|j                  d       }|dz  }t
        j                  j                  ||      }|t        d|       t
        j                  j                  |      }|j                  j                  |       nt        j                  |      }t        ||      }	|	S # t        $ r}
|r|rt        d| d|       |
|
d }
~
wt        $ r}
|
d }
~
ww xY w)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   )ra   rM  module_nameinstance_nameparts	directorymodule_file_pathspecmoduleinstancer   s              r@   get_instance_fnrd    sS   KM&C  hhuSbz*b	 '(89I!ww||IO8I8I#8NO%>>99+GWXD|!@AQ@RS  ^^44T:FKK##F+ ,,[9F 6=1 [#M?&F G s$   DD 	ED44E EEr  r   r  c                 8  K   |  d}|j                  |      }|{|j                  |        d{   }|_t        d| dt        |              t	        |d      r9t        t        |d            r$|j                         }|j                  ||d	       y7 fw)
zE
    Check if a user_id exists in cache,
    if not retrieve it.
    _user_api_key_user_id)rZ   N)r  z
User Row: z	, type = model_dump_jsoniX  )rZ   ra   r   )	rq   r  rA   r   r   callabler&  rg  ro   )r  r   r  	cache_keyr   user_rowcache_values          r@   _cache_user_rowrl    s     
 )01I9-HW55Jxj	$x.9IJKx!23"349 '668!#     6s   /BBA'Bc                 <  K   t        j                  d      }t        t        j                  dd            }t        j                  d      }t        j                  d      }t        j                  dd      }|t        d      t	               }||d	<   | |d
<   ||d<   t        j                  d||        |t        d      |t        d      |t        d      |j                  t        |d             	 t        j                  ||      5 }	t        j                  dd      dk7  r|	j                          |	j                  ||       |	j                  |       ddd       y# 1 sw Y   yxY w# t        $ r!}
t        dt!        |
      z          Y d}
~
yd}
~
ww xY ww)zl
    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  rL  
ValueErrorr   r   r9   attachr   smtplibSMTPstarttlsloginsend_messager   rA   r   )receiver_emailsubjectrw  	smtp_host	smtp_portsmtp_usernamesmtp_passwordsender_emailemail_messageserverr   s              r@   
send_emailr    s{     		+&IBIIk512IIIo.MIIo.M990$7LOPP "OM(M&(M$&M)%|^ GHHKLLKLL $/0M\\)Y/6yyV,7! LL6 . 0//  MBSVKLLMsU   C4F7E/ AE#E/ "F#E,(E/ +F,E/ /	F8FFFFr  c                 j    dd l } |j                  | j                               j                         }|S )Nr   r  )r  r  r  s      r@   r  r  .	  s,     "7>>%,,.1;;=LrB   c                 @    | j                  d      rt        |       S | S )z`
    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  7	  s"     &&rB   prisma_clientc           	        K   | t        j                         }| j                  dd||       d{   }|bt        |      dkD  rT|D ]3  }d|_        t        |j                        }|t        |      z   |_        5 | j                  d	|d
       d{    t        j                         }| j                  dd|       d{   }|bt        |      dkD  rT|D ]3  }d|_        t        |j                        }|t        |      z   |_        5 | j                  d	|d
       d{    t        j                         }| j                  dd|       d{   }|t        |      dkD  rsg }|D ]O  }	t        |	j                        }t        |	j                  d|t        |      z   |      }
|j                  |
       Q | j                  d	|d
       d{    yyyy7 7 R7 %7 7 7 w)zv
    Gets all the non-expired keys for a db, which need spend to be reset

    Resets their spend

    Updates db
    NrZ   r  )r  r  r  r  r   g        )r  secondsr  )r  r  r  r4  )r  r  r  r  )r  r  r  
updated_at)r   utcnowr  r   r  r   budget_durationr   r  r!  r(   r  r   )r  r  keys_to_resetrZ   
duration_susers_to_resetr4  teams_to_resetteam_reset_requestsr  reset_team_budget_requests              r@   reset_budgetr  C	  s;      oo+44S3 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   0G4G%A#G4G(/G4G+A#G4*G.+/G4G0BG4G2	G4(G4+G4.G40G42G4db_writer_clientrz  c                   K   d}d}t        | j                  j                               dkD  rt        |dz         D ]  }t	        j                         }	 | j
                  j                  t        d            4 d{   }|j                         4 d{   }| j                  j                         D ](  \  }}	|j                  j                  d|id	d
|	ii       * ddd      d{    ddd      d{    i | _         n t#        j$                  dj'                  t        | j(                  j                                            t        | j(                  j                               dkD  rt        |dz         D ]  }t	        j                         }	 | j
                  j                  t        d            4 d{   }|j                         4 d{   }| j(                  j                         D ]@  \  }}	t*        j,                  	 |j.                  j1                  d|i||	ddd	d
|	iid       B ddd      d{    ddd      d{    i | _         n t#        j$                  dj'                  t        | j2                  j                                            t        | j2                  j                               dkD  rt        |dz         D ]  }t	        j                         }	 | j
                  j                  t        d            4 d{   }|j                         4 d{   }| j2                  j                         D ](  \  }}	|j4                  j                  d|id	d
|	ii       * ddd      d{    ddd      d{    i | _         n t#        j$                  dj'                  t        | j6                  j                                            t        | j6                  j                               dkD  rt        |dz         D ]  }t	        j                         }	 | j
                  j                  t        d            4 d{   }|j                         4 d{   }| j6                  j                         D ]M  \  }}	t#        j$                  dj'                  ||	             |j8                  j                  d|id	d
|	ii       O ddd      d{    ddd      d{    i | _         n t        | j:                  j                               dkD  rt        |dz         D ]  }t	        j                         }	 | j
                  j                  t        d            4 d{   }|j                         4 d{   }| j:                  j                         D ]Q  \  }}	|j=                  d      d   }|j=                  d      d   }|j>                  j                  ||dd	d
|	ii       S ddd      d{    ddd      d{    i | _         n t        | j@                  j                               dkD  rt        |dz         D ]  }t	        j                         }	 | j
                  j                  t        d            4 d{   }|j                         4 d{   }| j@                  j                         D ](  \  }}	|jB                  j                  d|id	d
|	ii       * ddd      d{    ddd      d{    i | _          n t#        j$                  dj'                  t        | jD                                     d}d}t        | jD                        dkD  rt        |dz         D ]  }t	        j                         }	 tG        jH                  dd      }t        | jD                        dkD  r|||jK                  d      s|dz  }t#        j$                  dj'                  |             |jM                  |d z   tO        jP                  | jD                        d!d"i#       d{   }|jR                  d$k(  rg | _"         y| jD                  d| }t        dt        |      |      D ]{  }||||z    }|D cg c]  }| jU                  i |       }}| j
                  jV                  jY                  |d%&       d{    t#        j$                  d't        |       d(       } | jD                  t        |      d | _"        t#        j$                  t        |       d)t        | jD                                 y yy7 	7 7 # 1 d{  7  sw Y   xY w7 # 1 d{  7  sw Y   xY w# t        $ r?}
||k\  rt        |
||       t        j                  d|z         d{  7   Y d}
~
	d}
~
wt         $ r}
t        |
||       Y d}
~
	d}
~
ww xY w7 f7 P7 # 1 d{  7  sw Y   xY w7 # 1 d{  7  sw Y    xY w# t        $ r?}
||k\  rt        |
||       t        j                  d|z         d{  7   Y d}
~
	#d}
~
wt         $ r}
t        |
||       Y d}
~
	Cd}
~
ww xY w7 7 7 A# 1 d{  7  sw Y   RxY w7 J# 1 d{  7  sw Y   [xY w# t        $ r?}
||k\  rt        |
||       t        j                  d|z         d{  7   Y d}
~
fd}
~
wt         $ r}
t        |
||       Y d}
~
d}
~
ww xY w7 7 7 v# 1 d{  7  sw Y   xY w7 # 1 d{  7  sw Y   xY w# t        $ r?}
||k\  rt        |
||       t        j                  d|z         d{  7   Y d}
~
d}
~
wt         $ r}
t        |
||       Y d}
~
d}
~
ww xY w7 }7 g7 # 1 d{  7  sw Y   xY w7 # 1 d{  7  sw Y   xY w# t        $ r?}
||k\  rt        |
||       t        j                  d|z         d{  7   Y d}
~
:d}
~
wt         $ r}
t        |
||       Y d}
~
Zd}
~
ww xY w7 7 7 # 1 d{  7  sw Y   xY w7 # 1 d{  7  sw Y   xY w# t        $ r?}
||k\  rt        |
||       t        j                  d|z         d{  7   Y d}
~
d}
~
wt         $ r}
t        |
||       Y d}
~
d}
~
ww xY w7 c c}w 7 [# t        $ rC}
|d}||k\  rt        |
||       t        j                  d|z         d{  7   Y d}
~
d}
~
wt         $ r}
t        |
||       Y d}
~
d}
~
ww xY ww)*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   r3  rz  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   rr  ri   ranger  r  txr   r#  rF  r  r  r   $_raise_failed_update_spend_exceptionr   sleepr   r   r9   r:   rs  r<   max_end_user_budgetlitellm_endusertabler  rt  r  ru  r  rv  rQ  litellm_teammembershiprw  litellm_organizationtablerx  r  r  endswithpostr  r  r   rn  r  create_many)r  r  rz  n_retry_timesir3  transactionr)  r  response_costr   end_user_idr  r  rZ   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F29g&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 C(..~/D/DX/NO%5%:%:$~5!ZZ(L(LM!/1C D &; &  H
  ++s2?A<D A '4&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3     - *%8
FW mmAqD))) 4JBS   43333   4 - *%8
FW mmAqD))) 4JBS   43333     - *%8
FW mmAqD))) 4JBS   43333   * - *%8
FW mmAqD))) 4JBS   43333   ( - *%8
FW mmAqD))) 4JBS   43333     - *%8
FW mmAqD))) 4JBS 6  ,  - *9A&8
FW
 mmAqD))) 4JBS s  Aw*g =f>g f*f
f*Af f*+f,f*0g ;f'<g Bw*i#h+i#	ih.
i"Ah4 ih1ii#i
i#'Bw;*l%k&l)k0>k
?k0Akk0kk0l#k-$l/Bw*n).m1/n)2nm4
nA+m:6nm7nn)nn)Aw-*qpqp60p
1p64A/p#p6.p/p63q>p3?q
Aw*s/r7s/sr:
s As &s1r=2s6s/ss/A=wB%u%0u1u%w4u%u,u%u"A;u%wg f*f*f$ff$f*'g *f=	0f31f=	8g  	h(	.h7g:8h=wh(h#w#h((w+i#.i1i4i:h=;ii
i#i 	ii 	i##	k,.j&jj& w&k2k wkwlk0k0k*k k*%k0-l0l	6k97l	>l	m..m	=m >m	w	m.m)#w)m..w1n)4n7n:n nnnn)n&	nn&	!n))	p2.o, o#!o,&w,p8pwpwqp6p6p0#p&$p0+p63q6q		<p?=q		q	r4.rrr	wr4r/)w/r44w7s/:s=s ss	sss/s,	s" s,	's//	u8.t2&t)'t2,w2u>uwuwu%u%%	w.2v, v#!v,&w,w8wwwwr   r3  c                     ddl }dt        |        }|dz    |j                         z   }t        j                         }||z
  }t	        j
                  |j                  | |d|             | )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   r   )r   r3  rz  r8   r  r  r  r  s           r@   r  r  
  s      NcRSfXV   $&)=)=)=)??Oyy{H:%I)) $)	 	* 	
 GrB   current_spendsoft_budget_limitc                    ddl m} |y|j                         }|j                  dk(  r% ||j                  dz   dd      t        d      z
  }n. ||j                  |j                  dz   d      t        d      z
  }||z
  j                  }|j                  dk(  r| }n| |j                  dz
  z  }| ||z  z   }||kD  rt        d       yy)	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                 X   dd l }|y |j                  j                         } |j                  |j                  |j                  dz   d       |j
                  d      z
  }||z
  j                  }| |j                  dz
  z  }||z  }||kD  r||z  }| |j
                  |      z   }	||	fS y )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@RA I  %'--N		AK "N2O**'+5!$6H$6$6K$HH  111rB   c           	      x    | ||y d|v r/|j                  d      }|d   }||vrt        d|  d| d| d      y )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  ,  sm    +-1E;"x0'0</)'"5E4FFdeqdrrtu  rB   c                 :    t        | j                         dz        S )Ng    eA)rL  	timestamp)dts    r@   _to_nsr  :  s    r||~#$$rB   c                    d}t        | t              rt        | j                  t              r| j                  }|S t        | j                  t              r!t        j                  | j                        }|S t        | d      rHt        | dd       }t        |t              r|}|S t        |t              r"t        j                  |      }|S t        |       }|S t        |       }|S )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                  .    t        j                  dd      S )z
    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  R  s     99[(++rB   c                  l    t        j                  dd      } | r| S t        j                  dd      dk(  ryy)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_DOCSrz  ry  r  r  )docs_urls    r@   _get_docs_urlr  \  s7     yyT*H	yyG$. rB   c           
      x   ddl m} t        | t              rUt	        t        | ddt        |        d      t        j                  t        | dd      t        | d|j                        	      S t        | t              r| S t	        d
t        |       z   t        j                  t        | dd      |j                  	      S )zg
    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  o  s     !]#Ax6#a&);< 66!Wf-M6+P+PQ	
 	
 
A~	&)CF222a&)22	 rB   rS   )NNN)zr   rJ   r  rT  r  r  r}  rM  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   rI  rW  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   rz   ri  rH   rn  rq  r   rd  rl  r  r  r  r  r  r   rx   r  r  tupler  r  r  r  r  r  r  r\   rB   r@   <module>r     si        	     ( . $ 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d dTJ

 
$ 
T
 T
p$)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} & ~ mZ  
O s    G G&