
    g-                         d Z ddlZddlZddlmZmZmZ ddlmZmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZmZmZmZ ddlmZmZ dZdZ dZ!dZ" G d de      Z#y)z
PagerDuty Alerting Integration

Handles two types of alerts:
- High LLM API Failure Rate. Configure X fails in Y seconds to trigger an alert.
- High Number of Hanging LLM Requests. Configure X hangs in Y seconds to trigger an alert.
    N)datetime	timedeltatimezone)ListLiteralOptionalUnion)verbose_logger)	DualCache)SlackAlerting)AsyncHTTPHandlerget_async_httpx_clienthttpxSpecialProvider)UserAPIKeyAuth)AlertingConfigPagerDutyInternalEventPagerDutyPayloadPagerDutyRequestBody)StandardLoggingPayload&StandardLoggingPayloadErrorInformation<   iX  c                        e Zd ZdZ	 ddeeeef      f fdZd Z	de
dededed	   d
eeeeef      f
dZdee   de
fdZdee   dededefdZ	 ddee   ded
ee   fdZdedefdZ xZS )PagerDutyAlertingz
    Tracks failed requests and hanging requests separately.
    If threshold is crossed for either type, triggers a PagerDuty alert.
    alerting_argsc           	         ddl m}m} t        |           t        j                  d      }|st        d      || _        |xs i }t        |j                  dt              |j                  dt              |j                  dt              |j                  dt              	      | _        g | _        g | _        |d
ur"t        d|j$                  j&                         y )Nr   )CommonProxyErrorspremium_userPAGERDUTY_API_KEYzPAGERDUTY_API_KEY is not setfailure_threshold failure_threshold_window_secondshanging_threshold_seconds hanging_threshold_window_seconds)r   r    r!   r"   TzBPagerDutyAlerting is only available for LiteLLM Enterprise users. )litellm.proxy.proxy_serverr   r   super__init__osgetenv
ValueErrorapi_keyr   get#PAGERDUTY_DEFAULT_FAILURE_THRESHOLD2PAGERDUTY_DEFAULT_FAILURE_THRESHOLD_WINDOW_SECONDS+PAGERDUTY_DEFAULT_HANGING_THRESHOLD_SECONDS2PAGERDUTY_DEFAULT_HANGING_THRESHOLD_WINDOW_SECONDSr   _failure_events_hanging_eventsnot_premium_uservalue)selfr   kwargsr   r   _api_key	__class__s         ]/var/www/openai/venv/lib/python3.12/site-packages/litellm/integrations/pagerduty/pagerduty.pyr%   zPagerDutyAlerting.__init__.   s     	O9901;<<$%+-;+//#%H .;->->2B. '4&7&7+-X' .;->->2B..
$ >@=? t#TUfUwUwU}U}T~  $    c                 0  K   t        j                  t        j                        }|j	                  d      }|st        d      |j	                  d      xs i }|j	                  d      xs i }| j                  j                  t        d||j	                  d      |j	                  d      |j	                  d      |j	                  d	      |j	                  d
      |j	                  d      |j	                  d      |j	                  d      |j	                  d      |j	                  d                   | j                  j	                  dd      }	| j                  j	                  dd      }
| j                  | j                  |	|
d       d{    y7 w)z
        Record a failure event. Only send an alert to PagerDuty if the
        configured *failure* threshold is exceeded in the specified window.
        standard_logging_objectz9standard_logging_object is required for PagerDutyAlertingerror_informationmetadatafailed_responseerror_class
error_codellm_provideruser_api_key_hashuser_api_key_aliasuser_api_key_org_iduser_api_key_team_iduser_api_key_user_iduser_api_key_team_aliasuser_api_key_end_user_idfailure_event_type	timestampr>   r?   error_llm_providerrA   rB   rC   rD   rE   rF   rG   r    r   r      zHigh LLM API Failure Rateeventswindow_seconds	thresholdalert_prefixN)r   nowr   utcr*   r(   r/   appendr   r   !_send_alert_if_thresholds_crossed)r3   r4   response_obj
start_timeend_timerR   standard_logging_payload
error_info_metarO   rP   s              r7   async_log_failure_eventz)PagerDutyAlerting.async_log_failure_eventW   s{    
 ll8<<(EKZZ%F
  (K  %(()<=C 	 ),,Z8>B##"#4&NN=9%>>,7#->>.#A"')),?"@#(99-A#B$)II.C$D%*YY/E%F%*YY/E%F(-		2K(L).3M)N	
$ ++//0RTVW&&**+>B	 44'')4	 5 
 	
 	
s   FFFFuser_api_key_dictcachedata	call_type)
completiontext_completion
embeddingsimage_generation
moderationaudio_transcriptionpass_through_endpointrerankreturnc                    K   t        j                  d       t        j                  | j	                  ||             yw)z
        Example of detecting hanging requests by waiting a given threshold.
        If the request didn't finish by then, we treat it as 'hanging'.
        z#Inside Proxy Logging Pre-call hook!)request_datar]   N)r
   infoasynciocreate_taskhanging_response_handler)r3   r]   r^   r_   r`   s        r7   async_pre_call_hookz%PagerDutyAlerting.async_pre_call_hook   sC     ( 	AB))!5F * 	

 s   =?rk   c                 2  K   t        j                  d| j                  j                  dt               d       t        j                  | j                  j                  dt                     d{    | j                  |       d{   ry| j                  j                  t        dt        j                  t        j                        ddd|j                  |j                   |j"                  |j$                  |j&                  |j(                  |j*                               | j                  j                  d	t,              }| j                  j                  d
t              }| j/                  | j                  ||d       d{    y7 7 7 w)z
        Checks if request completed by the time 'hanging_threshold_seconds' elapses.
        If not, we classify it as a hanging request.
        z/Inside Hanging Response Handler!..sleeping for r!   z secondsN)rk   hanging_responseHangingRequestrH   r"   hanging_threshold_failsz#High Number of Hanging LLM RequestsrM   )r
   debugr   r*   r-   rm   sleep_request_is_completedr0   rT   r   r   rR   r   rS   r)   	key_aliasorg_idteam_iduser_id
team_aliasend_user_idr.   rU   )r3   rk   r]   rO   rP   s        r7   ro   z*PagerDutyAlerting.hanging_response_handler   s     	=d>P>P>T>TUp  s^  ?_  >`  `h  i	
 mm""+-X
 	
 	
 +++FFF 	##"#5",,x||4,+#3"3";";#4#>#>$5$<$<%6%>%>%6%>%>(9(D(D):)F)F	
$ ++//.>
 ++//%'R
	
 44'')>	 5 
 	
 	
K	
 G>	
s7   A.F0F1F
FC>F	F
FFFrN   rO   rP   rQ   c                 :  K   t        j                  t        j                        t	        |      z
  }|D cg c](  }|j                  dt         j                        |kD  s'|* }}|j                          |j                  |       t        j                  dt        |       d| d|        t        |      |k\  rW| j                  |d      }| dt        |       d	| d
}	d|i}
| j                  |	|
       d{    |j                          yyc c}w 7 w)z
        1. Prune old events
        2. If threshold is reached, build alert, send to PagerDuty
        3. Clear those events
        )secondsrJ   zHave z events in the last z seconds. Threshold is    )
max_errorsz: z in the last z	 seconds.recent_errors)alert_messagecustom_detailsN)r   rR   r   rS   r   r*   minclearextendr
   ru   len_build_error_summariessend_alert_to_pagerduty)r3   rN   rO   rP   rQ   cutoffeprunederror_summariesr   r   s              r7   rU   z3PagerDutyAlerting._send_alert_if_thresholds_crossed   s!     hll+i.OO#QVquu[(,,'G&'P!VQ 	f 	CK= 4^4DD[\e[fg	
 v;)#"99&Q9OO.3v;-}^<LIV  .?N..+- /    LLN $ R$s#   5D(D D$BD=D>Dr   c                 h    || d }g }|D ]$  }|j                  d       |j                  |       & |S )z
        Build short text summaries for the last `max_errors`.
        Example: "ValueError (code: 500, provider: openai)"
        NrJ   )poprT   )r3   rN   r   recent	summariesfes         r7   r   z(PagerDutyAlerting._build_error_summaries  sC     %	BFF;R   r8   r   r   c           	      j  K   	 t        j                  d|        t        t        j                        }t        t        |ddd|      | j                  d      }|j                  d	t        |      d
di       d{   S 7 # t        $ r"}t        j                  d|        Y d}~yd}~ww xY ww)z
        Send [critical] Alert to PagerDuty

        https://developer.pagerduty.com/api-reference/YXBpOjI3NDgyNjU-pager-duty-v2-events-api
        zSending alert to PagerDuty: )r@   criticalzLiteLLM AlertLiteLLM)summaryseveritysource	componentr   trigger)payloadrouting_keyevent_actionz'https://events.pagerduty.com/v2/enqueuezContent-Typezapplication/json)urljsonheadersNz"Error sending alert to PagerDuty: )r
   ru   r   r   LoggingCallbackr   r   r)   postdict	Exception	exception)r3   r   r   async_clientr   r   s         r7   r   z)PagerDutyAlerting.send_alert_to_pagerduty  s     	O  #?!OP-C1AA.L -A()'*'#1 !LL&
-G &**=']');< +    
  	O$$'I!%MNN	OsA   B3A:B >B?B B3B 	B0B+&B3+B00B3)N)r   )__name__
__module____qualname____doc__r   r	   r   r   r%   r\   r   r   r   r   strrp   ro   r   r   intrU   r   r   __classcell__)r6   s   @r7   r   r   (   s    FJ%%eND,@&AB%R/
b)  	
 	
 
%	3,-	.84
$TN4
?M4
p%+,% % 	%
 %P GH12@C	$	%O3 OPT Or8   r   )$r   rm   r&   r   r   r   typingr   r   r   r	   litellm._loggingr
   litellm.cachingr   1litellm.integrations.SlackAlerting.slack_alertingr   &litellm.llms.custom_httpx.http_handlerr   r   r   litellm.proxy._typesr   $litellm.types.integrations.pagerdutyr   r   r   r   litellm.types.utilsr   r   r+   r,   r-   r.   r    r8   r7   <module>r      so     	 2 2 1 1 + % K 
 0 
 ') #57 2.0 +58 2GO GOr8   