
    /
iX                     J   d Z ddlZddlZddlmZ ddlmZmZmZm	Z	 erddl
mZ ddlmZ ddlmZ ddlmZ dd	lmZmZmZmZmZmZmZmZ dd
lmZmZ ddlmZ  ej         e!          Z"	 ddl#m$Z$ dZ%n# e&$ r dZ%dZ'dZ(dZ$dZ)Y nw xY w G d de          Z* G d d          Z+dS )z
OpenTelemetry metrics collector for redis-py.

This module defines and manages all metric instruments according to
OTel semantic conventions for database clients.
    N)Enum)TYPE_CHECKINGCallableOptionalUnion)ConnectionPool)AsyncDatabase)ConnectionPoolInterface)SyncDatabase)$REDIS_CLIENT_CONNECTION_CLOSE_REASON$REDIS_CLIENT_CONNECTION_NOTIFICATIONAttributeBuilder	CSCReason	CSCResultGeoFailoverReasonPubSubDirectionget_pool_name)MetricGroup
OTelConfig)deprecated_args)MeterTFc                       e Zd ZdZdZdZdZdS )CloseReasona  
    Enum representing the reason why a Redis client connection was closed.

    Values:
        APPLICATION_CLOSE: The connection was closed intentionally by the application
            (for example, during normal shutdown or explicit cleanup).
        ERROR: The connection was closed due to an unexpected error
            (for example, network failure or protocol error).
        HEALTHCHECK_FAILED: The connection was closed because a health check
            or liveness check for the connection failed.
    application_closeerrorhealthcheck_failedN)__name__
__module____qualname____doc__APPLICATION_CLOSEERRORHEALTHCHECK_FAILED     C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\redis/observability/metrics.pyr   r   /   s-        
 
 ,E-r%   r   c                      e Zd ZdZdZdZdedefdZdId	Z	dId
Z
dIdZdIdZdIdZdIdZdIdZ	 	 	 	 	 	 	 dJdee         dee         dee         dee         dee         dee         dee         fdZdededededef
dZded         ded         defdZdeddfd Zdeddfd!Zd"eddfd#Zd$ed%         d&eddfd'Zd"ed&eddfd(Z  e!d)gd*d+,          	 	 	 	 	 	 	 	 	 dKd-ed&edee         dee         d.ee         d)ee         dee         dee         dee         dee         d/ee         ddfd0            Z"	 	 dLd1ee#         dee         ddfd2Z$d3eded4eddfd5Z%d"eddfd6Z&	 	 dLd7e'd8ee         d9ee         ddfd:Z( e!d;gd<d+,          	 	 	 dMd=ed>ee         d?ee         d;ee         ddf
d@            Z)	 dNdAee*         ddfdBZ+	 dNdCedee,         ddfdDZ-dEeddfdFZ.e/defdG            Z0defdHZ1dS )ORedisMetricsCollectorap  
    Collects and records OpenTelemetry metrics for Redis operations.

    This class manages all metric instruments and provides methods to record
    various Redis operations including connection pool events, command execution,
    and cluster-specific operations.

    Args:
        meter: OpenTelemetry Meter instance
        config: OTel configuration object
    zredis-pyz1.0.0meterconfigc                    t           st          d          || _        || _        t	                      | _        d | _        t          j        | j        j	        v r| 
                                 t          j        | j        j	        v r|                                  t          j        | j        j	        v r|                                  t          j        | j        j	        v r|                                  t          j        | j        j	        v r|                                  t          j        | j        j	        v r|                                  t          j        | j        j	        v r|                                  t.                              d           d S )NzROpenTelemetry API is not installed. Install it with: pip install opentelemetry-apiz!RedisMetricsCollector initialized)OTEL_AVAILABLEImportErrorr)   r*   r   attr_builderconnection_countr   
RESILIENCYmetric_groups_init_resiliency_metricsCOMMAND_init_command_metricsCONNECTION_BASIC_init_connection_basic_metricsCONNECTION_ADVANCED!_init_connection_advanced_metricsPUBSUB_init_pubsub_metrics	STREAMING_init_streaming_metricsCSC_init_csc_metricsloggerinfo)selfr)   r*   s      r&   __init__zRedisMetricsCollector.__init__Q   se    	A  
 
,.. $ !T[%>>>))+++$+";;;&&((('4;+DDD//111*dk.GGG22444!:::%%''' DK$===((***?dk777""$$$788888r%   returnNc                     | j                             ddd          | _        | j                             ddd          | _        | j                             dd	d
          | _        dS )zInitialize resiliency metrics.zredis.client.errorsz{error}z`A counter of all errors (both returned to the user and handled internally in the client library)nameunitdescriptionz&redis.client.maintenance.notificationsz{notification}z,Tracks server-side maintenance notificationsz"redis.client.geofailover.failoversz{geofailover}z6Total count of failovers happened using MultiDbClient.N)r)   create_counterclient_errorsmaintenance_notificationsgeo_failoversrA   s    r&   r2   z.RedisMetricsCollector._init_resiliency_metricsv   s    !Z66&z 7 
 
 *.)B)B9!F *C *
 *
& "Z665 P 7 
 
r%   c                     | j                             ddd| j        j                  | _        | j                             ddd          | _        | j                             d	d
d          | _        dS )z$Initialize basic connection metrics.z db.client.connection.create_timeszTime to create a new connectionrF   rG   rH   #explicit_bucket_boundaries_advisoryz'redis.client.connection.relaxed_timeoutz{relaxation}z@Counts up for relaxed timeout, counts down for unrelaxed timeoutrE   zredis.client.connection.handoffz	{handoff}zIConnections that have been handed off (e.g., after a MOVING notification)N)	r)   create_histogramr*   buckets_connection_create_timeconnection_create_timecreate_up_down_counterconnection_relaxed_timeoutrI   connection_handoffrM   s    r&   r6   z4RedisMetricsCollector._init_connection_basic_metrics   s    &*j&A&A39040Z	 'B '
 '
# +/**K*K:Z +L +
 +
' #'*";";2c #< #
 #
r%   c                     | j                             ddd          | _        | j                             ddd| j        j                  | _        | j                             d	d
d          | _        dS )z'Initialize advanced connection metrics.zdb.client.connection.timeoutsz	{timeout}zaThe number of connection timeouts that have occurred trying to obtain a connection from the pool.rE   zdb.client.connection.wait_timerO   z/Time to obtain an open connection from the poolrP   zredis.client.connection.closed{connection}z"Total number of closed connectionsN)r)   rI   connection_timeoutsrR   r*   buckets_connection_wait_timeconnection_wait_timeconnection_closedrM   s    r&   r8   z7RedisMetricsCollector._init_connection_advanced_metrics   s    #':#<#<0{ $= $
 $
  %)J$?$?1I040X	 %@ %
 %
! "&!:!:1< "; "
 "
r%   c                 `    | j                             ddd| j        j                  | _        dS )z0Initialize command execution metric instruments.zdb.client.operation.durationrO   zCommand execution durationrP   N)r)   rR   r*   buckets_operation_durationoperation_durationrM   s    r&   r4   z+RedisMetricsCollector._init_command_metrics   s8    "&*"="=/4040V	 #> #
 #
r%   c                 J    | j                             ddd          | _        dS )z%Initialize PubSub metric instruments.zredis.client.pubsub.messagesz	{message}z&Tracks published and received messagesrE   N)r)   rI   pubsub_messagesrM   s    r&   r:   z*RedisMetricsCollector._init_pubsub_metrics   s0    #z88/@  9  
  
r%   c                 `    | j                             ddd| j        j                  | _        dS )z(Initialize Streaming metric instruments.zredis.client.stream.lagrO   zkEnd-to-end lag per message, showing how stale are the messages when the application starts processing them.rP   N)r)   rR   r*   "buckets_stream_processing_duration
stream_lagrM   s    r&   r<   z-RedisMetricsCollector._init_streaming_metrics   s8    *55* F040^	 6 
 
r%   c                     | j                             ddd          | _        | j                             ddd          | _        | j                             dd	d
          | _        dS )z8Initialize Client Side Caching (CSC) metric instruments.zredis.client.csc.requestsz	{request}z)The total number of requests to the cacherE   zredis.client.csc.evictionsz
{eviction}z#The total number of cache evictionszredis.client.csc.network_savedByz,The total number of bytes saved by using CSCN)r)   rI   csc_requestscsc_evictionscsc_network_savedrM   s    r&   r>   z'RedisMetricsCollector._init_csc_metrics   s     J55,C 6 
 
 "Z66-= 7 
 
 "&!:!:1F "; "
 "
r%   server_addressserver_portnetwork_peer_addressnetwork_peer_port
error_typeretry_attemptsis_internalc                 X   t          | d          sdS | j                            ||          }|                    | j                            |||                     |                    | j                            ||                     | j                            d|           dS )a  
        Record error count

        Args:
            server_address: Server address
            server_port: Server port
            network_peer_address: Network peer address
            network_peer_port: Network peer port
            error_type: Error type
            retry_attempts: Retry attempts
            is_internal: Whether the error is internal (e.g., timeout, network error)
        rJ   Nrk   rl   )rm   rn   rp   )ro   rq      
attributes)hasattrr.   build_base_attributesupdatebuild_operation_attributesbuild_error_attributesrJ   add)	rA   rk   rl   rm   rn   ro   rp   rq   attrss	            r&   record_error_countz(RedisMetricsCollector.record_error_count   s    , t_-- 	F!77)# 8 
 
 	88%9"3- 9  	
 	
 	
 	44%' 5  	
 	
 	
 	qU33333r%   maint_notificationc                    t          | d          sdS | j                            ||          }|                    | j                            ||                     ||t
          <   | j                            d|           dS )a7  
        Record maintenance notification count

        Args:
            server_address: Server address
            server_port: Server port
            network_peer_address: Network peer address
            network_peer_port: Network peer port
            maint_notification: Maintenance notification
        rK   Nrs   )rm   rn   rt   ru   )rw   r.   rx   ry   rz   r   rK   r|   )rA   rk   rl   rm   rn   r   r}   s          r&   record_maint_notification_countz5RedisMetricsCollector.record_maint_notification_count  s    $ t899 	F!77)# 8 
 

 	88%9"3 9  	
 	
 	
 7I23&**1*?????r%   	fail_from)r   r	   fail_toreasonc                     t          | d          sdS | j                            |||          }| j                            d|          S )z
        Record geo failover

        Args:
            fail_from: Database failed from
            fail_to: Database failed to
            reason: Reason for the failover
        rL   N)r   r   r   rt   ru   )rw   r.   build_geo_failover_attributesrL   r|   )rA   r   r   r   r}   s        r&   record_geo_failoverz)RedisMetricsCollector.record_geo_failover6  s`     t_-- 	F!?? @ 
 
 !%%aE%:::r%   callbackc                     t           j        | j        j        vr	| j        sdS | j                            ddd|g          | _        dS )z
        Initialize observable gauge for connection count metric.

        Args:
            callback: Callback function to retrieve connection count
        Nzdb.client.connection.countrY   z!Number of connections in the poolrF   rG   rH   	callbacks)r   r5   r*   r1   r/   r)   create_observable_gaugerA   r   s     r&   init_connection_countz+RedisMetricsCollector.init_connection_countP  s^     (0III) J F $
 B B-;j	 !C !
 !
r%   c                     t           j        | j        j        vr	| j        sdS | j                            ddd|g          | _        dS )z
        Initialize observable gauge for CSC items metric.

        Args:
            callback: Callback function to retrieve CSC items count
        Nzredis.client.csc.itemsz{item}z5The total number of cached responses currently storedr   )r   r=   r*   r1   	csc_itemsr)   r   r   s     r&   init_csc_itemsz$RedisMetricsCollector.init_csc_itemsg  sR     ?$+";;;DN;F;;)Oj	 < 
 
r%   	pool_namec                     t          | d          sdS | j                            |          }| j                            d|           dS )zo
        Record a connection timeout event.

        Args:
            pool_name: Connection pool name
        rZ   Nr   rt   ru   )rw   r.   build_connection_attributesrZ   r|   rA   r   r}   s      r&   record_connection_timeoutz/RedisMetricsCollector.record_connection_timeout{  sW     t233 	F!==	=RR $$Q5$99999r%   connection_pool)r
   r   duration_secondsc                     t          | d          sdS | j                            t          |                    }| j                            ||           dS )z
        Record time taken to create a new connection.

        Args:
            connection_pool: Connection pool implementation
            duration_seconds: Creation time in seconds
        rT   Nr   ru   )rw   r.   r   r   rT   record)rA   r   r   r}   s       r&   record_connection_create_timez3RedisMetricsCollector.record_connection_create_time  si     t566 	F!==#O44 > 
 
 	#**+;*NNNNNr%   c                     t          | d          sdS | j                            |          }| j                            ||           dS )z
        Record time taken to obtain a connection from the pool.

        Args:
            pool_name: Connection pool name
            duration_seconds: Wait time in seconds
        r\   Nr   ru   )rw   r.   r   r\   r   )rA   r   r   r}   s       r&   record_connection_wait_timez1RedisMetricsCollector.record_connection_wait_time  sX     t344 	F!==	=RR!(()9e(LLLLLr%   
batch_sizezXThe batch_size argument is no longer used and will be removed in the next major version.z7.2.1)args_to_warnr   versioncommand_namedb_namespaceis_blockingc           	         t          | d          sdS | j                            |          sdS | j                            |||          }|                    | j                            |||	|
|                     |                    | j                            |                     | j        	                    ||           dS )a  
        Record command execution duration.

        Args:
            command_name: Redis command name (e.g., 'GET', 'SET', 'MULTI')
            duration_seconds: Execution time in seconds
            server_address: Redis server address
            server_port: Redis server port
            db_namespace: Redis database index
            batch_size: Number of commands in batch (for pipelines/transactions)
            error_type: Error type if operation failed
            network_peer_address: Resolved peer address
            network_peer_port: Peer port number
            retry_attempts: Number of retry attempts made
            is_blocking: Whether the operation is a blocking command
        r`   N)rk   rl   r   )r   rm   rn   rp   r   ro   ru   )
rw   r*   should_track_commandr.   rx   ry   rz   r{   r`   r   )rA   r   r   rk   rl   r   r   ro   rm   rn   rp   r   r}   s                r&   record_operation_durationz/RedisMetricsCollector.record_operation_duration  s   F t122 	F {//== 	F !77)#% 8 
 
 	88)%9"3-' 9  	
 	
 	
 	44% 5  	
 	
 	

 	&&'7E&JJJJJr%   close_reasonc                    t          | d          sdS | j                                        }|r|j        |t          <   |                    | j                            |                     | j                            d|           dS )z
        Record a connection closed event.

        Args:
            close_reason: Reason for closing (e.g. 'error', 'application_close')
            error_type: Error type if closed due to error
        r]   Nr   rt   ru   )	rw   r.   r   valuer   ry   r{   r]   r|   )rA   r   ro   r}   s       r&   record_connection_closedz.RedisMetricsCollector.record_connection_closed  s     t011 	F!==?? 	M:F:LE6744% 5  	
 	
 	
 	""1"77777r%   connection_namerelaxedc                     t          | d          sdS | j                            |          }||t          <   | j                            |rdnd|           dS )a
  
        Record a connection timeout relaxation event.

        Args:
            connection_name: Connection name
            maint_notification: Maintenance notification type
            relaxed: True to count up (relaxed), False to count down (unrelaxed)
        rV   N)r   rt   ru   )rw   r.   r   r   rV   r|   )rA   r   r   r   r}   s        r&   !record_connection_relaxed_timeoutz7RedisMetricsCollector.record_connection_relaxed_timeout  su     t9:: 	F!==+ > 
 
 7I23'++,@AAbU+SSSSSr%   c                     t          | d          sdS | j                            |          }| j                            d|           dS )z
        Record a connection handoff event (e.g., after MOVING notification).

        Args:
            pool_name: Connection pool name
        rW   Nr   rt   ru   )rw   r.   r   rW   r|   r   s      r&   record_connection_handoffz/RedisMetricsCollector.record_connection_handoff$  sW     t122 	F!==	=RR##A%#88888r%   	directionchannelshardedc                     t          | d          sdS | j                            |||          }| j                            d|           dS )z
        Record a PubSub message (published or received).

        Args:
            direction: Message direction ('publish' or 'receive')
            channel: Pub/Sub channel name
            sharded: True if sharded Pub/Sub channel
        rb   N)r   r   r   rt   ru   )rw   r.   build_pubsub_message_attributesrb   r|   )rA   r   r   r   r}   s        r&   record_pubsub_messagez+RedisMetricsCollector.record_pubsub_message6  sg     t.// 	F!AA B 
 

 	  u 55555r%   consumer_namez[The consumer_name argument is no longer used and will be removed in the next major version.lag_secondsstream_nameconsumer_groupc                     t          | d          sdS | j                            ||          }| j                            ||           dS )z
        Record the lag of a streaming message.

        Args:
            lag_seconds: Lag in seconds
            stream_name: Stream name
            consumer_group: Consumer group name
            consumer_name: Consumer name
        re   N)r   r   ru   )rw   r.   build_streaming_attributesre   r   )rA   r   r   r   r   r}   s         r&   record_streaming_lagz*RedisMetricsCollector.record_streaming_lagP  sa    * t\** 	F!<<#) = 
 
 	{u=====r%   resultc                     t          | d          sdS | j                            |          }| j                            d|           dS )z}
        Record a Client Side Caching (CSC) request.

        Args:
            result: CSC result ('hit' or 'miss')
        rh   N)r   rt   ru   )rw   r.   build_csc_attributesrh   r|   )rA   r   r}   s      r&   record_csc_requestz(RedisMetricsCollector.record_csc_requestp  sV     t^,, 	F!66f6EEaE22222r%   countc                     t          | d          sdS | j                            |          }| j                            ||           dS )z
        Record a Client Side Caching (CSC) eviction.

        Args:
            count: Number of evictions
            reason: Reason for eviction
        ri   N)r   ru   )rw   r.   r   ri   r|   )rA   r   r   r}   s       r&   record_csc_evictionz)RedisMetricsCollector.record_csc_eviction  sV     t_-- 	F!66f6EEu77777r%   bytes_savedc                     t          | d          sdS | j                                        }| j                            ||           dS )z
        Record the number of bytes saved by using Client Side Caching (CSC).

        Args:
            bytes_saved: Number of bytes saved
        rj   Nru   )rw   r.   r   rj   r|   )rA   r   r}   s      r&   record_csc_network_savedz.RedisMetricsCollector.record_csc_network_saved  sR     t011 	F!6688"";5"AAAAAr%   c                  (    t          j                    S )z
        Get monotonic time for duration measurements.

        Returns:
            Current monotonic time in seconds
        )time	monotonicr$   r%   r&   monotonic_timez$RedisMetricsCollector.monotonic_time  s     ~r%   c                 (    d| j          d| j         dS )NzRedisMetricsCollector(meter=z	, config=))r)   r*   rM   s    r&   __repr__zRedisMetricsCollector.__repr__  s    QdjQQ4;QQQQr%   )rC   N)NNNNNNN)	NNNNNNNNN)NN)NNN)N)2r   r   r   r    
METER_NAMEMETER_VERSIONr   r   rB   r2   r6   r8   r4   r:   r<   r>   r   strint	Exceptionboolr~   r   r   r   r   r   r   r   r   floatr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r$   r%   r&   r(   r(   A   sX       
 
 JM#9e #9Z #9 #9 #9 #9J
 
 
 
(
 
 
 
*
 
 
 
*
 
 
 

 
 
 

 
 
 

 
 
 
0 )-%).2+/*.(,&*,4 ,4 ,4 c],4 'sm	,4
 $C=,4 Y',4 !,4 d^,4 ,4 ,4 ,4\"@"@ "@ "	"@
 "@  "@ "@ "@ "@H;89; 67; "	; ; ; ;4

 

 
 
 
.

 

 
 
 
(:3 :4 : : : :OJKO  O 
	O O O O(MM  M 
	M M M M( _"^i   )-%)&*$(*..2+/(,&*;K ;K;K  ;K !	;K
 c];K sm;K SM;K Y';K 'sm;K $C=;K !;K d^;K 
;K ;K ;K 
;K~ /3*.8 8{+8 Y'8 
	8 8 8 86TT  T 	T
 
T T T T.99 
9 9 9 9* "&"&	6 6"6 #6 $	6
 
6 6 6 64 _%&l   &*(,'+> >> c]> !	>
  }> 
> > > 
>: '+3 3#3 
3 3 3 3& '+8 88 #8 
	8 8 8 8$BB 
B B B B$  E       \ R# R R R R R Rr%   r(   ),r    loggingr   enumr   typingr   r   r   r   redis.asyncio.connectionr   redis.asyncio.multidb.databaser	   redis.connectionr
   redis.multidb.databaser   redis.observability.attributesr   r   r   r   r   r   r   r   redis.observability.configr   r   redis.utilsr   	getLoggerr   r?   opentelemetry.metricsr   r,   r-   Counter	HistogramUpDownCounterr   r(   r$   r%   r&   <module>r      s            ; ; ; ; ; ; ; ; ; ; ; ; 4777777<<<<<<888888333333	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ? > > > > > > > ' ' ' ' ' '		8	$	$	++++++NN   NGIEMMM. . . . .$ . . .$n	R n	R n	R n	R n	R n	R n	R n	R n	R n	Rs   *A3 3BB