
    MiD                         S r SSKrSSKrSSKrSSKJrJrJrJr  SSK	J
r
  SSKJr  SSKJr  SSKJrJrJr  SSKJrJr  SS	KJrJr   " S
 S\5      rg)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)_get_httpx_clientget_async_httpx_clienthttpxSpecialProvider)POSTHOG_MAX_BATCH_SIZEPostHogEventPayload)StandardCallbackDynamicParamsStandardLoggingPayloadc            
         ^  \ rS rSrU 4S jrS rS rS rSS jrS\	\
\4   S\4S	 jrS
\S\	\
\4   S\
S\	\
\4   4S jrS\	\
\4   S\	\
\4   4S jrS\	\
\4   S\	\
\4   4S jrS
\S\	\
\4   S\
4S jrS\	\
\4   S\\\
   \\
   4   4S jrS rS rS\	\
\4   S\	\
\4   4S jrS\
4S jrS\S\
S\	\
\4   4S jrS S\S\
S\S\4S jjrS rSrU =r$ )!PostHogLogger    c                   >  [         R                  " S5        [        R                  " SS5      c  [	        S5      e[        [        R                  S9U l        [        5       U l
        [        R                  " S5      U l        [        R                  " SS5      nUR                  S5      U l        U R                   S	3U l        S
U l        SU l        / U l        [$        R&                  " U R(                  5        [*        TU ]X  " S0 UDS[.        S.D6  g! [         a)  n[         R0                  " S[3        U5       35        UeSnAff = f)z
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 logger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   debug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       v/var/www/eduai.edurigo.com/storigo/production/storigo_env/lib/python3.13/site-packages/litellm/integrations/posthog.pyr-   PostHogLogger.__init__!   s$   	  !BC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   DD 
E$E  Ec                 R    [         R                  " SU5        U R                  U5      u  pVUb  Uc  [        S5      eU R	                  U5      nSS0nU R                  U/U5      n	UR                  S5       S3n
U R                  R                  U
U	US9nUR                  5         UR                  S:w  a%  [        S	UR                   S
UR                   35      e[         R                  " S5        g ! [         a,  n[         R                  " S[        U5       35         S nAg S nAff = f)Nz<PostHog: Sync logging - Enters logging function for model %sz'PostHog credentials not found in kwargsContent-Typeapplication/jsonr   r   urljsonheaders   'Response from PostHog API status_code: , text: z%PostHog: Sync event successfully sentzPostHog Sync Layer Error - )r   r   _get_credentials_for_requestr    create_posthog_event_payload_create_posthog_payloadr$   r#   postraise_for_statusstatus_codetextr.   r/   )r0   r1   response_obj
start_timeend_timeapi_keyapi_urlevent_payloadr=   payloadr&   responser3   s                r5   log_success_eventPostHogLogger.log_success_eventI   s>    	M  NPV  $@@HG'/ IJJ ==fEM  2G 22M?GLG$^^C019K'',, - H
 %%'##s*=h>R>R=SS[\d\i\i[jk    !HI 	M$$'B3q6(%KLL	Ms   C-C0 0
D&:"D!!D&c                   #     [         R                  " SU5        U R                  5         U R                  XX45      I S h  vN   g  N! [         a,  n[         R
                  " S[        U5       35         S nAg S nAff = f7fNz=PostHog: Async logging - Enters logging function for model %szPostHog Layer Error - r   r   _ensure_async_setup_log_async_eventr    r.   r/   r0   r1   rH   rI   rJ   r3   s         r5   async_log_success_event%PostHogLogger.async_log_success_eventl   n     	  OQW $$&''jSSS 	$$'=c!fX%FG	@   B<A  AA BA 
A>"A94B9A>>Bc                   #     [         R                  " SU5        U R                  5         U R                  XX45      I S h  vN   g  N! [         a,  n[         R
                  " S[        U5       35         S nAg S nAff = f7frS   rT   rW   s         r5   async_log_failure_event%PostHogLogger.async_log_failure_eventw   rZ   r[   c                 V  #    U R                  U5      u  pVU R                  U5      nU R                  R                  UUUS.5        [        R
                  " SU R                   S35        [        U R                  5      U R                  :  a  U R                  5       I S h  vN   g g  N7f)N)eventrK   rL   z-PostHog, event added to queue. Will flush in z seconds...)
rA   rB   r(   appendr   r   flush_intervallenr   flush_queue)r0   r1   rH   rI   rJ   rK   rL   rM   s           r5   rV   PostHogLogger._log_async_event   s     <<VD99&A 	"
 	
 	;D<O<O;PP[\	
 t~~$//1""$$$ 2$s   BB) B'!B)r1   returnc                     UR                  SS5      nUc  [        S5      eUR                  SS5      nUS:X  a  SOSnU R                  UUUS	9nU R                  X!5      n[	        UUUS
9$ )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)rh   r1   
event_name)r`   
propertiesdistinct_id)get
ValueError_create_posthog_properties_get_distinct_idr   )r0   r1   rh   ri   rm   rn   ro   s          r5   rB   *PostHogLogger.create_posthog_event_payload   s     EKJJ%tE
 #*JKK+//R@	(1[(@_FV
44$;! 5 

 ++,CL"!#
 	
    rh   rm   c                 @   0 nU R                  USS5      US'   U R                  USS5      US'   U R                  US5      nUb  XTS'   US:X  a  U R                  US	5      nUb  XdS
'   U R                  USS5      US'   US:X  a  U R                  USS5      US'   U R                  US5      nUb  XtS'   U R                  USS5      US'   U R                  US5      S:X  a  SUS'   U R                  US5      nUb  XS'   U R                  XB5        U R                  XB5        U$ )z6Create PostHog properties following LLM Analytics specmodelrj   z	$ai_modelcustom_llm_providerz$ai_providermessagesz	$ai_inputrl   rO   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)	r0   rh   r1   rm   rn   ry   rO   r|   r   s	            r5   rr   (PostHogLogger._create_posthog_properties   si    
 #'..1H'SU"V
;%)^^4KMbdf%g
>" >>"9:F&.{#))~~&=zJH#3;/0 *.8OQ`bc)d
%&)).2nn=TVikl.mJ*+ '>P$/<+,$(NN3JO]`$a
=! >>18<	I)-J~&'>LI$*3;' 	"":6 	,,Z@ru   rn   c                 J   U R                  US0 5      nU R                  USU R                  5       5      nXAS'   U R                  USU R                  5       5      nXQS'   U R                  U5      nUR                  S5      =(       d    UR                  S5      nU(       a  XqS'   g g )	Nrh   trace_idz$ai_trace_ididz$ai_span_idparent_run_id	parent_idz$ai_parent_id)r   
_safe_uuid_extract_metadatarp   )r0   rn   r1   rh   r   span_idmetadatar   s           r5   r   #PostHogLogger._add_trace_properties   s    "&..9RTV"W>>"9:tGXY%->"..!8$@QR$+=!))&1LL1NX\\+5N	*3' ru   c                     U R                  U5      n[        U[        5      (       d  g1 SknUR                  5        H  u  pVXT;  d  M  XaU'   M     g)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)r0   rn   r1   r   litellm_internal_fieldskeyvalues          r5   r   -PostHogLogger._add_custom_metadata_properties   sL    ))&1(D))
#
 #..*JC1"'3 +ru   c                    U R                  U5      nU R                  US5      nU(       a  [        U5      $ U R                  US5      nU(       a  [        U5      $ U R                  US5      nU(       a  [        U5      $ U R                  5       $ )Nr   end_userr   )r   r   r/   r   )r0   rh   r1   r   r   r   r   s          r5   rs   PostHogLogger._get_distinct_id  sz     ))&1..95w<>>"9:Fx= >>"9:Fx=   ru   c                     UR                  SS5      nUbK  UR                  S5      =(       d    U R                  nUR                  S5      =(       d    U R                  nX44$ U R                  nU R                  nX44$ )a0  
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_keyr2   )rp   r   r%   )r0   r1   r   rK   rL   s        r5   rA   *PostHogLogger._get_credentials_for_request  s     JJ94@ 	) ,76::;LMeQUQeQeG6::;LMbQUQbQbG
  **G''Gru   c                 2  #     U R                   (       d  g[        R                  " S[        U R                   5       S35        0 nU R                    H,  nUS   US   4nX1;  a  / X'   X   R	                  US   5        M.     UR                  5        H  u  u  pEnSS0nU R                  Xd5      nUR                  S	5       S
3n	U R                  R                  U	UUS9I Sh  vN n
U
R                  5         U
R                  S:w  d  Mv  [        SU
R                   SU
R                   35      e   [        R                  " S[        U R                   5       S35        g N{! [         a,  n[        R                  " S[        U5       35         SnAgSnAff = f7f)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 eventsrK   rL   r`   r8   r9   r   r   r:   r>   r?   r@   zPostHog: Batch of z events successfully sentz"PostHog Error sending batch API - )r(   r   r   rc   ra   r   rC   r$   r"   rD   rE   rF   r    rG   r.   r/   r0   batches_by_credentialsitemr   rK   rL   eventsr=   rN   r&   rO   r3   s               r5   async_send_batchPostHogLogger.async_send_batch5  s    )	T>>  ,S-@,AI
 CE"IY8424*/&+224=A	 ' /E.J.J.L*"F"$6 66vG!(!4 5W=!%!2!2!7!7# # "8 " 
 ))+''3.#A(BVBVAWW_`h`m`m_no ! /M(   $S%8$99RS  	T$$'I#a&%RSS	TsR   FE FC
E  E!"E AE FE 
F("F
FFFc                 J   U R                   (       d]   [        R                  " 5       U l        [        R                  " U R                  5       5        SU l         [        R                  " S5        g g ! [         a(  n[        R                  " S[        U5       35        e S nAff = f)NTz%PostHog: Async components initializedz0PostHog: Failed to initialize async components: )r'   asyncioLockr   create_taskperiodic_flushr   r   r    errorr/   )r0   r3   s     r5   rU   !PostHogLogger._ensure_async_setupg  s    &&"),,.##D$7$7$9:*.'$$%LM '  $$'WX[\]X^W_%`as   AA0 0
B":#BB"c                 n    UR                  S0 5      =(       d    0 nUR                  S0 5      =(       d    0 $ )Nlitellm_paramsr   )rp   )r0   r1   r   s      r5   r   PostHogLogger._extract_metadatar  s0    $4b9?R!!*b17R7ru   c                 >    [        [        R                  " 5       5      $ N)r/   r   uuid4)r0   s    r5   r   PostHogLogger._safe_uuidv  s    4::<  ru   r   rK   c                 
    X!S.$ )N)rK   batchr   )r0   r   rK   s      r5   rC   %PostHogLogger._create_posthog_payloady  s    "44ru   objr   defaultc                 P    Ub  [        US5      (       d  U$ UR                  X#5      $ )Nrp   )hasattrrp   )r0   r   r   r   s       r5   r   PostHogLogger._safe_get|  s'    ;gc511Nwws$$ru   c                 J   U R                   (       d  g[        R                  " S[        U R                   5       S35         0 nU R                    H,  nUS   US   4nX1;  a  / X'   X   R	                  US   5        M.     UR                  5        H  u  u  pEnSS0nU R                  Xd5      nUR                  S	5       S
3n	U R                  R                  U	UUS9n
U
R                  5         U
R                  S:w  d  Mn  [        R                  " SU
R                   35        M     [        R                  " S[        U R                   5       S35        U R                   R                  5         g! [         a,  n[        R                  " S[        U5       35         SnAgSnAff = f)ai  
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 exitrK   rL   r`   r8   r9   r   r   r:   r>   z*PostHog: Failed to flush on exit - status zPostHog: Successfully flushed z events on exitz(PostHog: Error flushing events on exit: )r(   r   r   rc   ra   r   rC   r$   r#   rD   rE   rF   r   clearr    r/   r   s               r5   r+   PostHogLogger._flush_on_exit  s    ~~ T^^!4 55NO	
$	VBD"IY8424*/&+224=A	 ' /E.J.J.L*"F"$6 66vG!(!4 5W=++00# # 1 
 ))+''3."((DXEYEYDZ[! /M(   0T^^1D0E_U NN  " 	V  #KCPQF8!TUU	Vs    B8E, =A.E, ,
F"6"FF")r   r'   r"   r&   r   r(   r%   r#   )Nr~   r~   r   ) __name__
__module____qualname____firstlineno__r-   rP   rX   r]   rV   r   r/   r   r   rB   r   rr   r   r   rs   r   r   rA   r   rU   r   r   listrC   r   r+   __static_attributes____classcell__)r4   s   @r5   r   r       s   &P!MF		%$
4S> 
FY 
B0!70 S#X0 	0
 
c3h0d4S#X 4SRUX 4($sCx. (RVWZ\_W_R` (,!'=!GKCQTH~!	!  4S>  eHUXM[cdg[hLhFi  40Td	8S#X 84S> 8!C !5d 5S 5T#s(^ 5%S %s %S %C %
5V 5Vru   r   )__doc__r   r)   r   typingr   r   r   r   litellm._loggingr   litellm._uuidr   (litellm.integrations.custom_batch_loggerr	   &litellm.llms.custom_httpx.http_handlerr
   r   r   "litellm.types.integrations.posthogr   r   litellm.types.utilsr   r   r   r   ru   r5   <module>r      sJ   	   	 - - +  F 
 VVV% VVru   