Ë
    tPêj“.  ã                  óÀ   — d Z ddlmZ ddlZddlmZmZmZ ddl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 dd	lmZ erdd
lmZ ne	Z	 	 	 	 dd„Zdd„Z G d„ de«      Zy)u   MavvrikFocusLogger â€” FOCUS-based Mavvrik export logger.

Usage in config.yaml:
    litellm_settings:
      callbacks: ["mavvrik"]

Required env vars:
    MAVVRIK_API_KEY
    MAVVRIK_API_ENDPOINT
    MAVVRIK_CONNECTION_ID

Optional env vars:
    MAVVRIK_FOCUS_MAX_ROWS  â€” row cap per export window (default: 500000)

Only daily frequency is supported. The Mavvrik ingestion protocol stores one
file per calendar date (metrics/YYYY-MM-DD). Hourly or interval exports would
overwrite each other within the same day, producing incomplete data.
é    )ÚannotationsN)ÚdatetimeÚ	timedeltaÚtimezone)ÚTYPE_CHECKINGÚAnyÚFinal)Úverbose_proxy_logger)ÚMAVVRIK_FOCUS_EXPORT_JOB_NAME)ÚFocusTimeWindow)ÚFocusLogger)ÚAsyncIOSchedulerc                óâ  — | sy	 t        | t        t        f«      rAt        j                  t        | «      t
        j                  ¬«      j                  dddd¬«      S t        | t        «      rP| j                  «       } | sydD ]8  }	 t        j                  | |«      j                  t
        j                  ¬«      c S  t        j                  d| «       y# t        $ r Y Œ]w xY w# t        $ r Y Œ1w xY w)a\  Parse metricsMarker from Mavvrik register response into a UTC datetime.

    Handles both formats Mavvrik may return:
    - Unix timestamp (int/float): e.g. 1749340800
    - ISO date string: e.g. "2026-06-09" or "2026-06-09T00:00:00Z"

    Returns None for falsy values (0, None, empty string) which indicate
    no data has been ingested yet.
    N)Útzr   ©ÚhourÚminuteÚsecondÚmicrosecond)z%Y-%m-%dz%Y-%m-%dT%H:%M:%SZz%Y-%m-%dT%H:%M:%S)ÚtzinfouE   Mavvrik FOCUS: could not parse metricsMarker %r â€” skipping catch-up)Ú
isinstanceÚintÚfloatr   Úfromtimestampr   ÚutcÚreplaceÚstrÚstripÚstrptimeÚ
ValueErrorÚ	Exceptionr
   Úwarning)ÚmarkerÚfmts     ú|/home/oem/CyberBrain26-unified/.venv/lib/python3.12/site-packages/litellm/integrations/mavvrik_focus/mavvrik_focus_logger.pyÚ_parse_metrics_markerr&   &   sæ   € ñ ØðÜ�fœs¤E˜lÔ+Ü×)Ñ)¬%°«-¼H¿L¹LÔI×QÑQØ˜q¨¸ð Ró ð ô �fœcÔ"Ø—\‘\“^ˆFÙØàNò �ðÜ#×,Ñ,¨V°SÓ9×AÑAÌÏÉÐAÓVÒVðô × Ñ Ð!hÐjpÔqØøô "ò Ùðûäò ÙðúsH   …AC" Á"C" Á?C" Â3CÂ8C" Â;C" Ã	CÃC" ÃCÃC" Ã"	C.Ã-C.c                ó‚   — | €yt        | t        t        f«      r| dk(  S t        | t        «      r| j	                  «        S y)NTr   F)r   r   r   r   r   )r#   s    r%   Ú_is_empty_metrics_markerr(   I   s>   € Ø€~ØÜ�&œ3¤˜,Ô'Ø˜‰{ÐÜ�&œ#ÔØ—<‘<“>Ð!Ð!Øó    c                  ój   ‡ — e Zd ZdZdˆ fd„Z	 	 	 	 	 	 d	d„ZdZd
ˆ fd„Zd
d„Ze		 	 	 	 dd„«       Z
ˆ xZS )ÚMavvrikFocusLoggerzAFOCUS-based export logger that routes to the Mavvrik destination.c                óx  •— t        j                  dd«      j                  «       }|dk7  rt        d|› d�«      ‚t	        ‰| �  dddddt        j                  d«      t        j                  d	«      t        j                  d
«      dœdœ|¤Ž t        j                  d«      }|rt        |«      | _        y d| _        y )NÚMAVVRIK_FOCUS_FREQUENCYÚdailyzMAVVRIK_FOCUS_FREQUENCY='zÐ' is not supported. Only 'daily' is allowed -- the Mavvrik ingestion protocol stores one file per calendar date (metrics/YYYY-MM-DD). Hourly or interval exports would overwrite each other within the same day.ÚmavvrikÚcsvÚmavvrik_focus_exportsÚMAVVRIK_API_KEYÚMAVVRIK_API_ENDPOINTÚMAVVRIK_CONNECTION_ID)Úapi_keyÚapi_endpointÚconnection_id)ÚproviderÚexport_formatÚ	frequencyÚprefixÚdestination_configÚMAVVRIK_FOCUS_MAX_ROWSi ¡ © )ÚosÚgetenvÚlowerr    ÚsuperÚ__init__r   Ú	_max_rows)ÚselfÚkwargsr:   ÚrawÚ	__class__s       €r%   rC   zMavvrikFocusLogger.__init__V   s¿   ø€ ÜŸ9™9Ð%>ÀÓH×NÑNÓPˆ	Ø˜ÒÜØ+¨I¨;ð 7Jð Jóð ô 	‰Ñð 	
ØØØØ*äŸ9™9Ð%6Ó7Ü "§	¡	Ð*@Ó AÜ!#§¡Ð+BÓ!Cñ ñ	
ð ò	
ô —Y‘YÐ7Ó8ˆÙ14¤S¨£Xˆ�¸'ˆ�r)   c             ƒ  óÊ  K  — |�|n| j                   }| j                  «       }|j                  j                  ||j                  |j
                  ¬«      ƒ d{  –—† }|�Vt        |«      |k\  rHt        j                  d||j                  j                  «       |j
                  j                  «       «       d}|j                  «       rt        j                  d|«       nF|j                  j                  |«      }|j                  «       s|j                  j                  |«      }|j                   j#                  |xs d||j%                  |«      ¬«      ƒ d{  –—†  y7 �Œ7 Œ­w)zEExport with Mavvrik row cap applied when no explicit limit is passed.N)ÚlimitÚstart_time_utcÚend_time_utcu’   Mavvrik FOCUS export: row cap reached (%d rows). Some data for window %sâ†’%s may be excluded. Increase MAVVRIK_FOCUS_MAX_ROWS to export all rows.r)   z1Mavvrik FOCUS export: no usage data for window %s)ÚcontentÚtime_windowÚfilename)rD   Ú_ensure_engineÚ	_databaseÚget_usage_dataÚ
start_timeÚend_timeÚlenr
   r"   ÚdateÚis_emptyÚdebugÚ_transformerÚ	transformÚ_serializerÚ	serializeÚ_destinationÚdeliverÚ_build_filename)rE   ÚwindowrJ   Úeffective_limitÚengineÚdataÚpayloadÚ
normalizeds           r%   Ú_export_windowz!MavvrikFocusLogger._export_windown   sG  è ø€ ð +0Ð*;¡ÀÇÁˆØ×+Ñ+Ó-ˆØ"×,Ñ,×;Ñ;Ø!Ø!×,Ñ,ØŸ™ð <ó 
÷ 
ˆð
 Ð&¬3¨t«9¸Ò+GÜ ×(Ñ(ðFð  Ø×!Ñ!×&Ñ&Ó(Ø—‘×$Ñ$Ó&ôð ˆØ�=‰=Œ?Ü ×&Ñ&Ð'ZÐ\bÕcà &× 3Ñ 3× =Ñ =¸dÓ CˆJØ×&Ñ&Ô(Ø ×,Ñ,×6Ñ6°zÓB�Ø×!Ñ!×)Ñ)Ø’N˜sØØ×+Ñ+¨FÓ3ð *ó 
÷ 	
ñ 	
ð+
ùð*	
ús%   ‚AE#ÁEÁC?E#ÅE!ÅE#Å!E#é   c              ƒ  ó  •K  — | j                  «       }ddlm} |j                  }t	        ||«      st
        ‰| �  «       ƒ d{  –—†  y|j                  «       ƒ d{  –—† }t        j                  t        j                  «      }|j                  dddd¬«      t        d¬«      z
  }t        |«      }t        |«      }|t        | j                   dz
  ¬«      z
  }	|s|�ô||k  rï|€|	nt#        |t        d¬«      z   |	«      }
|�P|t        d¬«      z   |	k  r>t%        j&                  d| j                   |j)                  «       |
j)                  «       «       |
|k  r{t%        j*                  d|
j)                  «       «       t-        |
t        d¬«      z   |«      }t/        |
|d	¬
«      }| j1                  |d¬«      ƒ d{  –—†  |
t        d¬«      z  }
|
|k  rŒ{t/        ||d	¬
«      }| j1                  |d¬«      ƒ d{  –—†  y7 �Œ·7 �Œ¡7 ŒI7 Œ­w)u  Export today's window, catching up any dates Mavvrik has not yet received.

        On each run:
        1. Register with Mavvrik â†’ get metricsMarker (last successfully ingested date)
        2. If metricsMarker is behind yesterday (or 0/None for a fresh connector),
           catch up missed dates (capped at _MAX_CATCHUP_DAYS)
        3. Export yesterday (today's daily window)

        This ensures a failed export on day N is automatically retried on day N+1
        without any manual intervention.
        r   )ÚFocusMavvrikDestinationNr   é   )Údaysz…Mavvrik FOCUS export: metricsMarker is more than %d days behind (%s). Catching up from %s only; earlier data will not be re-exported.z0Mavvrik FOCUS export: catching up missed date %sr.   )rS   rT   r:   )r`   rJ   )rP   Ú;litellm.integrations.focus.destinations.mavvrik_destinationri   r]   r   rB   Ú_run_scheduled_exportÚget_metrics_markerr   Únowr   r   r   r   r&   r(   Ú_MAX_CATCHUP_DAYSÚmaxr
   r"   rV   ÚinfoÚminr   rf   )rE   rb   ri   Údestinationr#   ro   Ú	yesterdayÚlast_ingestedÚis_empty_markerÚearliest_catchupÚcatch_up_dateÚcatch_up_endr`   rH   s                €r%   rm   z(MavvrikFocusLogger._run_scheduled_export—   s  øè ø€ ð ×+Ñ+Ó-ˆõ	
ð $×0Ñ0ˆÜ˜+Ð'>Ô?Ü‘'Ñ/Ó1×1Ð1Øð *×<Ñ<Ó>×>ˆä—\‘\¤(§,¡,Ó/ˆØŸ;™;¨A°aÀÈq˜;ÓQÔT]ÐcdÔTeÑeˆ	ä4°VÓ<ˆä!9¸&Ó!AˆØ"+¬i¸T×=SÑ=SÐVWÑ=WÔ.XÑ"XÐÙ˜}Ð8¸]ÈYÒ=Và$1Ð$9Ñ ¼sÀ=ÔS\ÐbcÔSdÑCdÐfvÓ?wð ð Ð(¨]¼YÈAÔ=NÑ-NÐQaÒ-aÜ$×,Ñ,ð\à×*Ñ*Ø!×&Ñ&Ó(Ø!×&Ñ&Ó(ôð   )Ò+Ü$×)Ñ)ØFØ!×&Ñ&Ó(ôô  # =´9À!Ô3DÑ#DÀcÓJ�Ü(Ø,Ø)Ø%ô�ð
 ×)Ñ)°¸tÐ)ÓD×DÐDØ¤°Ô!2Ñ2�ð   )Ó+ô( !Ø ØØô
ˆð
 ×!Ñ!¨°tÐ!Ó<×<Ñ<ðk 2ùð
 ?ùðH Eøð 	=úsO   ƒA HÁG:ÁHÁG=ÁEHÆ6H Æ7HÇ$HÇ4HÇ5HÇ=HÈ HÈHc              ƒ  óØ  K  — ddl m} d}|�t        |dd«      }|�t        |dd«      }|rz|j                  rn|j	                  t
        ¬«      ƒ d{  –—† }|st        j                  d«       y	 | j                  «       ƒ d{  –—†  |j                  t
        ¬«      ƒ d{  –—†  y| j                  «       ƒ d{  –—†  y7 Œm7 Œ>7 Œ"# |j                  t
        ¬«      ƒ d{  –—†7   w xY w7 Œ/­w)u=   Scheduler entry point â€” uses Mavvrik-specific pod-lock key.r   )Úproxy_logging_objNÚdb_spend_update_writerÚpod_lock_manager)Ú
cronjob_idz0Mavvrik FOCUS export: unable to acquire pod lock)
Úlitellm.proxy.proxy_serverr|   ÚgetattrÚredis_cacheÚacquire_lockr   r
   rX   rm   Úrelease_lock)rE   r|   r~   ÚwriterÚacquireds        r%   Ú#initialize_mavvrik_focus_export_jobz6MavvrikFocusLogger.initialize_mavvrik_focus_export_jobá   sã   è ø€ å@àÐØÐ(Ü#Ð$5Ð7OÐQUÓVˆFØÐ!Ü#*¨6Ð3EÀtÓ#LÐ áÐ 0× <Ò <Ø$4×$AÑ$AÔMjÐ$AÓ$k×kˆHÙÜ$×*Ñ*Ð+]Ô^Øð^Ø×0Ñ0Ó2×2Ð2à&×3Ñ3Ô?\Ð3Ó]×]Ñ]à×,Ñ,Ó.×.Ñ.ð løð
 3øà]ùÐ&×3Ñ3Ô?\Ð3Ó]×]Ò]úà.úsf   ‚AC*ÁB>ÁC*Á.C ÂC ÂC ÂC*ÂCÂ C*Â8C(Â9C*Ã C ÃC*ÃC%ÃC!ÃC%Ã%C*c              ƒ  óØ  K  — t         j                  j                  t        ¬«      D �cg c]  }t	        |«      t        u r|‘Œ }}|s6dt         j
                  v r$ddlm}  |ddd¬«      }t        |t        «      r|g}|st        j                  d«       y|d   }|j                  «       } | j                  |j                  ft        dd	œ|¤Ž t        j                  d
|«       yc c}w ­w)z@Register the Mavvrik FOCUS export job on the provided scheduler.)Úcallback_typer/   r   )Ú$_init_custom_logger_compatible_classN)Úlogging_integrationÚinternal_usage_cacheÚ
llm_routerz4No MavvrikFocusLogger registered; skipping schedulerT)ÚidÚreplace_existingz3mavvrik_focus: background export job scheduled (%s))ÚlitellmÚlogging_callback_managerÚget_custom_loggers_for_typer+   ÚtypeÚ	callbacksÚ*litellm.litellm_core_utils.litellm_loggingrŠ   r   r
   rX   Ú_build_scheduler_triggerÚadd_jobr‡   r   rr   )Ú	schedulerÚcbÚloggersrŠ   ÚinstanceÚloggerÚtrigger_kwargss          r%   Ú!init_mavvrik_focus_background_jobz4MavvrikFocusLogger.init_mavvrik_focus_background_job÷   sü   è ø€ ô ×6Ñ6×RÑRÔasÐRÓtö-
àÜ�B‹xÔ-Ñ-ò ð-
ˆð -
ñ
 ˜9¬×(9Ñ(9Ñ9õñ CØ$-Ø%)ØôˆHô
 ˜(Ô$6Ô7Ø#˜*�ÙÜ ×&Ñ&Ð']Ô^Øà ™
ˆØ &× ?Ñ ?Ó AˆØˆ	×ÑØ×6Ñ6ð	
ä,Ø!ñ	
ð ò		
ô 	×!Ñ!Ð"WÐYgÕhùòA-
ùs   ‚'C*©C%ÁB'C*)rF   r   ÚreturnÚNone)r`   r   rJ   z
int | NonerŸ   r    )rŸ   r    )r˜   r   rŸ   r    )Ú__name__Ú
__module__Ú__qualname__Ú__doc__rC   rf   rp   rm   r‡   Ústaticmethodrž   Ú__classcell__)rH   s   @r%   r+   r+   S   sl   ø„ ÙKõBð0"
ð  ð"
ð ð	"
ð
 
ó"
ðN ÐõH=óT/ð, ð$iØ#ð$ià	ò$ió ô$ir)   r+   )r#   úobject | NonerŸ   zdatetime | None)r#   r§   rŸ   Úbool)r¤   Ú
__future__r   r?   r   r   r   Útypingr   r   r	   r�   Úlitellm._loggingr
   Úlitellm.constantsr   Ú,litellm.integrations.focus.destinations.baser   Ú'litellm.integrations.focus.focus_loggerr   Úapscheduler.schedulers.asyncior   r&   r(   r+   r>   r)   r%   ú<module>r°      sd   ðñõ& #ã 	ß 2Ñ 2ß ,Ñ ,ã Ý 1Ý ;Ý HÝ ?áÞ?àÐð Øð àó óFôIi˜õ Iir)   