
    jD                         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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)_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                  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(                         t+        | X  di |dt.        d y# t        $ r(}t        j0                  dt3        |              |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 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       u/Users/manta/Documents/Projects/TheRoad-I1/backend/.venv/lib/python3.12/site-packages/litellm/integrations/posthog.pyr,   z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 	D?#D::D?c                 L   	 t        j                  d|       | j                  |      \  }}||t        d      | j	                  |      }ddi}| j                  |g|      }	|j                  d       d}
| j                  j                  |
|	|      }|j                          |j                  dk7  r%t        d	|j                   d
|j                         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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.   )r/   r0   response_obj
start_timeend_timeapi_keyapi_urlevent_payloadr;   payloadr%   responser2   s                r4   log_success_eventzPostHogLogger.log_success_eventI   s@    	M  NPV  $@@HGW'/ 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,C/ /	D#8!DD#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   r-   r.   r/   r0   rF   rG   rH   r2   s         r4   async_log_success_eventz%PostHogLogger.async_log_success_eventl   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rP   rQ   rT   s         r4   async_log_failure_eventz%PostHogLogger.async_log_failure_eventw   rV   rW   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)eventrI   rJ   z-PostHog, event added to queue. Will flush in z seconds...)
r?   r@   r'   appendr   r   flush_intervallenr   flush_queue)r/   r0   rF   rG   rH   rI   rJ   rK   s           r4   rS   zPostHogLogger._log_async_event   s     <<VD99&A 	"
 	
 	;D<O<O;PP[\	
 t~~$//1""$$$ 2$s   BB(B& B(r0   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)rb   r0   
event_name)r[   
propertiesdistinct_id)get
ValueError_create_posthog_properties_get_distinct_idr   )r/   r0   rb   rc   rg   rh   ri   s          r4   r@   z*PostHogLogger.create_posthog_event_payload   s     EKJJ%tE
 #*JKK+//R@	(1[(@_FV
44$;! 5 

 ++,CVL"!#
 	
    rb   rg   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modelrd   z	$ai_modelcustom_llm_providerz$ai_providermessagesz	$ai_inputrf   rM   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)	r/   rb   r0   rg   rh   rr   rM   ru   rz   s	            r4   rl   z(PostHogLogger._create_posthog_properties   su    
 #'..1H'SU"V
;%)^^4KMbdf%g
>" >>"9:F&.J{#))~~&=zJH#3;
/0 *.8OQ`bc)d
%&)).2nn=TVikl.mJ*+ '>P$/<J+,$(NN3JO]`$a
=! >>18<	I)-J~&'>LI$*3
;' 	"":v6 	,,Z@rn   rh   c                 <   | j                  |di       }| j                  |d| j                               }||d<   | j                  |d| j                               }||d<   | j                  |      }|j                  d      xs |j                  d      }|r||d<   y y )	Nrb   trace_idz$ai_trace_ididz$ai_span_idparent_run_id	parent_idz$ai_parent_id)r{   
_safe_uuid_extract_metadatarj   )r/   rh   r0   rb   r   span_idmetadatar   s           r4   r|   z#PostHogLogger._add_trace_properties   s    "&..9RTV"W>>"9:tGXY%-
>"..!8$@QR$+
=!))&1LL1NX\\+5N	*3J' rn   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)r/   rh   r0   r   litellm_internal_fieldskeyvalues          r4   r}   z-PostHogLogger._add_custom_metadata_properties   sP    ))&1(D)
#
 #..*JC11"'
3 +rn   c                     | j                  |      }| j                  |d      }|rt        |      S | j                  |d      }|rt        |      S | j                  |d      }|rt        |      S | j                         S )Nr   end_userr   )r   r{   r.   r   )r/   rb   r0   r   r   r   r   s          r4   rm   zPostHogLogger._get_distinct_id  sz     ))&1..95w<>>"9:Fx= >>"9:Fx=   rn   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_keyr1   )rj   r   r$   )r/   r0   r   rI   rJ   s        r4   r?   z*PostHogLogger._get_credentials_for_request  s     JJ94@ 	) ,76::;LMeQUQeQeG6::;LMbQUQbQbG
  **G''Grn   c                 "  K   	 | 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                  |	||       d{   }
|
j                          |
j                  dk7  syt        d|
j                   d|
j                          t        j                  dt        | j                          d       y7 w# 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 eventsrI   rJ   r[   r6   r7   r   r   r8   r<   r=   r>   zPostHog: Batch of z events successfully sentz"PostHog Error sending batch API - )r'   r   r   r^   r\   r   rA   r#   r!   rB   rC   rD   r   rE   r-   r.   r/   batches_by_credentialsitemr   rI   rJ   eventsr;   rL   r%   rM   r2   s               r4   async_send_batchzPostHogLogger.async_send_batch5  s    )	T>>  ,S-@,AI
 CE"IY84424*3/&s+224=A	 ' /E.J.J.L*"'F"$6 66vw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                 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   errorr.   )r/   r2   s     r4   rR   z!PostHogLogger._ensure_async_setupg  s    &&"),,.##D$7$7$9:*.'$$%LM '  $$'WX[\]X^W_%`a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   )rj   )r/   r0   r   s      r4   r   zPostHogLogger._extract_metadatar  s0    $4b9?R!!*b17R7rn   c                 <    t        t        j                               S N)r.   r   uuid4)r/   s    r4   r   zPostHogLogger._safe_uuidv  s    4::<  rn   r   rI   c                     ||dS )N)rI   batchr   )r/   r   rI   s      r4   rA   z%PostHogLogger._create_posthog_payloady  s    "V44rn   objr   defaultc                 F    |t        |d      s|S |j                  ||      S )Nrj   )hasattrrj   )r/   r   r   r   s       r4   r{   zPostHogLogger._safe_get|  s&    ;gc51NwwsG$$rn   c                 6   | 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                  |	||      }
|
j                          |
j                  dk7  sqt        j                  d|
j                           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 exitrI   rJ   r[   r6   r7   r   r   r8   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   r^   r\   r   rA   r#   r"   rB   rC   rD   r   clearr   r.   r   s               r4   r*   zPostHogLogger._flush_on_exit  s    ~~ T^^!4 55NO	
$	VBD"IY84424*3/&s+224=A	 ' /E.J.J.L*"'F"$6 66vwG!(!4 5W=++00# # 1 
 ))+''3."((DXEYEYDZ[! /M(   0T^^1D0E_U NN  " 	V  #KCPQF8!TUU	Vs   B=E$ 9A*E$ $	F-!FF)Nrw   rw   r   )__name__
__module____qualname__r,   rN   rU   rY   rS   r   r.   r   r   r@   r   rl   r|   r}   rm   r   r   r?   r   rR   r   r   listrA   r{   r*   __classcell__)r3   s   @r4   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rn   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   rn   r4   <module>r      sJ   	   	 - - +  F 
 VVV% VVrn   