
    AHj0K                         d 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 ddlmZ ddlmZ ddlmZmZ dd	lmZmZmZ dd
lmZmZ ddlmZmZ  G d de      Zy)ao  
PostHog Integration - sends LLM analytics events to PostHog

Follows PostHog's LLM Analytics format: https://posthog.com/docs/llm-analytics/manual-capture

async_log_success_event: stores batch of events in memory and flushes to PostHog
async_log_failure_event: logs failed LLM calls with error information

For batching specific details see CustomBatchLogger class
    N)AnyDictOptionalTuple)verbose_logger)uuid)CustomBatchLogger)
safe_dumps)should_use_posthog_mockcreate_mock_posthog_client)_get_httpx_clientget_async_httpx_clienthttpxSpecialProvider)POSTHOG_MAX_BATCH_SIZEPostHogEventPayload)StandardCallbackDynamicParamsStandardLoggingPayloadc            
           e Zd Z fdZd Zd Zd Z	 ddZdee	e
f   defdZd	edee	e
f   d
e	dee	e
f   fdZdee	e
f   dee	e
f   fdZdee	e
f   dee	e
f   fdZd	edee	e
f   de	fdZdee	e
f   deee	   ee	   f   fdZd Zd Zdee	e
f   dee	e
f   fdZde	fdZdede	dee	e
f   fdZdde
de	de
de
fdZd Z xZS )PostHogLoggerc                    	 t        j                  d       t               | _        | j                  rt	                t        j                  d       t        j                  dd      t        d      t        t        j                        | _        t               | _        t        j                  d      | _        t        j                  dd      }|j                  d	      | _        | j                    d
| _        d| _        d| _        g | _        t+        j,                  | j.                         t1        | d  di |dt4        d y# t        $ r(}t        j6                  dt9        |              |d}~ww xY w)a  
        Initializes the PostHog logger, checks if the correct env variables are set

        Required environment variables:
        `POSTHOG_API_KEY` - your PostHog API key
        `POSTHOG_API_URL` - your PostHog API URL (defaults to https://app.posthog.com)
        zPostHog: in init posthog loggerz6[POSTHOG MOCK] PostHog logger initialized in mock modePOSTHOG_API_KEYNz4POSTHOG_API_KEY is not set, set 'POSTHOG_API_KEY=<>')llm_providerPOSTHOG_API_URLzhttps://us.i.posthog.com//batch/F)
flush_lock
batch_sizez.PostHog: Got exception on init PostHog client  )r   debugr   is_mock_moder   osgetenv	Exceptionr   r   LoggingCallbackasync_clientr   sync_clientr   rstripposthog_hostcapture_url_async_initializedr   	log_queueatexitregister_flush_on_exitsuper__init__r   	exceptionstr)selfkwargsposthog_api_urle	__class__s       T/root/tools/cai/cai_env/lib/python3.12/site-packages/litellm/integrations/posthog.pyr0   zPostHogLogger.__init__&   sQ   &	  !BC 7 9D  *,$$L yy*D19 VWW 61AA!D  12D#%99->#?D  ii(9;UVO / 6 6s ;D"&"3"3!4G<D&+D#"DODN OOD//0G %)6L  	$$@QI G		s   EE 	E9#E44E9c                    	 t        j                  d|       | j                  |      \  }}||t        d      | j	                  |      }ddi}| j                  |g|      }	|j                  d       d}
| j                  j                  |
t        |	      |      }|j                          |j                  dk7  r%t        d	|j                   d
|j                         | j                  rt        j                  d       y t        j                  d       y # t        $ r+}t        j                  dt        |              Y d }~y d }~ww xY w)Nz<PostHog: Sync logging - Enters logging function for model %sz'PostHog credentials not found in kwargsContent-Typeapplication/jsonr   r   urlcontentheaders   'Response from PostHog API status_code: , text: z-[POSTHOG MOCK] Sync event successfully mockedz%PostHog: Sync event successfully sentzPostHog Sync Layer Error - )r   r   _get_credentials_for_requestr#   create_posthog_event_payload_create_posthog_payloadr'   r&   postr
   raise_for_statusstatus_codetextr    r1   r2   )r3   r4   response_obj
start_timeend_timeapi_keyapi_urlevent_payloadr?   payloadr)   responser6   s                r8   log_success_eventzPostHogLogger.log_success_eventV   s]   #	M  NPV  $@@HGW'/ IJJ ==fEM  2G 22M?GLG$^^C019K'',,"7+ - H
 %%'##s*=h>R>R=SS[\d\i\i[jk    $$%TU$$%LM 	M$$'B3q6(%KLL	Ms   DD D 	E#!E		Ec                   K   	 t        j                  d|       | j                          | j                  ||||       d {    y 7 # t        $ r+}t        j
                  dt        |              Y d }~y d }~ww xY wwNz=PostHog: Async logging - Enters logging function for model %szPostHog Layer Error - r   r   _ensure_async_setup_log_async_eventr#   r1   r2   r3   r4   rJ   rK   rL   r6   s         r8   async_log_success_eventz%PostHogLogger.async_log_success_event|   s     	  OQW $$&''j(SSS 	$$'=c!fX%FG	@   B =A	 AA	 B A	 		A=!A83B 8A==B c                   K   	 t        j                  d|       | j                          | j                  ||||       d {    y 7 # t        $ r+}t        j
                  dt        |              Y d }~y d }~ww xY wwrT   rU   rX   s         r8   async_log_failure_eventz%PostHogLogger.async_log_failure_event   rZ   r[   c                 T  K   | j                  |      \  }}| j                  |      }| j                  j                  |||d       t	        j
                  d| j                   d       t        | j                        | j                  k\  r| j                          d {    y y 7 w)N)eventrM   rN   z-PostHog, event added to queue. Will flush in z seconds...)
rC   rD   r+   appendr   r   flush_intervallenr   flush_queue)r3   r4   rJ   rK   rL   rM   rN   rO   s           r8   rW   zPostHogLogger._log_async_event   s       <<VD99&A 	#GL	
 	;D<O<O;PP[\	
 t~~$//1""$$$ 2$s   BB(B& B(r4   returnc                     |j                  dd      }|t        d      |j                  dd      }|dk(  rdnd}| j                  |||	      }| j                  ||      }t	        |||
      S )z
        Helper function to create a PostHog event payload for logging

        Args:
            kwargs (Dict[str, Any]): request kwargs containing standard_logging_object

        Returns:
            PostHogEventPayload: defined in types.py
        standard_logging_objectNz+standard_logging_object not found in kwargs	call_type 	embeddingz$ai_embedding$ai_generation)rf   r4   
event_name)r_   
propertiesdistinct_id)get
ValueError_create_posthog_properties_get_distinct_idr   )r3   r4   rf   rg   rk   rl   rm   s          r8   rD   z*PostHogLogger.create_posthog_event_payload   s     EKJJ%tE
 #*JKK+//R@	(1[(@_FV
44$;! 5 

 ++,CVL"!#
 	
    rf   rk   c                 >   i }| j                  |dd      |d<   | j                  |dd      |d<   | j                  |d      }|||d<   |dk(  r| j                  |d	      }|||d
<   | j                  |dd      |d<   |dk(  r| j                  |dd      |d<   | j                  |d      }|||d<   | j                  |dd      |d<   | j                  |d      dk(  rd|d<   | j                  |d      }|||d<   | j                  ||       | j                  ||       |S )z6Create PostHog properties following LLM Analytics specmodelrh   z	$ai_modelcustom_llm_providerz$ai_providermessagesz	$ai_inputrj   rQ   z$ai_output_choicesprompt_tokensr   z$ai_input_tokenscompletion_tokensz$ai_output_tokensresponse_costz$ai_total_cost_usdresponse_time        z$ai_latencystatusfailureTz$ai_is_error	error_strz	$ai_error)	_safe_get_add_trace_properties_add_custom_metadata_properties)	r3   rf   r4   rk   rl   rv   rQ   ry   r~   s	            r8   rp   z(PostHogLogger._create_posthog_properties   sz    
 #'..1H'SU"V
;%)^^#%:B&

>"
 >>"9:F&.J{#))~~&=zJH#3;
/0 *.#_a*

%& )).2nn')<a/J*+
 '>P$/<J+,$(NN#_c%

=!
 >>18<	I)-J~&'>LI$*3
;' 	"":v6 	,,Z@rr   rl   c                 <   | j                  |di       }| j                  |d| j                               }||d<   | j                  |d| j                               }||d<   | j                  |      }|j                  d      xs |j                  d      }|r||d<   y y )	Nrf   trace_idz$ai_trace_ididz$ai_span_idparent_run_id	parent_idz$ai_parent_id)r   
_safe_uuid_extract_metadatarn   )r3   rl   r4   rf   r   span_idmetadatar   s           r8   r   z#PostHogLogger._add_trace_properties  s    "&..9RTV"W>>#Z1B
 &.
>"..!8$@QR$+
=!))&1LL1NX\\+5N	*3J' rr   c                     | j                  |      }t        |t              syh d}|j                         D ]  \  }}||vs|||<    y)z0Add custom metadata fields to PostHog propertiesN>    r?   user_idapi_baseendpointr   
deployment
model_infomodel_groupuser_api_keyhidden_paramsr   caching_groupsmodel_group_sizeuser_api_key_hashuser_api_key_aliasuser_api_key_spendlitellm_api_versionuser_api_key_org_idrequester_ip_addressuser_api_key_team_iduser_api_key_user_iduser_api_key_metadatauser_api_key_max_budgetuser_api_key_team_aliasuser_api_key_team_spenduser_api_key_user_emaillitellm_parent_otel_spanuser_api_key_end_user_idglobal_max_parallel_requestsuser_api_end_user_max_budgetuser_api_key_team_max_budgetuser_api_key_model_max_budget)r   
isinstancedictitems)r3   rl   r4   r   litellm_internal_fieldskeyvalues          r8   r   z-PostHogLogger._add_custom_metadata_properties  sX     ))&1(D)"#
H #..* 	(JC11"'
3	(rr   c                     | j                  |      }| j                  |d      }|rt        |      S | j                  |d      }|rt        |      S | j                  |d      }|rt        |      S | j                         S )Nr   end_userr   )r   r   r2   r   )r3   rf   r4   r   r   r   r   s          r8   rq   zPostHogLogger._get_distinct_idA  sz     ))&1..95w<>>"9:Fx= >>"9:Fx=   rr   c                     |j                  dd      }|B|j                  d      xs | j                  }|j                  d      xs | j                  }||fS | j                  }| j                  }||fS )ap  
        Get PostHog credentials for this request.

        Checks for per-request credentials in standard_callback_dynamic_params,
        falls back to instance defaults from environment variables.

        Args:
            kwargs: Request kwargs containing standard_callback_dynamic_params

        Returns:
            tuple[str, str]: (api_key, api_url)
         standard_callback_dynamic_paramsNposthog_api_keyr5   )rn   r   r(   )r3   r4   r   rM   rN   s        r8   rC   z*PostHogLogger._get_credentials_for_requestQ  s    " JJ94@ 	) ,70445FG ('' 
 1445FG %$$   **G''Grr   c                   K   	 | j                   syt        j                  dt        | j                          d       | j                  rt        j                  d       i }| j                   D ],  }|d   |d   f}||vrg ||<   ||   j                  |d          . |j                         D ]  \  \  }}}dd	i}| j                  ||      }|j                  d
       d}	| j                  j                  |	t        |      |       d{   }
|
j                          |
j                  dk7  st        d|
j                   d|
j                          | j                  r-t        j                  dt        | j                          d       yt        j                  dt        | j                          d       y7 # t        $ r+}t        j                   dt#        |              Y d}~yd}~ww xY ww)z
        Sends the in memory logs queue to PostHog API

        Raises:
            Raises a NON Blocking verbose_logger.exception if an error occurs
        NzPostHog: Sending batch of z eventsz@[POSTHOG MOCK] Mock mode enabled - API calls will be interceptedrM   rN   r_   r:   r;   r   r   r<   r@   rA   rB   z[POSTHOG MOCK] Batch of z events successfully mockedzPostHog: Batch of z events successfully sentz"PostHog Error sending batch API - )r+   r   r   rb   r    r`   r   rE   r'   r%   rF   r
   rG   rH   r#   rI   r1   r2   r3   batches_by_credentialsitemr   rM   rN   eventsr?   rP   r)   rQ   r6   s               r8   async_send_batchzPostHogLogger.async_send_batchs  s    3	T>>  ,S-@,AI   $$V
 CE" BIY84424*3/&s+224=A	B /E.J.J.L *"'F"$6 66vwG!(!4 5W=!%!2!2!7!7#&w/# "8 " 
 ))+''3.#A(BVBVAWW_`h`m`m_no !(   $$.s4>>/B.CC^_ $$(T^^)<(==VW#(  	T$$'I#a&%RSS	Ts^   G2F; G2C7F; F9	#F; -AF; G2,F; 8G29F; ;	G/!G*%G2*G//G2c                 6   | j                   sZ	 t        j                         | _        t        j                  | j                                d| _         t        j                  d       y y # t        $ r'}t        j                  dt        |               d }~ww xY w)NTz%PostHog: Async components initializedz0PostHog: Failed to initialize async components: )r*   asyncioLockr   create_taskperiodic_flushr   r   r#   errorr2   )r3   r6   s     r8   rV   z!PostHogLogger._ensure_async_setup  s    &&	"),,.##D$7$7$9:*.'$$%LM '  $$Fs1vhO 	s   AA( (	B1"BBc                 Z    |j                  di       xs i }|j                  di       xs i S )Nlitellm_paramsr   )rn   )r3   r4   r   s      r8   r   zPostHogLogger._extract_metadata  s0    $4b9?R!!*b17R7rr   c                 <    t        t        j                               S N)r2   r   uuid4)r3   s    r8   r   zPostHogLogger._safe_uuid  s    4::<  rr   r   rM   c                     ||dS )N)rM   batchr   )r3   r   rM   s      r8   rE   z%PostHogLogger._create_posthog_payload  s    "V44rr   objr   defaultc                 F    |t        |d      s|S |j                  ||      S )Nrn   )hasattrrn   )r3   r   r   r   s       r8   r   zPostHogLogger._safe_get  s&    ;gc51NwwsG$$rr   c                    | j                   syt        j                  dt        | j                          d       	 i }| j                   D ],  }|d   |d   f}||vrg ||<   ||   j	                  |d          . |j                         D ]  \  \  }}}ddi}| j                  ||      }|j                  d	       d
}	| j                  j                  |	t        |      |      }
|
j                          |
j                  dk7  szt        j                  d|
j                           | j                  r-t        j                  dt        | j                          d       n,t        j                  dt        | j                          d       | j                   j                          y# t         $ r+}t        j                  dt#        |              Y d}~yd}~ww xY w)a  
        Flush remaining events from internal log_queue before process exit.
        Called automatically via atexit handler.

        This works in conjunction with GLOBAL_LOGGING_WORKER's atexit handler:
        1. GLOBAL_LOGGING_WORKER atexit invokes pending callbacks
        2. Callbacks add events to this logger's internal log_queue
        3. This atexit handler flushes the internal queue to PostHog
        NzPostHog: Flushing z remaining events on exitrM   rN   r_   r:   r;   r   r   r<   r@   z*PostHog: Failed to flush on exit - status z$[POSTHOG MOCK] Successfully flushed z events on exitzPostHog: Successfully flushed z(PostHog: Error flushing events on exit: )r+   r   r   rb   r`   r   rE   r'   r&   rF   r
   rG   rH   r   r    clearr#   r2   r   s               r8   r.   zPostHogLogger._flush_on_exit  s    ~~ T^^!4 55NO	
)	VBD" BIY84424*3/&s+224=A	B /E.J.J.L *"'F"$6 66vwG!(!4 5W=++00#&w/# 1 
 ))+''3."((DXEYEYDZ[!(   $$:3t~~;N:O_ $$4S5H4IY NN  " 	V  #KCPQF8!TUU	Vs   CF& B#F& &	G/!GG)Nr{   r{   r   )__name__
__module____qualname__r0   rR   rY   r]   rW   r   r2   r   r   rD   r   rp   r   r   rq   r   r   rC   r   rV   r   r   listrE   r   r.   __classcell__)r7   s   @r8   r   r   %   s   .`$ML		 CF%$!
38n!
	!
F8!78 S#X8 	8
 
c3h8t4S#X 4SRUX 4 .(sCx..(26sCx..(`!'=!GKCQTH~!	!   38n  	x}hsm+	,  D:Tx8S#X 84S> 8!C !5d 5S 5T#s(^ 5%S %s %S %C %
:Vrr   r   )__doc__r   r,   r!   typingr   r   r   r   litellm._loggingr   litellm._uuidr   (litellm.integrations.custom_batch_loggerr	   *litellm.litellm_core_utils.safe_json_dumpsr
   (litellm.integrations.posthog_mock_clientr   r   &litellm.llms.custom_httpx.http_handlerr   r   r   "litellm.types.integrations.posthogr   r   litellm.types.utilsr   r   r   r   rr   r8   <module>r      sR   	   	 - - +  F A 
 V`V% `Vrr   