
    j9_                     R   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mZ dd
lmZmZ ddlm Z 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ConnectionState	CSCReason	CSCResultGeoFailoverReasonPubSubDirectionget_pool_name)MetricGroup
OTelConfig)deprecated_argsdeprecated_function)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     f/DATA/AppData/hermes/projects/honcho/.venv/lib/python3.11/site-packages/redis/observability/metrics.pyr   r   0   s-        
 
 ,E-r'   r   c                   8   e Zd ZdZdZdZdedefdZdPd	Z	dPd
Z
dPdZdPdZdPdZdPdZdPdZ	 	 	 	 	 	 	 dQd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	 dRd ed!ed"eddfd#Z ed$d%&          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$d0gd1d23          	 	 	 	 	 	 	 	 	 dSd4ed-e!dee         dee         d5ee         d0ee         dee         dee         dee         dee         d6ee         ddfd7            Z%	 	 dTd8ee&         dee         ddfd9Z'd:eded;eddfd<Z(d eddfd=Z)	 	 dTd>e*d?ee         d@ee         ddfdAZ+ e$dBgdCd23          	 	 	 dUdDe!dEee         dFee         dBee         ddf
dG            Z,	 dVdHee-         ddfdIZ.	 dVdJedee/         ddfdKZ0dLeddfdMZ1e2de!fdN            Z3defdOZ4dS )W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	                      | _        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_builderr   
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__R   s]    	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rB   s    r(   r3   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| _	        | j                             ddd          | _
        dS )z$Initialize basic connection metrics.z db.client.connection.create_timeszTime to create a new connectionrG   rH   rI   #explicit_bucket_boundaries_advisoryz'redis.client.connection.relaxed_timeoutz{relaxation}z@Counts up for relaxed timeout, counts down for unrelaxed timeoutrF   zredis.client.connection.handoffz	{handoff}zIConnections that have been handed off (e.g., after a MOVING notification)Nzdb.client.connection.count{connection}z4Number of connections currently in the pool by state)r+   create_histogramr,   buckets_connection_create_timeconnection_create_timecreate_up_down_counterconnection_relaxed_timeoutrJ   connection_handoffconnection_countconnection_count_updownrN   s    r(   r7   z4RedisMetricsCollector._init_connection_basic_metrics   s    &*j&A&A39040Z	 'B '
 '
# +/**K*K:Z +L +
 +
' #'*";";2c #< #
 #
 !% (,z'H'H-N (I (
 (
$$$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.rF   zdb.client.connection.wait_timerP   z/Time to obtain an open connection from the poolrQ   zredis.client.connection.closedrS   z"Total number of closed connectionsN)r+   rJ   connection_timeoutsrT   r,   buckets_connection_wait_timeconnection_wait_timeconnection_closedrN   s    r(   r9   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.durationrP   zCommand execution durationrQ   N)r+   rT   r,   buckets_operation_durationoperation_durationrN   s    r(   r5   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 messagesrF   N)r+   rJ   pubsub_messagesrN   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.lagrP   zkEnd-to-end lag per message, showing how stale are the messages when the application starts processing them.rQ   N)r+   rT   r,   "buckets_stream_processing_duration
stream_lagrN   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 cacherF   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+   rJ   csc_requestscsc_evictionscsc_network_savedrN   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)
        rK   Nrn   ro   )rp   rq   rs   )rr   rt      
attributes)hasattrr0   build_base_attributesupdatebuild_operation_attributesbuild_error_attributesrK   add)	rB   rn   ro   rp   rq   rr   rs   rt   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
        rL   Nrv   )rp   rq   rw   rx   )rz   r0   r{   r|   r}   r   rL   r   )rB   rn   ro   rp   rq   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
        rM   N)r   r   r   rw   rx   )rz   r0   build_geo_failover_attributesrM   r   )rB   r   r   r   r   s        r(   record_geo_failoverz)RedisMetricsCollector.record_geo_failoverC  s`     t_-- 	F!?? @ 
 
 !%%aE%:::r'   rw   	pool_nameconnection_statecounterc                     t          | d          sdS | j                            ||          }| j                            ||           dS )a  
        Record a connection count change for a single state.

        Args:
            pool_name: Connection pool name
            connection_state: State to update (IDLE or USED)
            counter: Number to add (positive) or subtract (negative)
        r[   N)r   r   rx   )rz   r0   build_connection_attributesr[   r   )rB   r   r   r   r   s        r(   record_connection_countz-RedisMetricsCollector.record_connection_count]  sc     t677 	F!==- > 
 
 	$((U(CCCCCr'   z{Connection count is now tracked via record_connection_count(). This functionality will be removed in the next major versionz7.4.0)r   versioncallbackc                     t           j        | j        j        vrdS | j                            ddd|g          | _        dS )z
        Initialize observable gauge for connection count metric.

        Args:
            callback: Callback function to retrieve connection counts
        Nz%db.client.connection.count.deprecatedrS   zThe number of connections that are currently in state described by the state attribute (deprecated - use db.client.connection.count instead)rG   rH   rI   	callbacks)r   r6   r,   r2   r+   create_observable_gaugerZ   rB   r   s     r(   init_connection_countz+RedisMetricsCollector.init_connection_countt  sU     't{/HHHF
 !%
 B B8e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,   r2   	csc_itemsr+   r   r   s     r(   init_csc_itemsz$RedisMetricsCollector.init_csc_items  sR     ?$+";;;DN;F;;)Oj	 < 
 
r'   c                     t          | d          sdS | j                            |          }| j                            d|           dS )zo
        Record a connection timeout event.

        Args:
            pool_name: Connection pool name
        r]   Nr   rw   rx   )rz   r0   r   r]   r   rB   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
        rV   Nr   rx   )rz   r0   r   r   rV   record)rB   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   rx   )rz   r0   r   r_   r   )rB   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   r   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
        rc   N)rn   ro   r   )r   rp   rq   rs   r   rr   rx   )
rz   r,   should_track_commandr0   r{   r|   r}   r~   rc   r   )rB   r   r   rn   ro   r   r   rr   rp   rq   rs   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   rw   rx   )	rz   r0   r   valuer   r|   r~   r`   r   )rB   r   rr   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)
        rX   Nr   rw   rx   )rz   r0   r   r   rX   r   )rB   r   r   r   r   s        r(   !record_connection_relaxed_timeoutz7RedisMetricsCollector.record_connection_relaxed_timeout7  sk     t9:: 	F!===XX6H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
        rY   Nr   rw   rx   )rz   r0   r   rY   r   r   s      r(   record_connection_handoffz/RedisMetricsCollector.record_connection_handoffL  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
        re   N)r   r   r   rw   rx   )rz   r0   build_pubsub_message_attributesre   r   )rB   r   r   r   r   s        r(   record_pubsub_messagez+RedisMetricsCollector.record_pubsub_message^  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
        rh   N)r   r   rx   )rz   r0   build_streaming_attributesrh   r   )rB   r   r   r   r   r   s         r(   record_streaming_lagz*RedisMetricsCollector.record_streaming_lagx  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')
        rk   N)r   rw   rx   )rz   r0   build_csc_attributesrk   r   )rB   r   r   s      r(   record_csc_requestz(RedisMetricsCollector.record_csc_request  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
        rl   N)r   rx   )rz   r0   r   rl   r   )rB   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
        rm   Nrx   )rz   r0   r   rm   r   )rB   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,   rN   s    r(   __repr__zRedisMetricsCollector.__repr__  s    QdjQQ4;QQQQr'   )rD   N)NNNNNNN)rw   )	NNNNNNNNN)NN)NNN)N)5r   r    r!   r"   
METER_NAMEMETER_VERSIONr   r   rC   r3   r7   r9   r5   r;   r=   r?   r   strint	Exceptionboolr   r   r   r   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*   B   s       
 
 JM"9e "9Z "9 "9 "9 "9H
 
 
 
( 
  
  
  
D
 
 
 
*
 
 
 

 
 
 

 
 
 

 
 
 
0 )-%).2+/*.(,&*,4 ,4 ,4 c],4 'sm	,4
 $C=,4 Y',4 !,4 d^,4 ,4 ,4 ,4\"@"@ "@ "	"@
 "@  "@ "@ "@ "@H;89; 67; "	; ; ; ;< 	D DD *D 	D
 
D D D D. G  


 

 
 
 

0

 

 
 
 
(: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   r   redis.observability.configr   r   redis.utilsr   r   	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. . . . .$ . . .$U
R U
R U
R U
R U
R U
R U
R U
R U
R U
Rs   .A7 7B	B	