
    g@                         d 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 ddlmZm	Z	m
Z
mZ ddlmZ ddlZddlmZ ddlmZ ddlmZmZmZ dd	l dd
lmZ ddlmZ dZ G d de      Zy)ay  
DataDog Integration - sends logs to /api/v2/log

DD Reference API: https://docs.datadoghq.com/api/latest/logs

`async_log_success_event` - used by litellm proxy to send logs to datadog
`log_success_event` - sync version of logging to DataDog, only used on litellm Python SDK, if user opts in to using sync functions

async_log_success_event:  will store batch of DD_MAX_BATCH_SIZE in memory and flush to Datadog once it reaches DD_MAX_BATCH_SIZE or every 5 seconds

async_service_failure_hook: Logs failures from Redis, Postgres (Adjacent systems), as 'WARNING' on DataDog

For batching specific details see CustomBatchLogger class
    N)datetime)AnyListOptionalUnion)Response)verbose_logger)CustomBatchLogger)_get_httpx_clientget_async_httpx_clienthttpxSpecialProvider)*)ServiceLoggerPayload)StandardLoggingPayload  c                       e Zd Z fdZd Zd Zd Zd Zd Zde	e
ef   ded	ej                  d
ej                  def
dZdedefdZ	 	 	 	 	 ddedee   dee   d	ee	eef      d
ee	eef      dee
   fdZ	 	 	 	 	 ddedee   dee   d	ee	eef      d
ee	eef      dee
   fdZde	e
ef   ded	ej                  d
ej                  def
dZed        Zed        Zed        Zed        Zed        Zed        Z  xZ!S )DataDogLoggerc                 D   	 t        j                  d       t        j                  dd      t	        d      t        j                  dd      t	        d      t        t        j                        | _        t        j                  d      | _	        dt        j                  d       d	| _
        t        j                  d
      xs, t        j                  d      xs t        j                  d      }|
| d	| _
        t               | _        t        j                  | j                                t        j                          | _        t%        | L  di || j"                  t(        d y# t        $ r(}t        j*                  dt-        |              |d}~ww xY w)z
        Initializes the datadog logger, checks if the correct env variables are set

        Required environment variables:
        `DD_API_KEY` - your datadog api key
        `DD_SITE` - your datadog site, example = `"us5.datadoghq.com"`
        zDatadog: in init datadog logger
DD_API_KEYNz)DD_API_KEY is not set, set 'DD_API_KEY=<>DD_SITEz+DD_SITE is not set in .env, set 'DD_SITE=<>)llm_providerzhttps://http-intake.logs.z/api/v2/logs_DATADOG_BASE_URLDATADOG_BASE_URLDD_BASE_URL)
flush_lock
batch_sizez.Datadog: Got exception on init Datadog client  )r	   debugosgetenv	Exceptionr   r   LoggingCallbackasync_clientr   
intake_urlr   sync_clientasynciocreate_taskperiodic_flushLockr   super__init__DD_MAX_BATCH_SIZE	exceptionstr)selfkwargsdd_base_urle	__class__s       Y/var/www/openai/venv/lib/python3.12/site-packages/litellm/integrations/datadog/datadog.pyr+   zDataDogLogger.__init__+   sk   #	  !BCyyt,4 KLLyyD)1 MNN 61AA!D !ii5DO+BIIi,@+AN O 		-. ,99/0,99]+ 
 &%0M">02D 3 3 56%llnDOG %)__AR  	$$@QI G		s   E*E. .	F7#FFc                   K   	 t        j                  d|       | j                  ||||       d{    y7 # t        $ r@}t        j                  dt        |       dt        j                                 Y d}~yd}~ww xY ww)aF  
        Async Log success events to Datadog

        - Creates a Datadog payload
        - Adds the Payload to the in memory logs queue
        - Payload is flushed every 10 seconds or when batch size is greater than 100


        Raises:
            Raises a NON Blocking verbose_logger.exception if an error occurs
        7Datadog: Logging - Enters logging function for model %sNDatadog Layer Error - 
r	   r   _log_async_eventr!   r-   r.   	traceback
format_excr/   r0   response_obj
start_timeend_timer2   s         r4   async_log_success_eventz%DataDogLogger.async_log_success_event[   sz     
	  I6 ''j(SSS 	$$(Q93G3G3I2JK 		7   B-9 79 B9 	B6A=8B=BBc                   K   	 t        j                  d|       | j                  ||||       d {    y 7 # t        $ r@}t        j                  dt        |       dt        j                                 Y d }~y d }~ww xY ww)Nr6   r7   r8   r9   r=   s         r4   async_log_failure_eventz%DataDogLogger.async_log_failure_events   sz     
	  I6 ''j(SSS 	$$(Q93G3G3I2JK 		rB   c                   K   	 | j                   st        j                  d       yt        j                  dt	        | j                         | j
                         | j                  | j                          d{   }|j                  dk(  r.t        j                  t        j                  j                         y|j                          |j                  dk7  r%t        d|j                   d|j                         t        j                  d|j                  |j                         y7 # t        $ r@}t        j                  d	t        |       d
t        j                                  Y d}~yd}~ww xY ww)z
        Sends the in memory logs queue to datadog api

        Logs sent to /api/v2/logs

        DD Ref: https://docs.datadoghq.com/api/latest/logs/

        Raises:
            Raises a NON Blocking verbose_logger.exception if an error occurs
        z!Datadog: log_queue does not existNz(Datadog - about to flush %s events on %si     'Response from datadog API status_code: , text: <Datadog: Response from datadog API status_code: %s, text: %sz"Datadog Error sending batch API - r8   )	log_queuer	   r-   r   lenr$   async_send_compressed_datastatus_code	DD_ERRORSDATADOG_413_ERRORvalueraise_for_statusr!   textr.   r;   r<   )r/   responser2   s      r4   async_send_batchzDataDogLogger.async_send_batch   s>    	>>(()LM  :DNN# "<<T^^LLH##s*(()D)D)J)JK%%'##s*=h>R>R=SS[\d\i\i[jk    N$$ M   	$$4SVHBy?S?S?U>VW 	sY   E8!D, E8AD, 8D*9A D, 9E8:A/D, )E8*D, ,	E556E0+E80E55E8c                 ^   	 t         j                  du r| j                  ||||      }n| j                  ||||      }| j                  j                  | j                  |d| j                  i      }|j                          |j                  dk7  r%t        d|j                   d|j                         t        j                  d|j                  |j                         y# t        $ r@}t        j                  d	t        |       d
t!        j"                                 Y d}~yd}~ww xY w)z
        Sync Log success events to Datadog

        - Creates a Datadog payload
        - instantly logs it on DD API
        Tr0   r>   r?   r@   
DD-API-KEY)urljsonheadersrF   rG   rH   rI   r7   r8   N)litellmdatadog_use_v1_create_v0_logging_payloadcreate_datadog_logging_payloadr%   postr$   r   rQ   rM   r!   rR   r	   r   r-   r.   r;   r<   )r/   r0   r>   r?   r@   
dd_payloadrS   r2   s           r4   log_success_eventzDataDogLogger.log_success_event   sF   (	%%-!<<!!-)%	 = 
 "@@!!-)%	 A 
 '',,OO $// - H %%'##s*=h>R>R=SS[\d\i\i[jk    N$$ 	  	$$(Q93G3G3I2JK 	s   C C# #	D,,6D''D,c                 ,  K   | j                  ||||      }| j                  j                  |       t        j                  d| j
                   d       t        | j                        | j                  k\  r| j                          d {    y y 7 w)NrV   z-Datadog, event added to queue. Will flush in z seconds...)	r^   rJ   appendr	   r   flush_intervalrK   r   rT   )r/   r0   r>   r?   r@   r`   s         r4   r:   zDataDogLogger._log_async_event   s     88%!	 9 

 	j);D<O<O;PP[\	
 t~~$//1''))) 2)s   B	BBBr0   r>   r?   r@   returnc                    ddl }|j                  dd      }|t        d      t        j                  }|j                  d      dk(  rt        j
                  }| j                  |       |j                  |t              }t        j                  d|       t        | j                         | j                         | j                         || j                         |	      }	|	S )
a  
        Helper function to create a datadog payload for logging

        Args:
            kwargs (Union[dict, Any]): request kwargs
            response_obj (Any): llm api response
            start_time (datetime.datetime): start time of request
            end_time (datetime.datetime): end time of request

        Returns:
            DatadogPayload: defined in types.py
        r   Nstandard_logging_objectz+standard_logging_object not found in kwargsstatusfailuredefault&Datadog: Logger - Logging payload = %sddsourceddtagshostnamemessageservicerh   )rY   get
ValueErrorDataDogStatusINFOERROR)truncate_standard_logging_payload_contentdumpsr.   r	   r   DatadogPayload_get_datadog_source_get_datadog_tags_get_datadog_hostname_get_datadog_service)
r/   r0   r>   r?   r@   rY   rg   rh   json_payloadr`   s
             r4   r^   z,DataDogLogger.create_datadog_logging_payload   s    & 	DJJJ%tE
 #*JKK##"&&x0I="((F 	667NOzz"93zGE|T#--/))+//1 --/

     datac                   K   ddl }ddl}|j                  |j                  |t              j                  d            }| j                  j                  | j                  || j                  ddd       d{   }|S 7 w)	a;  
        Async helper to send compressed data to datadog self.intake_url

        Datadog recommends using gzip to compress data
        https://docs.datadoghq.com/api/latest/logs/

        "Datadog recommends sending your logs compressed. Add the Content-Encoding: gzip header to the request when sending"
        r   Nrj   zutf-8gzipzapplication/json)rW   zContent-EncodingzContent-Type)rX   r   rZ   )
r   rY   compressry   r.   encoder#   r_   r$   r   )r/   r   r   rY   compressed_datarS   s         r4   rL   z(DataDogLogger.async_send_compressed_data  s|      	--

4
(E(L(LW(UV**// "oo$* 2 0 
 
 
s   A7B9B :Bpayloaderrorparent_otel_spanevent_metadatac                 4  K   	 ddl }|j                         }|j                  |t              }	t	        ddd|	dt
        j                        }
| j                  j                  |
       y# t        $ r"}t        j                  d|        Y d}~yd}~ww xY ww)	z
        Logs failures from Redis, Postgres (Adjacent systems), as 'WARNING' on DataDog

        - example - Redis is failing / erroring, will be logged on DataDog
        r   Nrj   r[    litellm-serverrm   z;Datadog: Logger - Exception in async_service_failure_hook: )rY   
model_dumpry   r.   rz   ru   WARNrJ   rc   r!   r	   r-   )r/   r   r   r   r?   r@   r   rY   _payload_dict_dd_message_str_dd_payloadr2   s               r4   async_service_failure_hookz(DataDogLogger.async_service_failure_hook5  s     	#..0M"jjjDO("'($))K NN!!+. 		  	$$MaSQ  			s/   BA%A* )B*	B3BBBBc                    K   yw)z
        Logs success from Redis, Postgres (Adjacent systems), as 'INFO' on DataDog

        No user has asked for this so far, this might be spammy on datatdog. If need arises we can implement this
        Nr   )r/   r   r   r   r?   r@   r   s          r4   async_service_success_hookz(DataDogLogger.async_service_success_hookZ  s      	s   c                    ddl }|j                  di       }|j                  di       xs i }|j                  d      }|j                  di       }	|j                  dd      }
|j                  d	d
      }|d   }|j                  dt        t        j                                     }t        |      }	 ||z
  j                         dz  }	 t        |      }i }t        |t
              r"|j                         D ]  \  }}|dv r|||<    ||
|||||j                  dd      |j                  dd      |	|j                  dd      ||||d}|j                  |t              }t        j                  d|       t        | j                         | j                         | j!                         || j#                         t$        j&                        }|S # t        $ r d}Y w xY w# t        $ r |}Y w xY w)z
        Note: This is our V1 Version of DataDog Logging Payload


        (Not Recommended) If you want this to get logged set `litellm.datadog_use_v1 = True`
        r   Nlitellm_paramsmetadatamessagesoptional_params	call_typezlitellm.completion	cache_hitFusageidr   )endpointcaching_groupsprevious_modelsmodelr   userresponse_cost)r   r   r   r?   r@   response_timer   r   model_parametersspendr   rS   r   r   rj   rl   rm   )rY   rs   r.   uuiduuid4dicttotal_secondsr!   
isinstanceitemsry   r	   r   rz   r{   r|   r}   r~   ru   rv   )r/   r0   r>   r?   r@   rY   r   r   r   r   r   r   r   r   r   clean_metadatakeyrP   r   r   r`   s                        r4   r]   z(DataDogLogger._create_v0_logging_payloadj  s    	$4b9z2.4" 	 ::j) **%6;JJ{,@A	JJ{E2	W%dC

$56U	!%
2AACdJM	(-L h%&nn.
U  
 */N3' / ""$ *ZZ,JJvr* /ZZ3 $&
" zz'3z7E|T#--/))+//1 --/ %%

 m  	! M	!
  	('L	(s$   2G 	G! GG!G0/G0c                      dt        j                  dd       dt        j                  dd       dt        j                  dd       d	t        j                          d
t        j                  dd       
S )Nzenv:DD_ENVunknownz	,service:
DD_SERVICEr[   z	,version:
DD_VERSIONz
,HOSTNAME:z
,POD_NAME:POD_NAME)r   r    r   r}   r   r   r4   r|   zDataDogLogger._get_datadog_tags  s    bii)45YryyW`?a>bbklnlulu  wC  EN  mO  lP  PZ  [h  [~  [~  [@  ZA  AK  LN  LU  LU  V`  bk  Ll  Km  n  	nr   c                  .    t        j                  dd      S )N	DD_SOURCEr[   r   r    r   r   r4   r{   z!DataDogLogger._get_datadog_source  s    yyi00r   c                  .    t        j                  dd      S )Nr   r   r   r   r   r4   r~   z"DataDogLogger._get_datadog_service  s    yy'788r   c                  .    t        j                  dd      S )NHOSTNAMEr   r   r   r   r4   r}   z#DataDogLogger._get_datadog_hostname  s    yyR((r   c                  .    t        j                  dd      S )Nr   r   r   r   r   r4   _get_datadog_envzDataDogLogger._get_datadog_env  s    yy9--r   c                  .    t        j                  dd      S )Nr   r   r   r   r   r4   _get_datadog_pod_namez#DataDogLogger._get_datadog_pod_name  s    yyY//r   )r   NNNN)"__name__
__module____qualname__r+   rA   rD   rT   ra   r:   r   r   r   r   rz   r^   r   r   rL   r   r   r.   datetimeObjfloatr   r   r]   staticmethodr|   r{   r~   r}   r   r   __classcell__)r3   s   @r4   r   r   )   sB   .`0)V0d*"-dCi - - %%	-
 ##- 
-^T h 6  "*.:>8<)-#%# }# #3-	#
 U;#567# 5!345# !#P  "*.:>8<)-% } #3-	
 U;#567 5!345 ! RdCi R R %%	R
 ##R 
Rh n n 1 1 9 9 ) ) . . 0 0r   r   )__doc__r&   r   r   r;   r   r   typingr   r   r   r   httpxr   r[   litellm._loggingr	   (litellm.integrations.custom_batch_loggerr
   &litellm.llms.custom_httpx.http_handlerr   r   r   "litellm.types.integrations.datadoglitellm.types.servicesr   litellm.types.utilsr   r,   r   r   r   r4   <module>r      sZ      	   , - -   + F 
 1 7 6 k0% k0r   