Ë
    tPêj>  ã                   óˆ   — d dl Z d dlmZ d dlmZmZmZmZ d dlZd dlm	Z	 d dl
mZ d dlmZ erd dlmZ neZ G d„ d	e«      Zy)
é    N)Údatetime)ÚTYPE_CHECKINGÚAnyÚFinalÚcast)Úverbose_logger©Ú!CLOUDZERO_EXPORT_INTERVAL_MINUTES©ÚCustomLogger)ÚAsyncIOSchedulerc            
       óº   ‡ — e Zd ZdZ	 	 	 ddedz  dedz  dedz  fˆ fd„Zd„ Zd„ Z	 	 	 	 dd	edz  d
ede	dz  de	dz  fd„Z
dd	edz  fd„Zd„ Zedefd„«       Zˆ xZS )ÚCloudZeroLoggeraD  
    CloudZero Logger for exporting LiteLLM usage data to CloudZero AnyCost API.

    Environment Variables:
        CLOUDZERO_API_KEY: CloudZero API key for authentication
        CLOUDZERO_CONNECTION_ID: CloudZero connection ID for data submission
        CLOUDZERO_TIMEZONE: Timezone for date handling (default: UTC)
    NÚapi_keyÚconnection_idÚtimezonec                 ó0  •— t        ‰| �  di |¤Ž |xs t        j                  d«      | _        |xs t        j                  d«      | _        |xs t        j                  dd«      | _        t        j                  d| j
                  | j                  «       y)zXInitialize CloudZero logger with configuration from parameters or environment variables.ÚCLOUDZERO_API_KEYÚCLOUDZERO_CONNECTION_IDÚCLOUDZERO_TIMEZONEÚUTCzACloudZero Logger initialized with connection ID: %s, timezone: %sN© )	ÚsuperÚ__init__ÚosÚgetenvr   r   r   r   Údebug)Úselfr   r   r   ÚkwargsÚ	__class__s        €úm/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/integrations/cloudzero/cloudzero.pyr   zCloudZeroLogger.__init__   s   ø€ ô 	‰ÑÑ"˜6Ò"ð Ò@¤"§)¡)Ð,?Ó"@ˆŒØ*ÒR¬b¯i©iÐ8QÓ.RˆÔØ ÒJ¤B§I¡IÐ.BÀEÓ$JˆŒÜ×ÑØOÐQU×QcÑQcÐei×erÑerõ	
ó    c              ƒ   óŠ  K  — ddl m} ddlm} |j                  j
                  }|r[|j                  rO|j                  |¬«      ƒ d{  –—† r4	 | j                  «       ƒ d{  –—†  |j                  |¬«      ƒ d{  –—†  yy| j                  «       ƒ d{  –—†  y7 ŒR7 Œ;7 Œ## |j                  |¬«      ƒ d{  –—†7   w xY w7 Œ+­w)aa  
        Handler for initializing CloudZero export job.

        Runs when CloudZero logger starts up.

        - If redis cache is available, we use the pod lock manager to acquire a lock and export the data.
            - Ensures only one pod exports the data at a time.
        - If redis cache is not available, we export the data directly.
        r   )Ú$CLOUDZERO_EXPORT_USAGE_DATA_JOB_NAME)Úproxy_logging_obj)Ú
cronjob_idN)
Úlitellm.constantsr$   Úlitellm.proxy.proxy_serverr%   Údb_spend_update_writerÚpod_lock_managerÚredis_cacheÚacquire_lockÚ_hourly_usage_data_exportÚrelease_lock)r   r$   r%   r*   s       r!   Úinitialize_cloudzero_export_jobz/CloudZeroLogger.initialize_cloudzero_export_job,   sÀ   è ø€ õ	
õ 	Aà"3×"JÑ"J×"[Ñ"[Ðñ Ð 0× <Ò <Ø%×2Ñ2Ð>bÐ2Óc×cÐcðiØ×8Ñ8Ó:×:Ð:à*×7Ñ7ÐCgÐ7Óh×hÑhð	 dð ×0Ñ0Ó2×2Ñ2ð døà:øàhùÐ*×7Ñ7ÐCgÐ7Óh×hÒhúð 3úsf   ‚ACÁBÁ	CÁB! Á!BÁ"B! Á&CÁ;BÁ<CÂCÂCÂB! ÂCÂ!B>Â7B:Â8B>Â>Cc              ƒ   óÊ   K  — ddl m}m} ddlm} t        j
                  |j                  «      }| |t        dz  ¬«      z
  }| j                  |d||¬«      ƒ d{  –—†  y7 Œ­w)	z|
        Exports the hourly usage data to CloudZero.

        Start time: 1 hour ago
        End time: current time
        r   )Ú	timedeltar   )Ú"CLOUDZERO_MAX_FETCHED_DATA_RECORDSé   ©ÚminutesÚreplace_hourly)ÚlimitÚ	operationÚstart_time_utcÚend_time_utcN)	r   r1   r   r'   r2   ÚnowÚutcr
   Úexport_usage_data)r   r1   r   r2   Úcurrent_time_utcÚone_hour_ago_utcs         r!   r-   z)CloudZeroLogger._hourly_usage_data_exportH   sa   è ø€ ÷ 	1åHä"*§,¡,¨x¯|©|Ó"<Ðà"2±YÔGhÐklÑGlÔ5mÑ"mÐØ×$Ñ$Ø4Ø&Ø+Ø)ð	 %ó 
÷ 	
ò 	
ús   ‚AA#ÁA!ÁA#r7   r8   r9   r:   c              ƒ   ób  K  — ddl m} ddlm} ddlm} 	 t        j                  d«       | j                  r| j                  st        d«      ‚ |«       }t        j                  d«       |j                  |||¬«      ƒ d	{  –—† }	|	j                  «       rt        j                  d
«       y	t        j                  dt        |	«      «        |«       }
|
j                  |	«      }|j                  «       rt        j                  d«       y	 || j                  | j                  | j                   ¬«      }t        j                  dt        |«      «       |j#                  ||¬«       t        j                  dt        |«      «       y	7 �Œ# t$        $ r}t        j&                  d|«       ‚ d	}~ww xY w­w)aP  
        Exports the usage data to CloudZero.

        - Reads data from the DB
        - Transforms the data to the CloudZero format
        - Sends the data to CloudZero

        Args:
            limit: Optional limit on number of records to export
            operation: CloudZero operation type ("replace_hourly" or "sum")
        r   )ÚCloudZeroStreamer©ÚLiteLLMDatabase©ÚCBFTransformerz,CloudZero Logger: Starting usage data exportzpCloudZero configuration missing. Please set CLOUDZERO_API_KEY and CLOUDZERO_CONNECTION_ID environment variables.z2CloudZero Logger: Loading usage data from database)r7   r9   r:   Nz/CloudZero Logger: No usage data found to exportz'CloudZero Logger: Processing %s recordsz4CloudZero Logger: No valid data after transformation)r   r   Úuser_timezonez6CloudZero Logger: Transmitting %s records to CloudZero)r8   z?CloudZero Logger: Successfully exported %s records to CloudZeroz0CloudZero Logger: Error exporting usage data: %s)Ú,litellm.integrations.cloudzero.cz_stream_apirA   Ú'litellm.integrations.cloudzero.databaserC   Ú(litellm.integrations.cloudzero.transformrE   r   r   r   r   Ú
ValueErrorÚget_usage_dataÚis_emptyÚlenÚ	transformÚwarningr   Úsend_batchedÚ	ExceptionÚerror)r   r7   r8   r9   r:   rA   rC   rE   ÚdatabaseÚdataÚtransformerÚcbf_dataÚstreamerÚes                 r!   r=   z!CloudZeroLogger.export_usage_data]   s{  è ø€ õ$ 	SÝKÝKð*	Ü× Ñ Ð!OÔPð —<’< t×'9Ò'9Ü ð Góð ñ
 .Ó/ˆHÜ× Ñ Ð!UÔVØ!×0Ñ0°uÈ^ÐjvÐ0Ów×wˆDà�}‰}ŒÜ×$Ñ$Ð%VÔWØä× Ñ Ð!JÌCÐPTËIÔVñ "0Ó!1ˆKØ)×3Ñ3°DÓ9ˆHà× Ñ Ô"Ü×&Ñ&Ð']Ô^Øñ 0ØŸ™Ø"×0Ñ0Ø"Ÿm™môˆHô × Ñ Ð!YÔ[^Ð_gÓ[hÔiØ×!Ñ! (°iÐ!Ô@ä× Ñ Ð!bÔdgÐhpÓdqÕrð5 xúô8 ò 	Ü× Ñ Ð!SÐUVÔWØûð	üsU   ‚F/–A+F ÂFÂ)F Â+F/Â,AF ÄF/Ä	A:F ÆF/ÆF Æ	F,ÆF'Æ'F,Æ,F/c              ƒ   ó:  K  — ddl m} ddlm} 	 t	        j
                  d«        |«       }t	        j
                  d«       |j                  |¬«      ƒ d{  –—† }|j                  «       r!t	        j                  d«       g g dddddd	œd
œS t	        j
                  dt        |«      «       |j                  d«      j                  «       } |«       }|j                  |«      }|j                  «       rJt	        j                  d«       |g t        |«      t        d„ |D «       «      t        d„ |D «       «      ddd	œd
œS |j                  «       }	t        d„ |	D «       «      }
t        t        d„ |	D «       «      «      }t        t        d„ |	D «       «      «      }t        d„ |	D «       «      }t	        j
                  dt        |«      «       ||	t        |	«      |
|||d	œd
œS 7 �Œ„# t        $ r2}t	        j                   d|«       t	        j                   d|«       ‚ d}~ww xY w­w)a  
        Returns the data that would be exported to CloudZero without actually sending it.

        Args:
            limit: Limit number of records to display (default: 10000)

        Returns:
            dict: Contains usage_data, cbf_data, and summary statistics
        r   rB   rD   z)CloudZero Logger: Starting dry run exportz0CloudZero Logger: Loading usage data for dry run)r7   Nz&CloudZero Dry Run: No usage data found)Útotal_recordsÚ
total_costÚtotal_tokensÚunique_accountsÚunique_services)Ú
usage_datarV   Úsummaryz+CloudZero Dry Run: Processing %s records...é2   z5CloudZero Dry Run: No valid data after transformationc              3   ó@   K  — | ]  }|j                  d d«      –— Œ y­w)Úspendr   N©Úget©Ú.0Úrows     r!   ú	<genexpr>z<CloudZeroLogger.dry_run_export_usage_data.<locals>.<genexpr>Ò   s   è ø€ Ò)[À#¨#¯'©'°'¸1×*=Ñ)[ùó   ‚c              3   óf   K  — | ])  }|j                  d d«      |j                  dd«      z   –— Œ+ y­w)Úprompt_tokensr   Úcompletion_tokensNrd   rf   s     r!   ri   z<CloudZeroLogger.dry_run_export_usage_data.<locals>.<genexpr>Ó   s2   è ø€ ò ,Ø^a˜CŸG™G O°QÓ7¸#¿'¹'ÐBUÐWXÓ:YÕYñ,ùs   ‚/1c              3   ó@   K  — | ]  }|j                  d d«      –— Œ y­w©ú	cost/costr   Nrd   ©rg   Úrecords     r!   ri   z<CloudZeroLogger.dry_run_export_usage_data.<locals>.<genexpr>ß   s   è ø€ Ò#[À6 F§J¡J¨{¸A×$>Ñ#[ùrj   c              3   ód   K  — | ](  }|j                  d «      sŒ|j                  d d«      –— Œ* y­w©úresource/accountÚ Nrd   rq   s     r!   ri   z<CloudZeroLogger.dry_run_export_usage_data.<locals>.<genexpr>á   ó+   è ø€ Òu¸6ÐV\×V`ÑV`ÐasÕVt�F—J‘JÐ1°2×6Ñuùó   ‚0™0c              3   ód   K  — | ](  }|j                  d «      sŒ|j                  d d«      –— Œ* y­w©úresource/servicerv   Nrd   rq   s     r!   ri   z<CloudZeroLogger.dry_run_export_usage_data.<locals>.<genexpr>ä   rw   rx   c              3   ó@   K  — | ]  }|j                  d d«      –— Œ y­w©úusage/amountr   Nrd   rq   s     r!   ri   z<CloudZeroLogger.dry_run_export_usage_data.<locals>.<genexpr>æ   s   è ø€ Ò%`È f§j¡j°À×&CÑ%`ùrj   z2CloudZero Logger: Dry run completed for %s recordsz-CloudZero Logger: Error in dry run export: %szCloudZero Dry Run Error: %s)rH   rC   rI   rE   r   r   rK   rL   rO   rM   ÚheadÚto_dictsrN   ÚsumÚsetrQ   rR   )r   r7   rC   rE   rS   rT   Úusage_data_samplerU   rV   Úcbf_data_dictr[   r]   r^   r\   rX   s                  r!   Údry_run_export_usage_dataz)CloudZeroLogger.dry_run_export_usage_dataŸ   s*  è ø€ õ 	LÝKðM	Ü× Ñ Ð!LÔMñ .Ó/ˆHÜ× Ñ Ð!SÔTØ (× 7Ñ 7¸eÐ 7Ó D×DˆDà�}‰}ŒÜ×&Ñ&Ð'OÔPà"$Ø "à)*Ø&'Ø()Ø+,Ø+,ñ ñ
ð 
ô × Ñ Ð!NÔPSÐTXÓPYÔZð (,§y¡y°£}×'=Ñ'=Ó'?Ðñ "0Ó!1ˆKØ)×3Ñ3°DÓ9ˆHà× Ñ Ô"Ü×&Ñ&Ð'^Ô_à"3Ø "ä),Ð->Ó)?Ü&)Ñ)[ÐIZÔ)[Ó&[Ü(+ñ ,Øevô,ó )ð ,-Ø+,ñ ñð ð $,×#4Ñ#4Ó#6ˆMô !$Ñ#[È]Ô#[Ó [ˆJÜ%(ÜÑuÀ]ÔuÓuó&ˆOô &)ÜÑuÀ]ÔuÓuó&ˆOô #&Ñ%`ÐR_Ô%`Ó"`ˆLä× Ñ Ð!UÔWZÐ[cÓWdÔeð 0Ø)ä%(¨Ó%7Ø",Ø$0Ø'6Ø'6ññ
ð 
ðq EúôH ò 	Ü× Ñ Ð!PÐRSÔTÜ× Ñ Ð!>ÀÔBØûð	üsU   ‚H�AG ÁGÁ4G ÂHÂB/G Ä;HÄ<BG ÇHÇG Ç	HÇ&-HÈHÈHc                 ó  — ddl m} ddlm} ddlm}  |«       }|j                  «       r|j                  d«       y|j                  dt        |«      › d�«       |j                  «       } |d	d
|d¬«      }|j                  ddd¬«       |j                  dddd¬«       |j                  dddd¬«       |j                  dddd¬«       |j                  ddd¬«       |j                  ddd¬«       |j                  ddd¬«       |j                  ddd¬«       |j                  dddd¬«       |j                  ddd¬«       |j                  d dd¬«       |j                  d!d"d¬«       |j                  d#d$d¬«       |D �]  }t        |j                  dd%«      «      }	t        |j                  dd«      «      }
t        |j                  dd«      «      }t        |j                  dd%«      «      }t        |j                  d d%«      «      }t        |j                  d!d%«      «      }t        |j                  d#d%«      «      }t        |j                  dd%«      «      }t        |j                  dd%«      «      }t        |j                  d&d%«      «      }t        |j                  d'd%«      «      }t        |j                  d(d%«      «      }t        |j                  d)d%«      «      }|j                  |	|
|||||||||||«       �Œ‚ |j                  |«       t        d*„ |D «       «      }t        t        d+„ |D «       «      «      }t        t        d,„ |D «       «      «      }t        d-„ |D «       «      }|j                  d.«       |j                  d/t        |«      d0›�«       |j                  d1|d2›�«       |j                  d3|d0›�«       |j                  d4|› �«       |j                  d5|› �«       |j                  d6«       y)7z<Display CBF transformed data in a formatted table on screen.r   )ÚSIMPLE)ÚConsole)ÚTablez'[yellow]No CBF data to display[/yellow]Nu2   
[bold green]ðŸ’° CloudZero CBF Transformed Data (z records)[/bold green]Tz	bold cyan)r   é   )Úshow_headerÚheader_styleÚboxÚpaddingztime/usage_startÚblueF)ÚstyleÚno_wraprp   ÚgreenÚright)r�   Újustifyr‘   Úentity_typeÚmagentaÚ	entity_idÚteam_idÚcyanÚ
team_aliasÚ
user_emailÚapi_key_aliasÚyellowr~   zresource/idr{   ru   Úwhitezresource/regionÚdimzN/Azresource/tag:team_idzresource/tag:team_aliaszresource/tag:user_emailzresource/tag:api_key_aliasc              3   ó@   K  — | ]  }|j                  d d«      –— Œ y­wro   rd   rq   s     r!   ri   z>CloudZeroLogger._display_cbf_data_on_screen.<locals>.<genexpr>?  s   è ø€ ÒQ¸v §
¡
¨;¸× :ÑQùrj   c              3   ód   K  — | ](  }|j                  d «      sŒ|j                  d d«      –— Œ* y­wrt   rd   rq   s     r!   ri   z>CloudZeroLogger._display_cbf_data_on_screen.<locals>.<genexpr>A  ó(   è ø€ Òk°vÈFÏJÉJÐWiÕLj�—
‘
Ð-¨r×2Ñkùrx   c              3   ód   K  — | ](  }|j                  d «      sŒ|j                  d d«      –— Œ* y­wrz   rd   rq   s     r!   ri   z>CloudZeroLogger._display_cbf_data_on_screen.<locals>.<genexpr>D  r¢   rx   c              3   ó@   K  — | ]  }|j                  d d«      –— Œ y­wr}   rd   rq   s     r!   ri   z>CloudZeroLogger._display_cbf_data_on_screen.<locals>.<genexpr>H  s   è ø€ Ò!VÀF &§*¡*¨^¸Q×"?Ñ!Vùrj   u(   
[bold blue]ðŸ“Š CBF Summary[/bold blue]z  Records: ú,z  Total Cost: $z.2fz  Total Tokens: z  Unique Accounts: z  Unique Services: uM   
[dim]ðŸ’¡ This is the CloudZero CBF format ready for AnyCost ingestion[/dim])Úrich.boxr‡   Úrich.consolerˆ   Ú
rich.tabler‰   rL   ÚprintrM   r€   Ú
add_columnÚstrre   Úadd_rowr�   r‚   )r   rV   r‡   rˆ   r‰   ÚconsoleÚrecordsÚ	cbf_tablerr   Útime_usage_startÚ	cost_costÚusage_amountÚresource_idÚresource_serviceÚresource_accountÚresource_regionr•   r—   r˜   rš   r›   rœ   r[   r]   r^   r\   s                             r!   Ú_display_cbf_data_on_screenz+CloudZeroLogger._display_cbf_data_on_screenû   sß  € å#Ý(Ý$á ›ˆà×ÑÔØ�M‰MÐCÔDØà�‰ÐKÌCÐPXËMÈ?ÐZpÐqÔrð "×*Ñ*Ó,ˆñ !¨TÀÐQWÐagÔhˆ	Ø×ÑÐ/°vÀuÐÔMØ×Ñ˜[°ÀÐRWÐÔXØ×Ñ˜]°)ÀWÐV[ÐÔ\Ø×Ñ˜[°	À7ÐTYÐÔZØ×Ñ˜Y¨f¸eÐÔDØ×Ñ˜\°ÀÐÔGØ×Ñ˜\°ÀÐÔGØ×Ñ˜_°HÀeÐÔLØ×Ñ˜^°8ÀWÐV[ÐÔ\Ø×Ñ˜]°)ÀUÐÔKØ×ÑÐ/°vÀuÐÔMØ×ÑÐ/°wÈÐÔNØ×ÑÐ.°eÀUÐÔKàó 	ˆFä" 6§:¡:Ð.@À%Ó#HÓIÐÜ˜FŸJ™J {°AÓ6Ó7ˆIÜ˜vŸz™z¨.¸!Ó<Ó=ˆLÜ˜fŸj™j¨¸Ó>Ó?ˆKÜ" 6§:¡:Ð.@À%Ó#HÓIÐÜ" 6§:¡:Ð.@À%Ó#HÓIÐÜ! &§*¡*Ð->ÀÓ"FÓGˆOÜ˜fŸj™j¨¸Ó>Ó?ˆKÜ˜FŸJ™J {°EÓ:Ó;ˆIÜ˜&Ÿ*™*Ð%;¸UÓCÓDˆGÜ˜VŸZ™ZÐ(AÀ5ÓIÓJˆJÜ˜VŸZ™ZÐ(AÀ5ÓIÓJˆJÜ §
¡
Ð+GÈÓ OÓPˆMà×ÑØ ØØØØØØØØØØ Ø Øöð!	ð@ 	�‰�iÔ ô  ÑQÈÔQÓQˆ
Ü!$ÜÑkÀÔkÓkó"
ˆô "%ÜÑkÀÔkÓkó"
ˆô
 "Ñ!VÈgÔ!VÓVˆà�‰ÐAÔBØ�‰˜¤C¨£L°Ð#3Ð4Ô5Ø�‰˜¨
°3Ð'7Ð8Ô9Ø�‰Ð(¨°aÐ(8Ð9Ô:Ø�‰Ð+¨OÐ+<Ð=Ô>Ø�‰Ð+¨OÐ+<Ð=Ô>à�‰ÐfÕgr"   Ú	schedulerc              ƒ   óZ  K  — ddl m} ddlm} t        j
                  j                  t        ¬«      }t        j                  dt        |«      «       t        |«      dkD  rJt        t        |d   «      }t        j                  d|z  «       | j                  |j                  d|¬«       y	y	­w)
z’
        Initialize the CloudZero background job.

        Starts the background job that exports the usage data to CloudZero every hour.
        r   r	   r   )Úcallback_typezfound %s cloudzero loggerszNInitializing remaining budget metrics as a cron job executing every %s minutesÚintervalr4   N)r'   r
   Ú"litellm.integrations.custom_loggerr   ÚlitellmÚlogging_callback_managerÚget_custom_loggers_for_typer   r   r   rM   r   Úadd_jobr/   )r¸   r
   r   Úprometheus_loggersÚcloudzero_loggers        r!   Úinit_cloudzero_background_jobz-CloudZeroLogger.init_cloudzero_background_jobS  s«   è ø€ õ 	HÝCä8?×8XÑ8X×8tÑ8tÜ)ð 9uó 9
Ðô 	×ÑÐ9¼3Ð?QÓ;RÔSÜÐ!Ó" QÒ&Ü&*¬?Ð<NÈqÑ<QÓ&RÐÜ× Ñ Ø`Ø3ñ4ôð ×ÑØ ×@Ñ@ØØ9ð õ ð 'ùs   ‚B)B+)NNN)Nr6   NN)i'  )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r«   r   r/   r-   Úintr   r=   r…   r·   Ústaticmethodr   rÃ   Ú__classcell__)r    s   @r!   r   r      sÌ   ø„ ñð #Ø$(Ø#ñ	
à�t‘ð
ð ˜T‘zð
ð ˜‘*õ	
ò$3ò8
ð. !Ø)Ø*.Ø(,ñ@à�T‰zð@ð ð@ð ! 4™ð	@ð
  ‘oó@ñDZ°S¸4±Zó ZòxVhðp ðÐ7Gò ó ôr"   r   )r   r   Útypingr   r   r   r   r½   Úlitellm._loggingr   r'   r
   r¼   r   Úapscheduler.schedulers.asyncior   r   r   r"   r!   ú<module>rÎ      s7   ðÛ 	Ý ß 2Ó 2ã Ý +Ý ?Ý ;áÞ?àÐô\�lõ \r"   