o
    <‘ðid  ã                   @   sò  U d Z ddlmZ ddlmZmZmZmZ ddlmZm	Z	m
Z
mZmZmZ ddlmZmZ ddlmZ ddlmZ ddlmZmZmZ erWdd	lmZ dd
lmZ ddlmZ daee e d< dZ!dZ"edgddd�							dsd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dfdd„ƒZ(dd de$ddfd!d"„Z)	#dtd$e#d%e	d&e%ddfd'd(„Z*ed)d*d+�dud,d-„ƒZ+ed)d*d+�d.ed  ddfd/d0„ƒZ,d$e#ddfd1d2„Z-d$e#de$ddfd3d4„Z.		dvd5ee d6ee& ddfd7d8„Z/d9e#d:e#d;e'ddfd<d=„Z0d$e#ddfd>d?„Z1							@dwdee# dee% dAee# dBee% d6ee& dee% dCe'ddfdDdE„Z2		dvdFedGee# dHee' ddfdIdJ„Z3edKgdLdd�			dxdMe$dNee# dOee# dKee# ddf
dPdQ„ƒZ4edKgdLdd�		dvdOee# dKee# ddfdRdS„ƒZ5de#de%dAe#dBe%d:e#ddfdTdU„Z6	dydVee fdWdX„Z7dudYdZ„Z8	dyd[ed$ee# ddfd\d]„Z9	dyd^e%d_ee
 ddfd`da„Z:dbe%ddfdcdd„Z;dedfdgdfd_eddfdhdi„Z<dee fdjdk„Z=dedl fdmdn„Z>dudodp„Z?de'fdqdr„Z@dS )zaT  
Simple, clean API for recording observability metrics.

This module provides a straightforward interface for Redis core code to record
metrics without needing to know about OpenTelemetry internals.

Usage in Redis core code:
    from redis.observability.recorder import record_operation_duration

    start_time = time.monotonic()
    # ... execute Redis command ...
    record_operation_duration(
        command_name='SET',
        duration_seconds=time.monotonic() - start_time,
        server_address='localhost',
        server_port=6379,
        db_namespace='0',
        error=None
    )
é    )Údatetime)ÚTYPE_CHECKINGÚCallableÚListÚOptional)ÚAttributeBuilderÚConnectionStateÚ	CSCReasonÚ	CSCResultÚGeoFailoverReasonÚPubSubDirection)ÚCloseReasonÚRedisMetricsCollector)Úget_observability_instance)Ú!get_observables_registry_instance)Údeprecated_argsÚdeprecated_functionÚstr_if_bytes)ÚConnectionPoolInterface)ÚSyncDatabase)Ú
OTelConfigNÚ_metrics_collectorÚ	csc_itemsÚconnection_countÚ
batch_sizezXThe batch_size argument is no longer used and will be removed in the next major version.z7.2.1)Úargs_to_warnÚreasonÚversionÚcommand_nameÚduration_secondsÚserver_addressÚserver_portÚdb_namespaceÚerrorÚis_blockingÚretry_attemptsÚreturnc	           	      C   sT   t du rtƒ a t du rdS zt j| |||||||||d�
 W dS  ty)   Y dS w )aŽ  
    Record a Redis command execution duration.

    This is a simple, clean API that Redis core code can call directly.
    If observability is not enabled, this returns immediately with zero overhead.

    Args:
        command_name: Redis command name (e.g., 'GET', 'SET')
        duration_seconds: Command execution time in seconds
        server_address: Redis server address
        server_port: Redis server port
        db_namespace: Redis database index
        error: Exception if command failed, None if successful
        is_blocking: Whether the operation is a blocking command
        batch_size: Number of commands in batch (for pipelines/transactions)
        retry_attempts: Number of retry attempts made

    Example:
        >>> start = time.monotonic()
        >>> # ... execute command ...
        >>> record_operation_duration('SET', time.monotonic() - start, 'localhost', 6379, '0')
    N)
r   r   r    r!   r"   Ú
error_typeÚnetwork_peer_addressÚnetwork_peer_portr$   r%   )r   Ú_get_or_create_collectorÚrecord_operation_durationÚ	Exception)	r   r   r    r!   r"   r#   r$   r   r%   © r-   ú[/root/parts/websockify/install/lib/python3.10/site-packages/redis/observability/recorder.pyr+   2   s(   )öþr+   Úconnection_poolr   c                 C   óD   t du rtƒ a t du rdS z
t j| |d� W dS  ty!   Y dS w )as  
    Record connection creation time.

    Args:
        connection_pool: Connection pool implementation
        duration_seconds: Time taken to create connection in seconds

    Example:
        >>> start = time.monotonic()
        >>> # ... create connection ...
        >>> record_connection_create_time('ConnectionPool<localhost:6379>', time.monotonic() - start)
    N©r/   r   )r   r*   Úrecord_connection_create_timer,   r1   r-   r-   r.   r2   t   s   þÿr2   é   Ú	pool_nameÚconnection_stateÚcounterc                 C   óF   t du rtƒ a t du rdS zt j| ||d� W dS  ty"   Y dS w )a€  
    Record a connection count change for a single state.

    Args:
        pool_name: Connection pool identifier
        connection_state: State to update (IDLE or USED)
        counter: Number to add (positive) or subtract (negative)

    Example:
        # New connection created (goes to IDLE first)
        >>> record_connection_count('pool_abc123', ConnectionState.IDLE, 1)

        # Acquire from pool (transition)
        >>> record_connection_count('pool_abc123', ConnectionState.IDLE, -1)
        >>> record_connection_count('pool_abc123', ConnectionState.USED, 1)

        # Release to pool (transition)
        >>> record_connection_count('pool_abc123', ConnectionState.USED, -1)
        >>> record_connection_count('pool_abc123', ConnectionState.IDLE, 1)

        # Pool disconnect 5 idle connections
        >>> record_connection_count('pool_abc123', ConnectionState.IDLE, -5)
    N©r4   r5   r6   )r   r*   Úrecord_connection_countr,   r8   r-   r-   r.   r9   •   s   ýÿr9   z{Connection count is now tracked via record_connection_count(). This functionality will be removed in the next major versionz7.4.0)r   r   c                  C   sB   t ƒ } | du r	dS dd„ }z	| j|d� W dS  ty    Y dS w )zB
    Initialize observable gauge for connection count metric.
    Nc                 S   ó.   t ƒ }| t¡}g }|D ]}| |ƒ ¡ q|S ©N)r   ÚgetÚCONNECTION_COUNT_REGISTRY_KEYÚextend©Ú__Úobservables_registryÚ	callbacksÚobservationsÚcallbackr-   r-   r.   Úobservable_callbackÏ   ó   
z2init_connection_count.<locals>.observable_callback©rD   )r*   Úinit_connection_countr,   )Ú	collectorrE   r-   r-   r.   rH   Â   s   	
ÿÿrH   Úconnection_poolsc                    sZ   t ƒ }|du r	dS zddlm‰  ‡ ‡fdd„}tƒ }| t|¡ W dS  ty,   Y dS w )zG
    Add connection pools to connection count observable registry.
    Nr   ©ÚObservationc                     s6   g } ˆD ]}|  ¡ D ]\}}|  ˆ ||d�¡ q
q| S )N©Ú
attributes)Úget_connection_countÚappend)rC   r/   ÚcountrN   ©rL   rJ   r-   r.   Úconnection_count_callbackô   s   ÿzBregister_pools_connection_count.<locals>.connection_count_callback)r*   Úopentelemetry.metricsrL   r   Úregisterr=   r,   )rJ   rI   rS   rA   r-   rR   r.   Úregister_pools_connection_countá   s   
ÿÿrV   c                 C   óB   t du rtƒ a t du rdS z	t j| d� W dS  ty    Y dS w )z»
    Record a connection timeout event.

    Args:
        pool_name: Connection pool identifier

    Example:
        >>> record_connection_timeout('ConnectionPool<localhost:6379>')
    N©r4   )r   r*   Úrecord_connection_timeoutr,   rX   r-   r-   r.   rY     ó   ÿÿrY   c                 C   r0   )at  
    Record time taken to obtain a connection from the pool.

    Args:
        pool_name: Connection pool identifier
        duration_seconds: Wait time in seconds

    Example:
        >>> start = time.monotonic()
        >>> # ... wait for connection from pool ...
        >>> record_connection_wait_time('ConnectionPool<localhost:6379>', time.monotonic() - start)
    N©r4   r   )r   r*   Úrecord_connection_wait_timer,   r[   r-   r-   r.   r\     s   þÿr\   Úclose_reasonr'   c                 C   r0   )a  
    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

    Example:
        >>> record_connection_closed('ConnectionPool<localhost:6379>', 'idle_timeout')
    N©r]   r'   )r   r*   Úrecord_connection_closedr,   r^   r-   r-   r.   r_   >  s   þÿr_   Úconnection_nameÚmaint_notificationÚrelaxedc                 C   r7   )a_  
    Record a connection timeout relaxation event.

    Args:
        connection_name: Connection identifier
        maint_notification: Maintenance notification type
        relaxed: True to count up (relaxed), False to count down (unrelaxed)

    Example:
        >>> record_connection_relaxed_timeout('localhost:6379_a1b2c3d4', 'MOVING', True)
    N©r`   ra   rb   )r   r*   Ú!record_connection_relaxed_timeoutr,   rc   r-   r-   r.   rd   \  s   ýÿrd   c                 C   rW   )zÝ
    Record a connection handoff event (e.g., after MOVING notification).

    Args:
        pool_name: Connection pool identifier

    Example:
        >>> record_connection_handoff('ConnectionPool<localhost:6379>')
    NrX   )r   r*   Úrecord_connection_handoffr,   rX   r-   r-   r.   re   }  rZ   re   Tr(   r)   Úis_internalc              	   C   sN   t du rtƒ a t du rdS zt j| ||||||d� W dS  ty&   Y dS w )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 (Exception)
        retry_attempts: Retry attempts
        is_internal: Whether the error is internal (e.g., timeout, network error)

    Example:
        >>> record_error_count('localhost', 6379, 'localhost', 6379, ConnectionError(), 3)
    N©r    r!   r(   r)   r'   r%   rf   )r   r*   Úrecord_error_countr,   rg   r-   r-   r.   rh   ˜  s"   ù	ÿrh   Ú	directionÚchannelÚshardedc                 C   sj   t du rtƒ a t du rdS |}|durtƒ }|dur|jrd}zt j| ||d� W dS  ty4   Y dS w )a5  
    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

    Example:
        >>> record_pubsub_message(PubSubDirection.PUBLISH, 'channel', False)
    N)ri   rj   rk   )r   r*   Ú_get_configÚhide_pubsub_channel_namesÚrecord_pubsub_messager,   )ri   rj   rk   Úeffective_channelÚconfigr-   r-   r.   rn   Å  s$   ýÿrn   Ú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                 C   sj   t du rtƒ a t du rdS |}|durtƒ }|dur|jrd}zt j| ||d� W dS  ty4   Y dS w )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
    N©rr   rs   rt   )r   r*   rl   Úhide_stream_namesÚrecord_streaming_lagr,   )rr   rs   rt   rq   Úeffective_stream_namerp   r-   r-   r.   rw   í  s$   ýÿrw   c                 C   s\  t du rtƒ a t du rdS | sdS z’t ¡  ¡ }tƒ }|duo!|j}t| tƒrg|  	¡ D ]8\}}|r3dnt
|ƒ}|D ])}	|	D ]$}
|
\}}t
|ƒ}| d¡\}}td|t|ƒd  ƒ}t j|||d� q=q9q+W dS | D ]7}t
|d ƒ}|rudn|}|d D ]$}
|
\}}t
|ƒ}| d¡\}}td|t|ƒd  ƒ}t j|||d� q{qiW dS  ty­   Y dS w )aQ  
    Record streaming lag from XREAD/XREADGROUP response.

    Parses the response and calculates lag for each message based on message ID timestamp.

    Args:
        response: Response from XREAD/XREADGROUP command
        consumer_group: Consumer group name (for XREADGROUP)
        consumer_name: Consumer name (for XREADGROUP)
    Nú-g        iè  ru   r   r3   )r   r*   r   ÚnowÚ	timestamprl   rv   Ú
isinstanceÚdictÚitemsr   ÚsplitÚmaxÚintrw   r,   )Úresponsert   rq   rz   rp   rv   rs   Ústream_messagesrx   ÚmessagesÚmessageÚ
message_idÚ_r{   rr   Ústream_entryr-   r-   r.   Ú"record_streaming_lag_from_response  s\   
ÿýùÿüýùüÿr‰   c                 C   sJ   t du rtƒ a t du rdS zt j| ||||d� W dS  ty$   Y dS w )a§  
    Record a 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 type (e.g., 'MOVING', 'MIGRATING')

    Example:
        >>> record_maint_notification_count('localhost', 6379, 'localhost', 6379, 'MOVING')
    N©r    r!   r(   r)   ra   )r   r*   Úrecord_maint_notification_countr,   rŠ   r-   r-   r.   r‹   h  s   ûÿr‹   Úresultc                 C   rW   )zm
    Record a Client Side Caching (CSC) request.

    Args:
        result: CSC result ('hit' or 'miss')
    N©rŒ   )r   r*   Úrecord_csc_requestr,   r�   r-   r-   r.   rŽ   �  ó   ÿÿrŽ   c                  C   sJ   t du rtƒ a t du rdS dd„ } z	t j| d� W dS  ty$   Y dS w )z;
    Initialize observable gauge for CSC items metric.
    Nc                 S   r:   r;   )r   r<   ÚCSC_ITEMS_REGISTRY_KEYr>   r?   r-   r-   r.   rE   ²  rF   z+init_csc_items.<locals>.observable_callbackrG   )r   r*   Úinit_csc_itemsr,   )rE   r-   r-   r.   r‘   §  s   
ÿÿr‘   rD   c                    sd   t du rtƒ a t du rdS ddlm‰  ‡ ‡‡fdd„}ztƒ }| t|¡ W dS  ty1   Y dS w )zÄ
    Adds given callback to CSC items observable registry.

    Args:
        callback: Callback function that returns the cache size
        pool_name: Connection pool name for observability
    Nr   rK   c                      s   ˆ ˆƒ t jˆd�d�gS )NrX   rM   )r   Úbuild_csc_attributesr-   ©rL   rD   r4   r-   r.   Úcsc_items_callbackÙ  s
   
þÿz7register_csc_items_callback.<locals>.csc_items_callback)r   r*   rT   rL   r   rU   r�   r,   )rD   r4   r”   rA   r-   r“   r.   Úregister_csc_items_callbackÄ  s   ÿr•   rQ   r   c                 C   r0   )zˆ
    Record a Client Side Caching (CSC) eviction.

    Args:
        count: Number of evictions
        reason: Reason for eviction
    N©rQ   r   )r   r*   Úrecord_csc_evictionr,   r–   r-   r-   r.   r—   è  s   þÿr—   Úbytes_savedc                 C   rW   )z„
    Record the number of bytes saved by using Client Side Caching (CSC).

    Args:
        bytes_saved: Number of bytes saved
    N©r˜   )r   r*   Úrecord_csc_network_savedr,   r™   r-   r-   r.   rš     r�   rš   Ú	fail_fromr   Úfail_toc                 C   r7   )zŸ
    Record a geo failover.

    Args:
        fail_from: Database failed from
        fail_to: Database failed to
        reason: Reason for the failover
    N©r›   rœ   r   )r   r*   Úrecord_geo_failoverr,   r�   r-   r-   r.   rž     s   ýÿrž   c                  C   sj   z!t ƒ  ¡ } | du s| jjsW dS |  ¡  tjtj¡}t|| jƒW S  t	y+   Y dS  t
y4   Y dS w )z–
    Get or create the global metrics collector.

    Returns:
        RedisMetricsCollector instance if observability is enabled, None otherwise
    N)r   Úget_provider_managerrp   Úenabled_telemetryÚget_meter_providerÚ	get_meterr   Ú
METER_NAMEÚMETER_VERSIONÚImportErrorr,   )ÚmanagerÚmeterr-   r-   r.   r*   9  s   
ÿþr*   r   c                  C   s6   zt ƒ  ¡ } | du rW dS | jW S  ty   Y dS w )zš
    Get the OTel configuration from the observability manager.

    Returns:
        OTelConfig instance if observability is enabled, None otherwise
    N)r   rŸ   rp   r,   )r¦   r-   r-   r.   rl   T  s   
ÿrl   c                   C   s   da dS )zM
    Reset the global collector (used for testing or re-initialization).
    N)r   r-   r-   r-   r.   Úreset_collectord  s   r¨   c                   C   s   t du rtƒ a t duS )zw
    Check if observability is enabled.

    Returns:
        True if metrics are being collected, False otherwise
    N)r   r*   r-   r-   r-   r.   Ú
is_enabledl  s   	r©   )NNNNNNN)r3   )r&   N)NN)NNNNNNT)NNNr;   )AÚ__doc__r   Útypingr   r   r   r   Úredis.observability.attributesr   r   r	   r
   r   r   Úredis.observability.metricsr   r   Úredis.observability.providersr   Úredis.observability.registryr   Úredis.utilsr   r   r   Úredis.connectionr   Úredis.multidb.databaser   Úredis.observability.configr   r   Ú__annotations__r�   r=   ÚstrÚfloatr�   r,   Úboolr+   r2   r9   rH   rV   rY   r\   r_   rd   re   rh   rn   rw   r‰   r‹   rŽ   r‘   r•   r—   rš   rž   r*   rl   r¨   r©   r-   r-   r-   r.   Ú<module>   sÔ    ý÷ÿþýüûúùø	÷
ö=ÿþ
ý$ýÿþý
ü-ýýÿþÿ
þÿþ
ý!þÿþ
ýÿþý
ü!ÿ
þùÿþýüûúù
ø/ýÿþý
ü(ýüÿþýüû'ýýþýüJÿþýüû
ú(ÿ
ÿ
þÿþ
ý&þÿþ
ýÿ
þÿþý
ü
