o
    ưi                  	   @   sz  d dl Z d dlZd dlZd dlmZmZ d dlmZmZmZm	Z	m
Z
mZmZmZmZmZmZ d dlZd dlmZmZ d dlmZ d dlmZmZ d dlmZmZmZmZ d dlT d d	lm Z m!Z! d d
l"m#Z# erod dl$m%Z% neZ%da&dd Z'G dd deZ(	ddee) de*dee) de+fddZ,de+de
e)e)f fddZ-dee) de)de.fddZ/dee) de
e)e)f fddZ0dS )     N)datetime	timedelta)TYPE_CHECKINGAny	AwaitableCallableDictListLiteralOptionalTupleUnioncast)print_verboseverbose_loggerCustomLogger) get_litellm_metadata_from_kwargs&get_metadata_variable_name_from_kwargs) LiteLLM_DeletedVerificationTokenLiteLLM_TeamTableLiteLLM_UserTableUserAPIKeyAuth)*)_sanitize_prometheus_label_name _sanitize_prometheus_label_valueStandardLoggingPayload)AsyncIOSchedulerc                  C   s   t du rddlm}  | a t S )z
    Get cached get_end_user_id_for_cost_tracking function.
    Lazy imports on first call to avoid loading utils.py at import time (60MB saved).
    Subsequent calls use cached function for better performance.
    Nr   !get_end_user_id_for_cost_tracking)"_get_end_user_id_for_cost_trackingZlitellm.utilsr    r    r"   V/home/app/Keep/.python/lib/python3.10/site-packages/litellm/integrations/prometheus.py)_get_cached_end_user_id_for_cost_tracking4   s   r$   c                   @   s~  e Zd Zdd Zdeeee f fddZdedefddZ	d	ede
e fd
dZd	edee de
e fddZdedeeee f fddZd	edee fddZdeddfddZd	edee dee ddfddZdededdfddZd	efdd Zd!eeee f ddfd"d#Zd	edefd$d%Zd&d' Zd	edee fd(d)Zd*d+ Zd,ed-e
e d.e
e d/e
e d0e
e d1e
e d2e
e d3e
e d4efd5d6Zd,ed4efd7d8Z 	dd1e
e d2e
e d.e
e d/e
e d9e!d:e"d3e
e fd;d<Z#d-e
e d.e
e d/e
e d0e
e d1e
e d2e
e d3e
e d:e"d4efd=d>Z$	dd.e
e d/e
e d?e!d@e!dAe
e f
dBdCZ%d?e!d0e
e d.e
e d/e
e d1e
e d2e
e d4efdDdEZ&dFdG Z'			dd?e
e! d4e
e( dHe
e) de
e* fdIdJZ+	ddKe
e* dHe
e) defdLdMZ,					dd?e
e! dNe
e( d4e
e( d,e
e-e!ef  dHe
e) defdOdPZ.	ddQe!dRe)dNe/dSe
e fdTdUZ0dVe!dNe/fdWdXZ1ddYe(dZed[e(de(fd\d]Z2d^e!deee
e f fd_d`Z3d^e!fdadbZ4dce!d9e!dde
e dAe
e dee
e dfe
e fdgdhZ5	idd^e!d4edje"fdkdlZ6dmedne"doedpe
e dqef
drdsZ7e8dHe)defdtduZ9dved?e!dRe)fdwdxZ:dved?e!dRe)fdydzZ;d{e*ddedAe
e dee
e d|ef
d}d~Z<ddedAedeed|efddZ=ddedAe
e dee
e d|efddZ>ddedAe
e dee
e d|efddZ?ddedAedeed|edef
ddZ@defddZAdede"de"fddZBde
e" de
e" de"fddZCdeDdeEeFee( e
e* f  f deDee( geEd f deGd fddZHdd ZIdd ZJdd ZKdd ZLdd ZMdd ZNdee-ee/f  fddZOdeeP fddZQdeeR fddZSd1e
e d2e
e de
e" de
e" d:e"f
ddZTdedede
e" de
e" d:e"dePfddZUdePfddZVdNe/fddZWd.e
e d/e
e d:e"de
e" de
e" f
ddZXd.ed/ede
e" de
e" d:e"de/fddZYd3e
e de
e" de
e" d:e"fddńZZd3ede
e" de
e" d:e"deRf
ddǄZ[deRfddʄZ\de]de"fdd̈́Z^de(de(de
e" fddфZ_e8de`fddԄZae8ddք ZbdS )PrometheusLoggerc              
   K   s  zCddl m}m}m} |  | _| || _| || _| || _	| jdd| 
dd| _| jdd| 
dd| _| j	dd	| 
dtd
| _| j	dd| 
dtd
| _| j	dd| 
dtd
| _| jdd| 
dd| _| jdd| 
dd| _| jdd| 
dd| _| jdd| 
dd| _| jdd| 
dd| _| jdd| 
dd| _| jdd| 
dd| _| jdd| 
dd| _| jd d!| 
d d| _| jd"d#| 
d"d| _| jd$d%| 
d$d| _| jd&d'| 
d&d| _| jd(d)| 
d(d| _| jd*d+| 
d*d| _| jd,d-| 
d,d| _| jd.d/| 
d.d| _ | jd0d1| 
d0d| _!| j	d2d3| 
d2td
| _"| j	d4d5| 
d4td
| _#| j	d6d7g d8td
| _$| jd9d:g d;d| _%| jd<d=g d>d| _&| jd?d@dAgd| _'| jdBdC| 
dBd| _(| jdDdE| 
dDd| _)| jdFdG| 
dFd| _*| jdHdI| 
dHd| _+| jdJdK| 
dJd| _,| jdLdM| 
dLd| _-| jdNdO| 
dNd| _.| j	dPdQ| 
dPd| _/| dRdS| 
dR| _0| dTdU| 
dT| _1| jdVdWdXgd| _2| jdYdZ| 
dYd| _3| jd[d\| 
d[d| _4| jd]d^| 
d]d| _5| jd_d`| 
d_d| _6| jdadb| 
dad| _7| jdcddg d| _8| jdedfg d| _9W d S  t:y\ } zt;dgt<|  |d }~ww )hNr   )CounterGauge	Histogram$litellm_proxy_failed_requests_metriczjTotal number of failed responses from proxy - the client did not get a success response from litellm proxy)nameZdocumentation
labelnames#litellm_proxy_total_requests_metriczXTotal number of requests made to the proxy server - track number of client side requests$litellm_request_total_latency_metricz0Total latency (seconds) for a request to LiteLLM)r+   Zbucketslitellm_llm_api_latency_metricz1Total latency (seconds) for a models LLM API call*litellm_llm_api_time_to_first_token_metricz-Time to first token for a models LLM API calllitellm_spend_metriczTotal spend on LLM requests)r+   litellm_total_tokens_metricz7Total number of input + output tokens from LLM requestslitellm_input_tokens_metricz.Total number of input tokens from LLM requestslitellm_output_tokens_metricz/Total number of output tokens from LLM requests$litellm_remaining_team_budget_metriczRemaining budget for teamlitellm_team_max_budget_metriczMaximum budget set for team*litellm_team_budget_remaining_hours_metricz*Remaining days for team budget to be reset'litellm_remaining_api_key_budget_metriczRemaining budget for api key!litellm_api_key_max_budget_metriczMaximum budget set for api key-litellm_api_key_budget_remaining_hours_metricz.Remaining hours for api key budget to be reset$litellm_remaining_user_budget_metriczRemaining budget for userlitellm_user_max_budget_metriczMaximum budget set for user*litellm_user_budget_remaining_hours_metricz+Remaining hours for user budget to be reset,litellm_remaining_api_key_requests_for_modelzLRemaining Requests API Key can make for model (model based rpm limit on key)*litellm_remaining_api_key_tokens_for_modelzJRemaining Tokens API Key can make for model (model based tpm limit on key)!litellm_remaining_requests_metriczWLLM Deployment Analytics - remaining requests for model, returned from LLM API Providerlitellm_remaining_tokens_metricz:remaining tokens for model, returned from LLM API Providerlitellm_overhead_latency_metricz;Latency overhead (milliseconds) added by LiteLLM processing"litellm_request_queue_time_secondsz>Time spent in request queue before processing starts (seconds)Z!litellm_guardrail_latency_secondsz)Latency (seconds) for guardrail executionguardrail_namestatus
error_type	hook_typelitellm_guardrail_errors_totalz=Total number of errors encountered during guardrail executionrD   rF   rG    litellm_guardrail_requests_totalz%Total number of guardrail invocationsrD   rE   rG   (litellm_provider_remaining_budget_metriczHRemaining budget for provider - used when you set provider budget limitsapi_providerlitellm_deployment_statezlLLM Deployment Analytics - The state of the deployment: 0 = healthy, 1 = partial outage, 2 = complete outagelitellm_deployment_tpm_limitz$Deployment TPM limit found in configlitellm_deployment_rpm_limitz$Deployment RPM limit found in configlitellm_deployment_cooled_downzLLM Deployment Analytics - Number of times a deployment has been cooled down by LiteLLM load balancing logic. exception_status is the status of the exception that caused the deployment to be cooled down$litellm_deployment_success_responseszOLLM Deployment Analytics - Total number of successful LLM API calls via litellm$litellm_deployment_failure_responseszLLM Deployment Analytics - Total number of failed LLM API calls for a specific LLM deploymeny. exception_status is the status of the exception from the llm api!litellm_deployment_total_requestszXLLM Deployment Analytics - Total number of LLM API calls via litellm - success + failure+litellm_deployment_latency_per_output_tokenz3LLM Deployment Analytics - Latency per output token'litellm_deployment_successful_fallbackszfLLM Deployment Analytics - Number of successful fallback requests from primary model -> fallback model#litellm_deployment_failed_fallbackszbLLM Deployment Analytics - Number of failed fallback requests from primary model -> fallback model(litellm_callback_logging_failures_metriczTTotal number of failures when emitting logs to callbacks (e.g. s3_v2, langfuse, etc)callback_name&litellm_llm_api_failed_requests_metricz5deprecated - use litellm_proxy_failed_requests_metriclitellm_requests_metriczdeprecated - use litellm_proxy_total_requests_metric. Total number of LLM calls to litellm - track total per API Key, team, userlitellm_cache_hits_metricz"Total number of LiteLLM cache hitslitellm_cache_misses_metricz$Total number of LiteLLM cache misseslitellm_cached_tokens_metricz&Total tokens served from LiteLLM cacheZlitellm_total_usersz Total number of users in LiteLLMZlitellm_teams_countz Total number of teams in LiteLLMz(Got exception on init prometheus client )=prometheus_clientr&   r'   r(   _parse_prometheus_configlabel_filters_create_metric_factoryZ_counter_factoryZ_gauge_factoryZ_histogram_factoryget_labels_for_metricr)   r,   ZLATENCY_BUCKETSr-   r.   r/   r0   litellm_tokens_metricr2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   !litellm_request_queue_time_metric litellm_guardrail_latency_metricrH   rJ   rL   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rZ   r[   r\   r]   r^   litellm_total_users_metriclitellm_teams_count_metric	Exceptionr   str)selfkwargsr&   r'   r(   er"   r"   r#   __init__D   sF  
								

	zPrometheusLogger.__init__returnc           
      C   s   ddl }ddlm} |j}|si S td|  g }t | _|D ]}t|t	r0|di |}n|}|
| | j|j q!| |}|jrX| | dd|j }t|| |}	| |	 |	S )zNParse prometheus metrics configuration for label filtering and enabled metricsr   N)PrometheusMetricsConfigzprometheus config: z!Configuration validation failed:

r"   )litellm%litellm.types.integrations.prometheusrp   Zprometheus_metrics_configr   debugsetenabled_metrics
isinstancedictappendupdatemetrics_validate_all_configurationsZ
has_errors_pretty_print_validation_errorsjoinZall_error_messages
ValueError_build_label_filters_pretty_print_prometheus_config)
rk   rr   rp   configparsed_configsZgroup_configZparsed_configvalidation_resultserror_messagera   r"   r"   r#   r`     s0   





z)PrometheusLogger._parse_prometheus_configr   c                 C   sf   g }g }|D ]&}|j D ] }| |}|r|| q|jr+| ||j}|r+|| qqt||dS )z>Validate all metric configurations and return collected errors)metric_errorslabel_errors)r{   _validate_single_metric_namery   include_labels_validate_single_metric_labelsValidationResults)rk   r   r   r   r   metric_namemetric_errorlabel_errorr"   r"   r#   r|     s"   



z-PrometheusLogger._validate_all_configurationsr   c                 C   s0   ddl m} |t|tvrt||tdS dS )zValidate a single metric namer   )get_args)r   valid_metricsN)typingr   ru   DEFINED_PROMETHEUS_METRICSMetricValidationError)rk   r   r   r"   r"   r#   r     s   z-PrometheusLogger._validate_single_metric_namelabelsc                    sD   ddl m} t|t|  fdd|D }|r t|| dS dS )z#Validate labels for a single metricr   )r   c                    s   g | ]}| vr|qS r"   r"   .0labelvalid_labelsr"   r#   
<listcomp>  s    zCPrometheusLogger._validate_single_metric_labels.<locals>.<listcomp>r   invalid_labelsr   N)r   r   PrometheusMetricLabels
get_labelsr   LabelValidationError)rk   r   r   r   r   r"   r   r#   r     s   z/PrometheusLogger._validate_single_metric_labelsc                 C   s<   i }|D ]}|j D ]}|jr| |du r|j||< q	q|S )z1Build label filters from validated configurationsN)r{   r   r   )rk   r   ra   r   r   r"   r"   r#   r   %  s   

z%PrometheusLogger._build_label_filtersc                 C   s4   |  ||}|r| j|j|j|jd t|jdS )z
        Ensure that all the configured labels are valid for the metric

        Raises ValueError if the metric labels are invalid and pretty prints the error
        r   T)r   "_pretty_print_invalid_labels_errorr   r   r   r   message)rk   r   r   r   r"   r"   r#   "_validate_configured_metric_labels2  s   
z3PrometheusLogger._validate_configured_metric_labelsr   Nc                 C   s  zddl m} ddlm} ddlm} ddlm} | }|ddd}|d	 |||d
d |j	rxdd |j	D }|j	d j
}	|dd| dd}
|||
d
d |dddddd}|jdddd t|	D ]}|| qk|| |jr|jD ]D}|d|j dd|j dd}|||d
d |d|j dddddd}|jdddd t|jD ]}|| q|| q~|d	 W dS  ty   |j	D ]}t|j q|jD ]}t|j qY dS w )z-Pretty print all validation errors using richr   ConsolePanelTableTextu(   🚨🚨 Configuration Validation Errorsbold redstylerq   redborder_stylec                 S   s   g | ]}|j qS r"   r   )r   rm   r"   r"   r#   r   \  s    zDPrometheusLogger._pretty_print_validation_errors.<locals>.<listcomp>zInvalid Metric Names: ,    📊 Valid Metric NamesT
bold greenleftgreentitleshow_headerheader_styletitle_justifyr   Available Metricscyanr   no_wrapzInvalid Labels for '': u   🏷️ Valid Labels for ''Valid LabelsN)rich.consoler   
rich.panelr   
rich.tabler   	rich.textr   printr   r   r~   
add_columnsortedadd_rowr   r   r   r   ImportErrorr   errorr   )rk   r   r   r   r   r   consoler   Zinvalid_metricsr   Zmetrics_error_textmetrics_tablemetricr   Zlabels_error_textlabels_tabler   r   r   r"   r"   r#   r}   G  s|   




z0PrometheusLogger._pretty_print_validation_errorsr   r   c                 C   s   zcddl m} ddlm} ddlm} ddlm} | }|d| dd| d	d
d}	|dddddd}
|
j	dddd t
|D ]}|
| qA|d |||	dd ||
 |d W dS  ty}   td| d| dt
|  Y dS w )z8Pretty print error message for invalid labels using richr   r   r   r   r   u%   🚨🚨 Invalid Labels for Metric: 'z'
Invalid labels: r   z'
Please specify only valid labels belowr   r   u$   🏷️ Valid Labels for this MetricTr   r   r   r   r   r   r   rq   r   r   zInvalid labels for metric 'r   z. Valid labels: N)r   r   r   r   r   r   r   r   r~   r   r   r   r   r   r   r   )rk   r   r   r   r   r   r   r   r   r   r   r   r"   r"   r#   r     s:   


z3PrometheusLogger._pretty_print_invalid_labels_errorinvalid_metric_namer   c              
   C   s   z]ddl m} ddlm} ddlm} ddlm} | }|d| ddd	}|d
ddddd}	|	jdddd t	|D ]}
|	
|
 q;|d |||dd ||	 |d W dS  tyt   td| dt	|  Y dS w )z=Pretty print error message for invalid metric name using richr   r   r   r   r   u   🚨🚨 Invalid Metric Name: 'z1'
Please specify one of the allowed metrics belowr   r   r   Tr   r   r   r   r   r   r   rq   r   r   zInvalid metric name: z. Valid metrics: N)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rk   r   r   r   r   r   r   r   r   r   r   r"   r"   r#   "_pretty_print_invalid_metric_error  s:   



z3PrometheusLogger._pretty_print_invalid_metric_errorc                 C   s.   |  |}|r| j|j|jd t|jdS )z]
        Raises ValueError if the metric name is invalid and pretty prints the error
        )r   r   N)r   r   r   r   r   r   )rk   r   r   r"   r"   r#   _valid_metric_name  s   

z#PrometheusLogger._valid_metric_namera   c              	   C   s  zddl m} ddlm} ddlm} ddlm} | }|ddd}|d	d
ddd}|jddd
d t	| drH| j
rHt| j
D ]}	||	 q?n|d |dd
ddd}
|
jddd
d |
jddd |rt| D ]\}}|rwd|nd}|
|| qln|
dd |d |||dd || ||
 |d W d!S  ty   tdt	| drt| j
nd  td |  Y d!S w )"z>Pretty print the processed prometheus configuration using richr   r   r   r   r   z"Prometheus Configuration Processedz	bold bluer   u   📊 Enabled MetricsTzbold magentar   )r   r   r   r   zMetric Namer   r   rv   z8[yellow]All metrics enabled (no filter applied)[/yellow]u   🏷️  Label Filtersr   zAllowed Labelsyellowr   z[dim]No labels specified[/dim]z+[yellow]No label filtering applied[/yellow]z*[dim]All default labels will be used[/dim]rq   bluer   zEnabled metrics: zAll metricszLabel filters: N)r   r   r   r   r   r   r   r   r   hasattrrv   r   r   itemsr~   r   r   r   info)rk   ra   r   r   r   r   r   r   r   r   r   r   r   Z
labels_strr"   r"   r#   r     sh   


z0PrometheusLogger._pretty_print_prometheus_configc                 C   s"   t | dsdS | jsdS || jv S )z3Check if a metric is enabled based on configurationrv   T)r   rv   )rk   r   r"   r"   r#   _is_metric_enabledD  s
   

z#PrometheusLogger._is_metric_enabledc                    s    fdd}|S )zMCreate a factory function that returns either a real metric or a no-op metricc                     s6   | r| d n| dd}|r | i |S t S )Nr   r*    )getr   Z
NoOpMetric)argsrl   r   metric_classrk   r"   r#   factoryS  s   
z8PrometheusLogger._create_metric_factory.<locals>.factoryr"   )rk   r   r   r"   r   r#   rb   P  s   	z'PrometheusLogger._create_metric_factoryc                    s8   t |}|| jvr|S | j|   fdd|D }|S )zE
        Get the labels for a metric, filtered if configured
        c                    s   g | ]}| v r|qS r"   r"   r   Zconfigured_labelsr"   r#   r   o  s    z:PrometheusLogger.get_labels_for_metric.<locals>.<listcomp>)r   r   ra   )rk   r   Zdefault_labelsfiltered_labelsr"   r   r#   rc   ^  s   



z&PrometheusLogger.get_labels_for_metricc                    sZ  ddl m} td|  |d}|d u st|ts$td| | j||dr-d S |dd}|d	i p:i }|d
pAi }	t	 }
|
|dd}|d
 d }|d
 d }|d
 d }|d
 d }|d
 d }|d }|d }|d }|d
 d}|d
 d}i |r|ni |r|ni }|d urt|tr|d }ng }t
d| d| d| d| d| 
 tdDi d|d|d|d |d! d!|d! d"|d#|d$|d%|d
 d& d'd(d|d)|d*|d+|d+ d,|d, d-|d. d/d d0d d1t|d2d3|d
 d4d5|d
 d6d7|d
 d7d8tjr%t|d8nd }|d urDt|trD|d9rDdd:lm} ||}| j|||||||||d;	 | j|||||||||d<	 | j|||||||d=I d H  | j||||	|jd> | j|||||||d? | ||||| | j||d@ t| jdAdB|dC}| jjdDi |  d S )ENr   r   z@prometheus Logging - Enters success logging function for kwargs standard_logging_objectz)standard_logging_object is required, got=rl   standard_logging_payloadmodelr   litellm_paramsmetadata
prometheusservice_typeuser_api_key_user_iduser_api_key_hashuser_api_key_aliasuser_api_key_team_iduser_api_key_team_aliascompletion_tokenstotal_tokensresponse_costZrequester_metadatauser_api_key_auth_metadatarequest_tagsz'inside track_prometheus_metrics, model z, response_cost z, tokens_used z, end_user_id z, user_api_key end_userhashed_api_keyapi_key_aliasrequested_modelmodel_groupteam
team_aliasuser
user_emailZuser_api_key_user_emailstatus_codeZ200litellm_model_nametagsmodel_idapi_baserM   custom_llm_providerexception_statusexception_classcustom_metadata_labelsr   routeZuser_api_key_request_route	client_iprequester_ip_address
user_agentstreamzsk-)
hash_token)	end_user_iduser_api_keyr   r   user_api_teamuser_api_team_aliasuser_idr   enum_values)	r   r  r  r   r   r  r  r  r  )r  r  r  r   r   r   r  )r  r   rl   r   r  )rl   r   r  r   r  r  r  )r   r  r,   r   supported_enum_labelsr  r"   ) litellm.types.utilsr   r   rt   r   rw   rx   r   $_should_skip_metrics_for_invalid_keyr$   r   UserAPIKeyLabelValuesget_custom_labels_from_metadatarr   prometheus_emit_stream_labelrj   
startswithZlitellm.proxy.utilsr  ._increment_top_level_request_and_spend_metrics_increment_token_metrics#_increment_remaining_budget_metrics#_set_virtual_key_rate_limit_metricsr  _set_latency_metrics"set_llm_deployment_success_metrics_increment_cache_metricsprometheus_label_factoryrc   r,   r   inc)rk   rl   response_obj
start_timeend_timer   r   r   r   	_metadatar    r  r  r  r   r  r  output_tokensZtokens_usedr   Z_requester_metadatar   Zcombined_metadata_tagsr  r  _labelsr"   r"   r#   async_log_success_eventu  sd  




 	

!	
z(PrometheusLogger.async_log_success_eventr   r  r  r   r   r  r  r  r  c
                 C   s   t d |d urt|tr|d }
t| jdd|	d}| jjdi ||d  t| jdd|	d}| j	jdi ||d  t| jd	d|	d}| j
jdi ||d
  d S )Nz2prometheus Logging - Enters token metrics functionr   r1   r   r  r   r2   Zprompt_tokensr3   r   r"   )r   rt   rw   rx   r#  rc   rd   r   r$  r2   r3   )rk   r   r  r  r   r   r  r  r  r  r*  r+  r"   r"   r#   r  4  s@   

z)PrometheusLogger._increment_token_metricsc                 C   s   | d}|du rdS |du rHt| jdd|d}| jjdi |  | dd}|dkrFt| jd	d|d}| jjdi || dS dS t| jd
d|d}| jjdi |  dS )z
        Increment cache-related Prometheus metrics based on cache hit/miss status.

        Args:
            standard_logging_payload: Contains cache_hit field (True/False/None)
            enum_values: Label values for Prometheus metrics
        	cache_hitNTr\   r   r  r   r   r^   r]   r"   )r   r#  rc   r\   r   r$  r^   r]   )rk   r   r  r-  r+  r   r"   r"   r#   r"  g  s8   

z)PrometheusLogger._increment_cache_metricsr   r   c              	      s   | dpi }| dd }	| dd }
| dd }| dd }| dd }| dd }tj| j|||||d| j|||	|
|d	| j||||d
ddI d H }t|D ]\}}t|trkt	
dg d|  d|  qSd S )Nr   Zuser_api_key_team_spendZuser_api_key_team_max_budgetZuser_api_key_spendZuser_api_key_max_budgetZuser_api_key_user_spendZuser_api_key_user_max_budget)r  r   r   key_max_budget	key_spend)r  r  
team_spendteam_max_budgetr   )r  
user_spenduser_max_budgetr   T)return_exceptionsz0[Non-Blocking] Prometheus: Budget metric lookup )keyr   r   z	 failed: )r   asynciogather-_set_api_key_budget_metrics_after_api_request*_set_team_budget_metrics_after_api_request*_set_user_budget_metrics_after_api_request	enumeraterw   ri   r   rt   )rk   r  r  r  r   r   r   r  r(  Z_team_spendZ_team_max_budgetZ_api_key_spendZ_api_key_max_budgetZ_user_spendZ_user_max_budgetresultsirr"   r"   r#   r    sL   

z4PrometheusLogger._increment_remaining_budget_metricsc
                 C   sZ   t | jdd|	d}
| jjdi |
  t | jdd|	d}
| jjdi |
| d S )Nr[   r   r  r0   r"   )r#  rc   r[   r   r$  r0   )rk   r  r  r   r   r  r  r  r   r  r+  r"   r"   r#   r    s   z?PrometheusLogger._increment_top_level_request_and_spend_metricsrl   r   r  c                 C   s   ddl m} ||}d| }d| }	||tjptj}
||	tjp'tj}| jt|t|t|t||
 | j	t|t|t|t|| d S )Nr   )#get_model_group_from_litellm_kwargszlitellm-key-remaining-requests-zlitellm-key-remaining-tokens-)
Z)litellm.proxy.common_utils.callback_utilsr?  r   sysmaxsizer=   r   r   ru   r>   )rk   r  r   rl   r   r  r?  r   Z remaining_requests_variable_nameZremaining_tokens_variable_nameremaining_requestsremaining_tokensr"   r"   r#   r    s.   
z4PrometheusLogger._set_virtual_key_rate_limit_metricsc                 C   s  | dpt }| d}	| dd }
| dd }| j|
|d}|d urD| dddu rDt| jd	d
|d}| jjdi || nt	
d | j|
|d}|d urjt| jdd
|d}| jjdi || | j|	|d}|d urt| jdd
|d}| jjdi || | di pi }| dpi  d}|d ur|dkrt| jdd
|d}| jjdi || d S d S d S )Nr'  r&  api_call_start_timecompletion_start_time)r&  r'  r  FTr/   r   r  zUTime to first token metric not emitted, stream option in model_parameters is not Truer.   r-   r   r   queue_time_secondsr   rB   r"   )r   r   now_safe_duration_secondsr#  rc   r/   r   observer   rt   r.   r-   re   )rk   rl   r   r  r   r  r  r  r'  r&  rD  rE  Ztime_to_first_token_secondsZ_ttft_labelsZapi_call_total_time_secondsr+  Ztotal_time_seconds_litellm_paramsrF  r"   r"   r#   r     s   


z%PrometheusLogger._set_latency_metricsc                    s8  ddl m} td|  |di }| j||drd S |dd}|di p+i }t }	|	|d	d
}
|d d }|d d }|d d }|d d }|d d }z+| jt	|
t	|t	|t	|t	|t	|t	|t	|dd
  | | W d S  ty } ztdt| W Y d }~d S d }~ww )Nr   r   z@prometheus Logging - Enters failure logging function for kwargs r   r   r   r   r   r   r   r   r   r   r   r   r   r  0prometheus Layer Error(): Exception occured - {})r  r   r   rt   r   r  r$   rZ   r   r   r$  "set_llm_deployment_failure_metricsri   	exceptionformatrj   )rk   rl   r%  r&  r'  r   r   r   r   r    r  r  r  r   r  r  rm   r"   r"   r#   async_log_failure_eventc  s^   	
z(PrometheusLogger.async_log_failure_eventrM  c              	   C   s   d}|rt |dr|jrzt|j}W n ttfy   Y nw |sG|rGt|ddp.t|dd}|durGzt|}W n ttfyF   d}Y nw |sx|rx|d}|rxt|ddp]t|dd}|durxzt|}W |S  ttfyw   d}Y |S w |S )aT  
        Extract HTTP status code from various input formats for validation.

        This is a centralized helper to extract status code from different
        callback function signatures. Handles both ProxyException (uses 'code')
        and standard exceptions (uses 'status_code').

        Args:
            kwargs: Dictionary potentially containing 'exception' key
            enum_values: Object with 'status_code' attribute
            exception: Exception object to extract status code from directly

        Returns:
            Status code as integer if found, None otherwise
        Nr   coderM  )r   r   intr   	TypeErrorgetattrr   )rk   rl   r  rM  r   Zexception_in_kwargsr"   r"   r#   _extract_status_code  sN   


z%PrometheusLogger._extract_status_coder   c                    sF   |dkrdS |dur!t |  g d}t fdd|D r!dS dS )a  
        Determine if a request has an invalid API key based on status code and exception.

        This method prevents invalid authentication attempts from being recorded in
        Prometheus metrics. A 401 status code is the definitive indicator of authentication
        failure. Additionally, we check exception messages for authentication error patterns
        to catch cases where the exception hasn't been converted to a ProxyException yet.

        Args:
            status_code: HTTP status code (401 indicates authentication error)
            exception: Exception object to check for auth-related error messages

        Returns:
            True if the request has an invalid API key and metrics should be skipped,
            False otherwise
        i  TN)zvirtual key expectedzexpected to start with 'sk-'zauthentication errorzinvalid api keyzapi key not validc                 3   s    | ]}| v V  qd S Nr"   )r   patternZexception_strr"   r#   	<genexpr>  s    z?PrometheusLogger._is_invalid_api_key_request.<locals>.<genexpr>F)rj   lowerany)rk   r   rM  Zauth_error_patternsr"   rW  r#   _is_invalid_api_key_request  s   z,PrometheusLogger._is_invalid_api_key_requestuser_api_key_dictc                 C   s`   | j |||d}|du r|r|d}| j||dr.td| d|r't|jnd  dS dS )	aD  
        Determine if Prometheus metrics should be skipped for invalid API key requests.

        This is a centralized validation method that extracts status code and exception
        information from various callback function signatures and determines if the request
        represents an invalid API key attempt that should be filtered from metrics.

        Args:
            kwargs: Dictionary potentially containing exception and other data
            user_api_key_dict: User API key authentication object (currently unused)
            enum_values: Object with status_code attribute
            standard_logging_payload: Standard logging payload dictionary
            exception: Exception object to check directly

        Returns:
            True if metrics should be skipped (invalid key detected), False otherwise
        )rl   r  rM  NrM  rM  zESkipping Prometheus metrics for invalid API key request: status_code=z, exception=TF)rT  r   r[  r   rt   type__name__)rk   rl   r\  r  r   rM  r   r"   r"   r#   r    s"   
z5PrometheusLogger._should_skip_metrics_for_invalid_keyrequest_dataoriginal_exceptiontraceback_strc              
      s$  ddl m} | j||drdS | j|d}z|j||di d}|di p)i }|d	i d
p;|d	i d
}	td$i d|jd|jd|j	d|j
d|jd|jd|jd|dddt|dt|d| |d|d|jd|dd|dd|	dtjrt|dn1d}
t| jdd |
d!}| jjd$i |  t| jd"d |
d!}| jjd$i |  W dS }
t| jdd |
d!}| jjd$i |  t| jd"d |
d!}| jjd$i |  W dS  ty } ztd#t| W Y d}~dS d}~ww )%ar  
        Track client side failures

        Proxy level tracking - failed client side requests

        labelnames=[
                    "end_user",
                    "hashed_api_key",
                    "api_key_alias",
                    REQUESTED_MODEL,
                    "team",
                    "team_alias",
                ] + EXCEPTION_LABELS,
        r   )StandardLoggingPayloadSetup)r\  rM  Nr]  proxy_server_request)r   rd  r   
model_infoidr   r   r   r   r   r   r   r   r   r   r   r  r  r   r  r	  r
  r  r  r  r)   r   r  r,   rK  r"   )*litellm.litellm_core_utils.litellm_loggingrc  r  rT  Z_get_request_tagsr   r  r  r  r   api_key	key_aliasteam_idr   rj   _get_exception_class_nameZrequest_routerr   r  r#  rc   r)   r   r$  r,   ri   r   rM  rN  )rk   r`  ra  r\  rb  rc  r   r*  r(  r  r  r+  rm   r"   r"   r#   async_post_call_failure_hook#  s   
	



z-PrometheusLogger.async_post_call_failure_hookdatac                    s   dS )a^  
        Proxy level tracking - triggered when the proxy responds with a success response to the client

        Note: litellm_proxy_total_requests_metric is NOT incremented here to avoid
        double-counting. It is incremented in async_log_success_event which fires
        for all successful requests (both streaming and non-streaming).
        Nr"   )rk   rm  r\  responser"   r"   r#   async_post_call_success_hookx  s   
z-PrometheusLogger.async_post_call_success_hookobjr5  defaultc                 C   s.   |du r|S t |tr|||S t|||S )z&Get value from dict or Pydantic model.N)rw   rx   r   rS  )rk   rp  r5  rq  r"   r"   r#   	_safe_get  s
   
zPrometheusLogger._safe_getrequest_kwargsc           	   	      s>  | di pi }| di pi }| |dpi }t|tr |n!t|ddt|ddt|ddt|ddt|d	dt|d
dd| di pHi    ddtt f fdd}dtt f fdd}dtt f fdd}dtt f fdd}| | | |  d	p  d	 d
p  d
dS )z
        Extract label values for deployment failure metrics from all available
        sources in request_kwargs. Falls back to litellm_params metadata and
        user_api_key_auth when standard_logging_payload has None values.
        r   r   r   r   Nr   r   r   r
  r  )r   r   r   r   r
  r  user_api_key_authro   c                     D    d} | d ur| S   d} | d ur| S d ur tdd S d S )Nr   ri  r   rS  valZ_litellm_params_metadatar(  rt  r"   r#   _get_api_key_alias     

zUPrometheusLogger._extract_deployment_failure_label_values.<locals>._get_api_key_aliasc                     ru  )Nr   rj  rv  rw  ry  r"   r#   _get_team_id  r{  zOPrometheusLogger._extract_deployment_failure_label_values.<locals>._get_team_idc                     ru  )Nr   r   rv  rw  ry  r"   r#   _get_team_alias  r{  zRPrometheusLogger._extract_deployment_failure_label_values.<locals>._get_team_aliasc                     sP    d} | d ur| S   d} | d ur| S d ur&tdd p%tdd S d S )Nr   rh  Zapi_key_hashrv  rw  ry  r"   r#   _get_hashed_api_key  s   

zVPrometheusLogger._extract_deployment_failure_label_values.<locals>._get_hashed_api_key)r   r   r   r   r	  r  )r   rr  rw   rx   rS  r   rj   )	rk   rs  r   rJ  Z_metadata_rawrz  r|  r}  r~  r"   ry  r#   (_extract_deployment_failure_label_values  sH   	





z9PrometheusLogger._extract_deployment_failure_label_valuesc                 C   s  zDt d |di }|di pi }|dd}|dd}|dd}|dd}|d	d}|du rR|d
p=i dpL|dpGi dpLi }	|	d}|du rj|d
p\i dpi|dpfi d}|dd}
| j||drzW dS | |}|di pi }|dp|d}|dp|d}|dp|d}|dp|d}|dp|d}|dp|d}d}|durtt|dd}|dks|st|dd}|durt|}t||||
||r| |nd|p||||||dg ||d}	 | j	|pd |||
pd d! |dur.t
| jd"d#|d$}| jjd'i |  t
| jd%d#|d$}| jjd'i |  W dS  tyc } zt d&t| W Y d}~dS d}~ww )(a  
        Sets Failure metrics when an LLM API call fails

        - mark the deployment as partial outage
        - increment deployment failure responses metric
        - increment deployment total requests metric

        Args:
            request_kwargs: dict

        (setting remaining tokens requests metricr   r   r   Nr   r  r  rM  Zlitellm_metadatare  r   rf  r  r   r   r   r   r   r   r   r   r   r	  r
  r  r   NonerP  r   )r   r  r  rM   r  r  r   r   r   r   r   r   r	  r  r   r   r  r  rM   rS   r   r  rT   zLPrometheus Error: set_llm_deployment_failure_metrics. Exception occured - {}r"   )r   rt   r   r  r  rj   rS  r  rk  set_deployment_partial_outager#  rc   rS   r   r$  rT   ri   rN  )rk   rs  r   rJ  r   r   r  r  rM  _model_infollm_providerZfallback_valuesr(  r   r   r   r   r	  r  r  rP  r  r+  rm   r"   r"   r#   rL    s   



z3PrometheusLogger.set_llm_deployment_failure_metricsre  r   r  r  c           
      C   s   | dp	| d}| dp| d}|dur4t| jddt||||dd}	| jjd	i |	| |durVt| jddt||||dd}	| jjd	i |	| dS dS )
z?
        Set the deployment TPM and RPM limits metrics
        tpmrpmNrO   r   r  r  rP   r"   )r   r#  rc   r  rO   r   ru   rP   )
rk   re  r   r   r  r  r  r  r  r+  r"   r"   r#   %_set_deployment_tpm_rpm_limit_metricso  s:   z6PrometheusLogger._set_deployment_tpm_rpm_limit_metrics      ?r)  c              
   C   s  zPt d |d}|d u rW d S | j|||drW d S |d }|di p)i }t|}	|dd }
|dd }|	dp@i }|d	d }|sK|rV| j|||
|||d
 d }d }|d d  }rn|dd }|dd }|d d }rt| jdd|d}| jj	d i |
|d  |r	 t| jdd|d}| jj	d i || |rt| jdd|d}| jj	d i || 	 | j|
pd|pd|pd|pdd t| jdd|d}| jj	d i |  t| jdd|d}| jj	d i |  || }d }|dd d ur|d du r|d|| }|p|}| }d }|d urL|dkrO|| }t| jdd|d}| jj	d i |
| W d S W d S W d S  tyo } zt dt| W Y d }~d S d }~ww )!Nr  r   )rl   r  r   r  r   r   r  re  rf  )re  r   r   r  r  r  Zhidden_paramsadditional_headersZx_ratelimit_remaining_requestsZx_ratelimit_remaining_tokenslitellm_overhead_time_msrA   r   r  i  r?   r@   r   r  rR   rT   r  TrE  r   rU   zLPrometheus Error: set_llm_deployment_success_metrics. Exception occured - {}r"   )r   rt   r   r  r   r  r#  rc   rA   r   rI  r?   ru   r@   set_deployment_healthyrR   r$  rT   total_secondsrU   ri   rM  rN  rj   )rk   rs  r&  r'  r  r)  r   r  rJ  r(  r   r  r  r  rB  rC  r  r  r+  Zresponse_msZ!time_to_first_token_response_timeZ_latencyZ_latency_secondsZlatency_per_tokenrm   r"   r"   r#   r!    s   
	

z3PrometheusLogger.set_llm_deployment_success_metricsrD   latency_secondsrE   rF   rG   c              
   C   s   z4| j j|||p	d|d| | jj|||d  |dkr/|r2| jj|||d  W dS W dS W dS  tyQ } ztdt	|  W Y d}~dS d}~ww )a\  
        Record guardrail metrics for prometheus.

        Args:
            guardrail_name: Name of the guardrail
            latency_seconds: Execution latency in seconds
            status: "success" or "error"
            error_type: Type of error if any, None otherwise
            hook_type: "pre_call", "during_call", or "post_call"
        nonerC   rK   r   rI   z#Error recording guardrail metrics: N)
rf   r   rI  rJ   r$  rH   ri   r   rt   rj   )rk   rD   r  rE   rF   rG   rm   r"   r"   r#   _record_guardrail_metrics?  s4   "z*PrometheusLogger._record_guardrail_metricsc                 C   sT   d}t | drt| dpd}t|dkr"|d  |dd   d }|| jj7 }|S )Nr   r     r   .)r   rS  lenupper	__class__r_  )rM  Zexception_class_namer"   r"   r#   rk  k  s   
z*PrometheusLogger._get_exception_class_nameoriginal_model_groupc                    s   ddl m}m} td|| t|}||pi }|j|d}|d}	tt	t
 |dp0g }
t||	|d |d |d	 |d
 t
t|dd| ||
d	}t| jdd|d}| jjdi |  dS )zF

        Logs a successful LLM fallback event on prometheus

        r   StandardLoggingMetadatarc  zLPrometheus: log_success_fallback_event, original_model_group: %s, kwargs: %sr  r   r   r   r   r   r   r   N	r   Zfallback_modelr   r   r   r   r  r  r   rV   r   r  r"   )rg  r  rc  r   rt   r   r   get_standard_logging_metadatar   r	   rj   r  rS  rk  r#  rc   rV   r   r$  )rk   r  rl   ra  r  rc  _metadata_keyr(  standard_metadata
_new_modelr*  r  r+  r"   r"   r#   log_success_fallback_event{  sB   
z+PrometheusLogger.log_success_fallback_eventc                    s   ddl m}m} td|| |d}t|}||pi }ttt	 |dp*g }	|j
|d}
t|||
d |
d |
d	 |
d
 t	t|dd| ||	d	}t| jdd|d}| jjdi |  dS )z@
        Logs a failed LLM fallback event on prometheus
        r   r  zLPrometheus: log_failure_fallback_event, original_model_group: %s, kwargs: %sr   r   r  r   r   r   r   r   Nr  rW   r   r  r"   )rg  r  rc  r   rt   r   r   r   r	   rj   r  r  rS  rk  r#  rc   rW   r   r$  )rk   r  rl   ra  r  rc  r  r  r(  r*  r  r  r+  r"   r"   r#   log_failure_fallback_event  sB   
z+PrometheusLogger.log_failure_fallback_eventstaterM   c                 C   s<   t | jddt||||dd}| jjdi || dS )z+
        Set the deployment state.
        rN   r   r  r  Nr"   )r#  rc   r  rN   r   ru   )rk   r  r   r  r  rM   r+  r"   r"   r#   set_litellm_deployment_state  s   z-PrometheusLogger.set_litellm_deployment_statec                 C      |  d|||| d S )Nr   r  rk   r   r  r  rM   r"   r"   r#   r       
z'PrometheusLogger.set_deployment_healthyc                 C   r  )Nr  r  r  r"   r"   r#   r    r  z.PrometheusLogger.set_deployment_partial_outagec                 C   r  )N   r  r  r"   r"   r#   set_deployment_complete_outage	  r  z/PrometheusLogger.set_deployment_complete_outager  c                 C   s0   | j t|t|t|t|t|  dS )zn
        increment metric when litellm.Router / load balancing logic places a deployment in cool down
        N)rQ   r   r   r$  )rk   r   r  r  rM   r  r"   r"   r#    increment_deployment_cooled_down	  s   
z1PrometheusLogger.increment_deployment_cooled_downrY   c                 C   s   | j j|d  dS )za
        Increment metric when logging to a callback fails (e.g., s3_v2, langfuse, etc.)
        )rY   N)rX   r   r$  )rk   rY   r"   r"   r#   "increment_callback_logging_failure%	  s   
z3PrometheusLogger.increment_callback_logging_failureproviderspendbudget_limitc                 C   s    | j || j||d dS )z?
        Track provider remaining budget in Prometheus
        
max_budgetr  N)rL   r   ru   _safe_get_remaining_budget)rk   r  r  r  r"   r"   r#   track_provider_remaining_budget0	  s   z0PrometheusLogger.track_provider_remaining_budgetr  c                 C   s$   |d u rt dS |d u r|S || S )Ninf)float)rk   r  r  r"   r"   r#   r  =	  s
   z+PrometheusLogger._safe_get_remaining_budgetdata_fetch_function.set_metrics_function	data_type)teamskeysusersc              
      s   ddl m} |du rdS zEd}d}|||dI dH \}}|du r%t|}|| d | }	||I dH  td|	d D ]}|||dI dH \}}
||I dH  q;W dS  tyr } ztd| d	t|  W Y d}~dS d}~ww )
ab  
        Generic method to initialize budget metrics for teams or API keys.

        Args:
            data_fetch_function: Function to fetch data with pagination.
            set_metrics_function: Function to set metrics for the fetched data.
            data_type: String representing the type of data ("teams" or "keys") for logging purposes.
        r   prisma_clientNr  2   )	page_sizepager  zError initializing z budget metrics: )litellm.proxy.proxy_serverr  r  rangeri   r   rM  rj   )rk   r  r  r  r  r  r  rm  total_countZtotal_pages_rm   r"   r"   r#   _initialize_budget_metricsH	  s0   z+PrometheusLogger._initialize_budget_metricsc              	      sx   ddl m  ddlm du rtd dS dtdtdttt	 t
t f f fd	d
}| j|| jddI dH  dS )zY
        Initialize team budget metrics by reusing the generic pagination logic.
        r   )get_paginated_teamsr  NzDPrometheus: skipping team metrics initialization, DB not initializedr  r  ro   c                    s2    | |dI d H \}}|d u rt |}||fS )N)r  r  r  )r  )r  r  r  r  r  r  r"   r#   fetch_teams	  s   zEPrometheusLogger._initialize_team_budget_metrics.<locals>.fetch_teamsr  r  r  r  )Z1litellm.proxy.management_endpoints.team_endpointsr  r  r  r   rt   rQ  r   r	   r   r   r  _set_team_list_budget_metrics)rk   r  r"   r  r#   _initialize_team_budget_metricsu	  s(   
z0PrometheusLogger._initialize_team_budget_metricsc                    s   ddl m} ddlm  ddlm ddlm du r$t	d dS dt
d	t
d
tt|tttf  tt
 f f fdd}| j|| jddI dH  dS )z\
        Initialize API key budget metrics by reusing the generic pagination logic.
        r   )r   )UI_SESSION_TOKEN_TEAM_ID)_list_key_helperr  NzCPrometheus: skipping key metrics initialization, DB not initializedr  r  ro   c                    sR   || d d d d  dd d
I d H }| dg }| d}|d u r%t|}||fS )NT)
r  r  sizer  rj  ri  Zkey_hashZexclude_team_idZreturn_full_objectZorganization_idr  r  )r   r  )r  r  Zkey_list_responser  r  r  r  r  r"   r#   
fetch_keys	  s$   
zGPrometheusLogger._initialize_api_key_budget_metrics.<locals>.fetch_keysr  r  )r   r   litellm.constantsr  Z;litellm.proxy.management_endpoints.key_management_endpointsr  r  r  r   rt   rQ  r   r	   rj   r   r   r   r  _set_key_list_budget_metrics)rk   r   r  r"   r  r#   "_initialize_api_key_budget_metrics	  s4   z3PrometheusLogger._initialize_api_key_budget_metricsc              	      sv   ddl m} ddlm   du rtd dS dtdtdtt| t	t f f fd	d
}| j
|| jddI dH  dS )zY
        Initialize user budget metrics by reusing the generic pagination logic.
        r   )r   r  NzDPrometheus: skipping user metrics initialization, DB not initializedr  r  ro   c                    sF   |d |  } j jj|| ddidI d H } j j I d H }||fS )Nr  Z
created_atZdesc)skipZtakeorder)dblitellm_usertableZ	find_manycount)r  r  r  r  r  r  r"   r#   fetch_users	  s   zEPrometheusLogger._initialize_user_budget_metrics.<locals>.fetch_usersr  r  )litellm.proxy._typesr   r  r  r   rt   rQ  r   r	   r   r  _set_user_list_budget_metrics)rk   r   r  r"   r  r#   _initialize_user_budget_metrics	  s(   z0PrometheusLogger._initialize_user_budget_metricsc              	      s   ddl m} ddlm} |jj}|r?|jr?|j|dI dH r=z|  I dH  W |j	|dI dH  dS |j	|dI dH  w dS |  I dH  dS )a  
        Handler for initializing remaining budget metrics for all teams to avoid metric discrepancies.

        Runs when prometheus logger starts up.

        - If redis cache is available, we use the pod lock manager to acquire a lock and initialize the metrics.
            - Ensures only one pod emits the metrics at a time.
        - If redis cache is not available, we initialize the metrics directly.
        r   )'PROMETHEUS_EMIT_BUDGET_METRICS_JOB_NAME)proxy_logging_obj)Z
cronjob_idN)
r  r  r  r  Zdb_spend_update_writerpod_lock_managerredis_cacheacquire_lock$_initialize_remaining_budget_metricsrelease_lock)rk   r  r  r  r"   r"   r#   #initialize_remaining_budget_metrics	  s"   

z4PrometheusLogger.initialize_remaining_budget_metricsc                    sH   t d |  I dH  |  I dH  |  I dH  |  I dH  dS )zc
        Helper to initialize remaining budget metrics for all teams, API keys, and users.
        z+Emitting key, team, user budget metrics....N)r   rt   r  r  r  '_initialize_user_and_team_count_metrics)rk   r"   r"   r#   r  
  s   
z5PrometheusLogger._initialize_remaining_budget_metricsc              
      s   ddl m} |du rtd dS z1|jj I dH }| j| td|  |jj	 I dH }| j
| td|  W dS  ty` } ztdt|  W Y d}~dS d}~ww )z
        Initialize user and team count metrics by querying the database.

        Updates:
        - litellm_total_users: Total count of users in the database
        - litellm_teams_count: Total count of teams in the database
        r   r  NzOPrometheus: skipping user/team count metrics initialization, DB not initializedz'Prometheus: set litellm_total_users to z'Prometheus: set litellm_teams_count to z,Error initializing user/team count metrics: )r  r  r   rt   r  r  r  rg   ru   Zlitellm_teamtablerh   ri   rM  rj   )rk   r  Ztotal_usersZtotal_teamsrm   r"   r"   r#   r  
  s0   
z8PrometheusLogger._initialize_user_and_team_count_metricsr  c                    s$   |D ]}t |tr| | qdS )z8Helper function to set budget metrics for a list of keysN)rw   r   _set_key_budget_metrics)rk   r  r5  r"   r"   r#   r  .
  s   

z-PrometheusLogger._set_key_list_budget_metricsr  c                       |D ]}|  | qdS )z9Helper function to set budget metrics for a list of teamsN)_set_team_budget_metrics)rk   r  r   r"   r"   r#   r  6
     z.PrometheusLogger._set_team_list_budget_metricsr  c                    r  )z9Helper function to set budget metrics for a list of usersN)_set_user_budget_metrics)rk   r  r   r"   r"   r#   r  ;
  r  z.PrometheusLogger._set_user_list_budget_metricsr0  r1  c                    s6   |r| j ||p	d|||dI dH }| | dS dS )z
        Set team budget metrics after an LLM API request

        - Assemble a LiteLLM_TeamTable object
            - looks up team info from db if not available in metadata
        - Set team budget metrics
        r   )rj  r   r  r  r   N)_assemble_team_objectr  )rk   r  r  r0  r1  r   team_objectr"   r"   r#   r9  @
  s   z;PrometheusLogger._set_team_budget_metrics_after_api_requestrj  r   c              
      s   ddl m} ddlm}m} |pd| }	t|||	|d}
z||||dI dH }W n tyG } ztdt	|  |
W  Y d}~S d}~ww |r\|j
|
_
|
jdu r\|jdur\|j|
_|
S )z
        Assemble a LiteLLM_TeamTable object

        for fields not available in metadata, we fetch from db
        Fields not available in metadata:
        - `budget_reset_at`
        r   )get_team_objectr  user_api_key_cache)rj  r   r  r  )rj  r  r  Nz4[Non-Blocking] Prometheus: Error getting team info: )litellm.proxy.auth.auth_checksr  r  r  r  r   ri   r   rt   rj   budget_reset_atr  )rk   rj  r   r  r  r   r  r  r  Z_total_team_spendr  Z	team_inform   r"   r"   r#   r  Z
  s8   z&PrometheusLogger._assemble_team_objectr   c                 C   s   t |j|jpdd}t| jdd|d}| jjdi || j|j	|j
d |j	durCt| jdd|d}| jjdi ||j	 |jduret| jd	d|d}| jjdi || j|jd
 dS dS )z
        Set team budget metrics for a single team

        - Remaining Budget
        - Max Budget
        - Budget Reset At
        r   )r   r   r4   r   r  r  Nr5   r6   r  r"   )r  rj  r   r#  rc   r4   r   ru   r  r  r  r5   r  r6   %_get_remaining_hours_for_budget_reset)rk   r   r  r+  r"   r"   r#   r  
  sJ   

z)PrometheusLogger._set_team_budget_metricsc                 C   s   t |j|jpdd}t| jdd|d}| jjd
i || j|j	|j
d |j	durCt| jdd|d}| jjd
i ||j	 |jdur[| jjd
i || j|jd	 dS dS )z{
        Set virtual key budget metrics

        - Remaining Budget
        - Max Budget
        - Budget Reset At
        r   )r   r   r7   r   r  r  Nr8   r  r"   )r  tokenri  r#  rc   r7   r   ru   r  r  r  r8   r  r9   r  )rk   r\  r  r+  r"   r"   r#   r  
  sB   

z(PrometheusLogger._set_key_budget_metricsr.  r/  c                    s6   |r| j ||p	d|||dI d H }| | d S d S )Nr   )r  r   r.  r/  r   )_assemble_key_objectr  )rk   r  r   r   r.  r/  r\  r"   r"   r#   r8  
  s   z>PrometheusLogger._set_api_key_budget_metrics_after_api_requestc              
      s   ddl m} ddlm}m} |pd| }	t||||	d}
z|
jr5||
j||dI dH }|r8|j|
_W |
S W |
S W |
S  tyW } zt	
dt|  W Y d}~|
S d}~ww )z2
        Assemble a UserAPIKeyAuth object
        r   )get_key_objectr  )r  ri  r  r  )Zhashed_tokenr  r  Nz3[Non-Blocking] Prometheus: Error getting key info: )r  r  r  r  r  r   r  r  ri   r   rt   rj   )rk   r  r   r.  r/  r   r  r  r  Z_total_key_spendr\  Z
key_objectrm   r"   r"   r#   r  
  s>   
z%PrometheusLogger._assemble_key_objectr2  r3  c                    s0   |r| j ||||dI dH }| | dS dS )z
        Set user budget metrics after an LLM API request

        - Assemble a LiteLLM_UserTable object
            - looks up user info from db if not available in metadata
        - Set user budget metrics
        )r  r  r  r   N)_assemble_user_objectr  )rk   r  r2  r3  r   user_objectr"   r"   r#   r:    s   z;PrometheusLogger._set_user_budget_metrics_after_api_requestc              
      s   ddl m} ddlm}m} |pd| }t|||d}	z||||dddI dH }
W n tyH } ztdt	|  |	W  Y d}~S d}~ww |
r]|
j
|	_
|	jdu r]|
jdur]|
j|	_|	S )	z
        Assemble a LiteLLM_UserTable object

        for fields not available in metadata, we fetch from db
        Fields not available in metadata:
        - `budget_reset_at`
        r   )get_user_objectr  )r  r  r  F)r  r  r  Zuser_id_upsertZcheck_db_onlyNz4[Non-Blocking] Prometheus: Error getting user info: )r  r  r  r  r  r   ri   r   rt   rj   r  r  )rk   r  r  r  r   r  r  r  Z_total_user_spendr  Z	user_inform   r"   r"   r#   r  3  s:   z&PrometheusLogger._assemble_user_objectr   c                 C   s   t |jd}t| jdd|d}| jjd
i || j|j|j	d |jdur?t| jdd|d}| j
jd
i ||j |jdurat| jdd|d}| jjd
i || j|jd	 dS dS )z
        Set user budget metrics for a single user

        - Remaining Budget
        - Max Budget
        - Budget Reset At
        )r   r:   r   r  r  Nr;   r<   r  r"   )r  r  r#  rc   r:   r   ru   r  r  r  r;   r  r<   r  )rk   r   r  r+  r"   r"   r#   r  a  sH   

z)PrometheusLogger._set_user_budget_metricsr  c                 C   s   |t |j  d S )z6
        Get remaining hours for budget reset
        i  )r   rG  tzinfor  )rk   r  r"   r"   r#   r    s   z6PrometheusLogger._get_remaining_hours_for_budget_resetr&  r'  c                 C   s$   t |trt |tr||  S dS )z
        Compute the duration in seconds between two objects.

        Returns the duration as a float if both start and end are instances of datetime,
        otherwise returns None.
        N)rw   r   r  )rk   r&  r'  r"   r"   r#   rH    s   z'PrometheusLogger._safe_duration_seconds	schedulerc                 C   s|   ddl m} ddlm} tjjtd}t	dt
| t
|dkr<tt|d }t	d|  | j|jd|dd	d
 dS dS )z
        Initialize budget metrics as a cron job. This job runs every `PROMETHEUS_BUDGET_METRICS_REFRESH_INTERVAL_MINUTES` minutes.

        It emits the current remaining budget metrics for all Keys and Teams.
        r   )2PROMETHEUS_BUDGET_METRICS_REFRESH_INTERVAL_MINUTESr   )Zcallback_typezfound %s prometheus loggerszNInitializing remaining budget metrics as a cron job executing every %s minutesintervalZprometheus_budget_metrics_jobT)minutesrf  Zreplace_existingN)r  r  "litellm.integrations.custom_loggerr   rr   Zlogging_callback_managerZget_custom_loggers_for_typer%   r   rt   r  r   Zadd_jobr  )r  r  r   Zprometheus_loggersZprometheus_loggerr"   r"   r#   "initialize_budget_metrics_cron_job  s,   
z3PrometheusLogger.initialize_budget_metrics_cron_jobc                  C   sx   ddl m}  ddlm} ddlm} dtjv r,ddl m}m	} | }|
| | |}n|  }|d| |d d	S )
a  
        Mount the Prometheus metrics endpoint with optional authentication.

        Args:
            require_auth (bool, optional): Whether to require authentication for the metrics endpoint.
                                        Defaults to False.
        r   )make_asgi_app)verbose_proxy_logger)appZPROMETHEUS_MULTIPROC_DIR)CollectorRegistrymultiprocessz/metricsz;Starting Prometheus Metrics on /metrics (no authentication)N)r_   r  litellm._loggingr  r  r   osenvironr  r  ZMultiProcessCollectormountrt   )r  r  r   r  r  registryZmetrics_appr"   r"   r#   _mount_metrics_endpoint  s   	


z(PrometheusLogger._mount_metrics_endpointrU  )NNN)NNNNN)r  )cr_  
__module____qualname__rn   r   rj   r	   r`   r   r|   r   r   r   r   r   r   r   r}   r   tupler   r   r   boolr   rb   r   rc   r,  r   r  r  r"  rx   r  r  r  r  r   rO  r   ri   rQ  rT  r[  r   r  r   rl  ro  rr  r  rL  r  r!  r  staticmethodrk  r  r  r  r  r  r  r  r  r  r  r   r   r   r
   r  r  r  r  r  r  r  r  r   r  r   r  r9  r  r  r  r8  r  r:  r  r  r   r  rH  r   r  r  r"   r"   r"   r#   r%   B   sP     },


R
+
/
F
 @	

3
8
1	

$
)
T5
>
)
0
U

^ 
1
 &
,
/
.








-0
#


,
3+

%

.
2
r%   r  r  tagro   c                    s   |  } fdd| D }tjj|v r#t }|d|jidd|d< |jdur@|j D ]\}}t|}| v r?t	|||< q-|j
dur]t|j
}	|	 D ]\}}| v r\t	|||< qN D ]
}
|
|vrid||
< q_|S )z
    Returns a dictionary of label + values for prometheus.

    Ensures end_user param is not sent to prometheus if it is not supported.
    c                    s"   i | ]\}}| v r|t |qS r"   )r   )r   r   valuer  r"   r#   
<dictcomp>  s
    z,prometheus_label_factory.<locals>.<dictcomp>Zuser_api_key_end_user_idr   )r   r   r   N)Z
model_dumpr   ZUserAPIKeyLabelNamesZEND_USERr  r$   r   r  r   r   r   get_custom_labels_from_tags)r  r  r  	enum_dictr   r    r5  r  Zsanitized_keyZcustom_tag_labelsr   r"   r  r#   r#    s6   




r#  r   c                 C   s   t j}|du st|dkri S i }|D ]C}|}|dr#|dddn|}|d}| }|D ]}t|tr<||d}nd}|du rD nq.|durVt|t	rV|||dd< q|S )z)
    Get custom labels from metadata
    Nr   z	metadata.r   r  r  r  )
rr   Z!custom_prometheus_metadata_labelsr  r  replacesplitrw   rx   r   rj   )r   r  resultr5  Zoriginal_keyZ
keys_partsr  partr"   r"   r#   r    s(   

r  r   configured_tagc                    s<   ddl  ddlm} | }||t fdd| D S )a  
    Check if any of the request tags matches a wildcard configured pattern

    Args:
        tags: List[str] - The request tags
        configured_tag: str - The configured tag

    Returns:
        bool - True if any of the request tags matches the configured tag, False otherwise

    e.g.
    tags = ["User-Agent: curl/7.68.0", "User-Agent: python-requests/2.28.1", "prod"]
    configured_tag = "User-Agent: curl/*"
    _tag_matches_wildcard_configured_pattern(tags=tags, configured_tag=configured_tag) # True

    configured_tag = "User-Agent: python-requests/*"
    _tag_matches_wildcard_configured_pattern(tags=tags, configured_tag=configured_tag) # True

    configured_tag = "gm"
    _tag_matches_wildcard_configured_pattern(tags=tags, configured_tag=configured_tag) # False
    r   N)PatternMatchRouterc                 3   s    | ]
} j |d V  qdS ))rV  stringN)match)r   r  reZregex_patternr"   r#   rX  Y  s    z;_tag_matches_wildcard_configured_pattern.<locals>.<genexpr>)r  Z.litellm.router_utils.pattern_match_deploymentsr  Z_pattern_to_regexrZ  )r   r  r  Zpattern_routerr"   r  r#   (_tag_matches_wildcard_configured_pattern;  s
   
r  c                 C   s   ddl m} tj}|du st|dkri S i }|D ]%}|d| }|| v r+d||< qd|v r:t| |dr:d||< qd||< q|S )	a  
    Get custom labels from tags based on admin configuration.

    Supports both exact matches and wildcard patterns:
    - Exact match: "prod" matches "prod" exactly
    - Wildcard pattern: "User-Agent: curl/*" matches "User-Agent: curl/7.68.0"

    Reuses PatternMatchRouter for wildcard pattern matching.

    Returns dict of label_name: "true" if the tag matches the configured tag, "false" otherwise

    {
        "tag_User-Agent_curl": "true",
        "tag_User-Agent_python_requests": "false",
        "tag_Environment_prod": "true",
        "tag_Environment_dev": "false",
        "tag_Service_api_gateway_v2": "true",
        "tag_Service_web_app_v1": "false",
    }
    r   )r   NZtag_truer   )r   r  false)rs   r   rr   Zcustom_prometheus_tagsr  r  )r   r   Zconfigured_tagsr  r  Z
label_namer"   r"   r#   r  \  s"   

r  rU  )1r6  r  r@  r   r   r   r   r   r   r   r   r	   r
   r   r   r   r   rr   r  r   r   r  r   Z'litellm.litellm_core_utils.core_helpersr   r   r  r   r   r   r   rs   r   r   r  r   Zapscheduler.schedulers.asyncior   r!   r$   r%   rj   r  rx   r#  r  r  r  r  r"   r"   r"   r#   <module>   sz   4                       A
2 
"!