o
    i"                     @   s   d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 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 d d
lmZ d dlmZ d dlmZ eeZG dd de
jZe ZdS )    N)Iterable)Optional)config)agent)periodic)
get_logger)
RCCallback)RemoteConfigClient)REMOTE_CONFIG_AGENT_ENDPOINT)ServiceStatus)	StopWatchc                	       s"  e Zd ZdZdZd, fddZd,ddZd,d	d
Zd,ddZde	fddZ
d,ddZd-de	ddfddZd-de	ddfddZd, fddZdedede	fddZg fdededeej ddfddZdeddfd d!Zdeddfd"d#Zd$d% Zdedee fd&d'Zd.d(d)Zd,d*d+Z  ZS )/RemoteConfigPollerzRemote configuration worker.

    This implements a finite-state machine that allows checking the agent for
    the expected endpoint, which could be enabled after the client is started.
    TreturnNc                    s>   t t| jtjddd t | _| j| _t	
 | _t | _d S )NTF)intervalno_wait_at_startautorestart)superr   __init__ddconfig_remote_config_poll_intervalr	   _client_agent_check_stateosgetpid
_parent_iddict_capabilities_mapself	__class__ X/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/internal/remoteconfig/worker.pyr      s   

zRemoteConfigPoller.__init__c                 C   sn   zt  }W n ty   d }Y nw |r0|dg }|r0t|v s&dt |v r0| j| _|   d S td d S )N	endpoints/a2  Agent is down or Remote Config is not enabled in the Agent
Check your Agent version, you need an Agent running on 7.39.1 version or above.
Check Your Remote Config environment variables on your Agent:
DD_REMOTE_CONFIGURATION_ENABLED=true
See: https://docs.datadoghq.com/agent/guide/how_remote_config_works/)	r   info	Exceptiongetr
   _onliner   logdebug)r   r&   r$   r"   r"   r#   r   '   s   zRemoteConfigPoller._agent_checkc                 C   sh   t  }| j s| j| _	 W d    d S W d    n1 s w   Y  | }td|| jj d S )Nzrequest config in %.5fs to %s)	r   r   requestr   r   elapsedr*   r+   	agent_url)r   swr-   r"   r"   r#   r)   >   s   
zRemoteConfigPoller._onlinec                 C   s   |   S N)r   r   r"   r"   r#   r   H   s   zRemoteConfigPoller.periodicc                 C   s0   t j}|r| jr| jtjkrdS |   dS dS )NTF)r   _remote_config_enabled_enablestatusr   RUNNINGstart)r   rc_env_enabledr"   r"   r#   enableK   s   
zRemoteConfigPoller.enablec                 C   sd   d| _ tdt t  | j  | jjr0| j	  tdt t t
| jj  dS dS )z6Client Id needs to be refreshed when application forksFz7[%d][P: %d] Remote Config Poller fork. Refreshing statezC[%d][P: %d] Restarted global subscriber for registered products: %sN)r2   r*   r+   r   r   getppidr   renew_id_product_callbacksrestart_subscriberlistkeysr   r"   r"   r#   reset_at_forkW   s   

z RemoteConfigPoller.reset_at_forkFjoinc                 C   s&   t dt | j | jj|d dS )z"Stop the global subscriber thread.z5[%s][P: %s] Remote Config Poller. Stopping subscriberr?   N)r*   r+   r   r   r   r   stop_subscriberr   r?   r"   r"   r#   rA   g   s   z"RemoteConfigPoller.stop_subscriberc                 C   s6   | j |d | j  | jtjkrd S | j|d d S )Nr@   )rA   r   reset_productsr3   r   STOPPEDstoprB   r"   r"   r#   disablep   s
   
zRemoteConfigPoller.disablec                    s<   |    | jtjks| jd u rd S tt| j|i | d S r0   )rA   r3   r   rD   _workerr   r   _stop_service)r   argskwargsr    r"   r#   rH   y   s   z RemoteConfigPoller._stop_serviceproductcallbackc                 C   s   | j ||S )a<  Update the callback for a registered product.

        Some Products fork and restart their instances when application creates new process. In that case,
        we need to update the callback instance to ensure the instance of the child process receives correctly the
        Remote Configuration payloads.
        )r   update_product_callback)r   rK   rL   r"   r"   r#   rM      s   z*RemoteConfigPoller.update_product_callbackcapabilitiesc                 C   s   zC| j js	|   | j || |D ]}| j|||kr(td|| j|  q|| j|< q| j | | j 	 sA| j 
  W dS W dS  tyT   tjddd Y dS w )a  Register a product callback for remote configuration updates.

        Registration only registers the callback and capabilities. To include the
        product in client payloads (enable it), call enable_product() separately.

        Args:
            product: Product name (e.g., "ASM_FEATURES", "LIVE_DEBUGGING")
            callback: Callback function to invoke when payloads are received in child processes
            capabilities: list of capabilities to register for this product
        zFCapability %s already registered for product %s, skipping registrationzerror starting the RCM clientTexc_infoN)r   r:   r7   register_callbackr   r(   r*   erroradd_capabilitiesis_subscriber_runningstart_subscriberr'   r+   )r   rK   rL   rN   
capabilityr"   r"   r#   rQ      s(   
z$RemoteConfigPoller.register_callbackc                 C      | j | dS )a@  Enable a product to be included in client payloads.

        When a product is enabled, it will be added to the 'products' list
        in payloads sent to the agent, indicating that this client wants
        to receive configurations for this product.

        Args:
            product: Product name to enable
        N)r   enable_productr   rK   r"   r"   r#   rX         
z!RemoteConfigPoller.enable_productc                 C   rW   )a2  Disable a product, removing it from client payloads.

        The product's callback remains registered and can still receive
        configurations, but the client will not request configurations
        for this product from the agent.

        Args:
            product: Product name to disable
        N)r   disable_productrY   r"   r"   r#   r[      rZ   z"RemoteConfigPoller.disable_productc                 C   sV   t jrdS z| j| | jjs|   W dS W dS  ty*   tjddd Y dS w )zUnregister a product callback.

        This removes the callback but does not disable the product. To also
        disable the product, call disable_product() separately.

        Args:
            product: Product name to unregister
        Nz#error unregistering from RCM clientTrO   )		rc_configskip_shutdownr   unregister_productr:   rF   r'   r*   r+   rY   r"   r"   r#   unregister_callback   s   	z&RemoteConfigPoller.unregister_callbackc                 C   s   | j j|S )z*Get the registered callback for a product.)r   r:   r(   rY   r"   r"   r#   get_registered   s   z!RemoteConfigPoller.get_registeredc                 C   s   |    | S r0   )r7   r   r"   r"   r#   	__enter__   s   zRemoteConfigPoller.__enter__c                 G   s   | j dd d S )NTr@   )rF   )r   rI   r"   r"   r#   __exit__   s   zRemoteConfigPoller.__exit__)r   N)F)r   r   )__name__
__module____qualname____doc__r2   r   r   r)   r   boolr7   r>   rA   rF   rH   strr   rM   r   enumIntFlagrQ   rX   r[   r_   r   r`   ra   rb   __classcell__r"   r"   r    r#   r      s:    
	



		
+
r   )ri   r   typingr   r   ddtracer   r   ddtrace.internalr   r   ddtrace.internal.loggerr   ddtrace.internal.remoteconfigr   $ddtrace.internal.remoteconfig.clientr	   r\   'ddtrace.internal.remoteconfig.constantsr
   ddtrace.internal.servicer   ddtrace.internal.utils.timer   rc   r*   PeriodicServicer   remoteconfig_pollerr"   r"   r"   r#   <module>   s$     
]