o
    i"                     @   s   d dl mZ d dlmZ d dlmZ d dlZd dlZd dlZd dlm	Z	 d dlm
Z
 d dlmZ G dd	 d	eZG d
d deZeG dd dZdS )    )division)	dataclass)fieldN)Any)Callable)Optionalc                   @   s   e Zd ZdZdZddedefddZdefd	d
Z	dededdfddZ
dedefddZdeddfddZdefddZedefddZdd ZdS )RateLimiterz4
    A token bucket rate limiter implementation
    )
_lockcurrent_window_nstime_windowlast_update_ns
max_tokensprev_window_rate
rate_limittokenstokens_allowedtokens_total    eAr   r   c                 C   sH   || _ || _|| _|| _t | _d| _d| _d| _	d| _
t | _dS )a  
        Constructor for RateLimiter

        :param rate_limit: The rate limit to apply for number of requests per second.
            rate limit > 0 max number of requests to allow per second,
            rate limit == 0 to disallow all requests,
            rate limit < 0 to allow all requests
        :type rate_limit: :obj:`int`
        :param time_window: The time window where the rate limit applies in nanoseconds. default value is 1 second.
        :type time_window: :obj:`float`
        r   N)r   r   r   r   timemonotonic_nsr   r
   r   r   r   	threadingLockr	   )selfr   r    r   Q/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/internal/rate_limiter.py__init__   s   
zRateLimiter.__init__returnc                 C   s"   t  }| |}| || |S )z
        Check whether the current request is allowed or not

        This method will also reduce the number of available tokens by 1

        :returns: Whether the current request is allowed or not
        :rtype: :obj:`bool`
        )r   r   _is_allowed_update_rate_counts)r   timestamp_nsallowedr   r   r   
is_allowed9   s   
zRateLimiter.is_allowedr    r   Nc                 C   s^   | j s|| _ n|| j  | jkr|  | _d| _d| _|| _ |r&|  jd7  _|  jd7  _d S )Nr      )r
   r   _current_window_rater   r   r   )r   r    r   r   r   r   r   J   s   
zRateLimiter._update_rate_countsc                 C   s~   | j dkrdS | j dk rdS | j$ | | | jdkr,|  jd8  _	 W d    dS 	 W d    dS 1 s8w   Y  d S )Nr   FTr"   )r   r	   
_replenishr   )r   r   r   r   r   r   ^   s   



$zRateLimiter._is_allowedc                 C   sZ   z| j | jkrW || _d S || j | j }W || _n|| _w t| j| j || j  | _ d S N)r   r   r   r   minr   )r   r   elapsedr   r   r   r$   q   s   
	
zRateLimiter._replenishc                 C   s   | j sdS | j| j  S )N      ?)r   r   r   r   r   r   r#      s   z RateLimiter._current_window_ratec                 C   s$   | j du r	|  S |  | j  d S )z
        Return the effective sample rate of this rate limiter

        :returns: Effective sample rate value 0.0 <= rate <= 1.0
        :rtype: :obj:`float``
        Ng       @)r   r#   r)   r   r   r   effective_rate   s   
	zRateLimiter.effective_ratec                 C   s   d | jj| j| j| j| jS )NzJ{}(rate_limit={!r}, tokens={!r}, last_update_ns={!r}, effective_rate={!r}))format	__class____name__r   r   r   r*   r)   r   r   r   __repr__   s   zRateLimiter.__repr__)r   )r-   
__module____qualname____doc__	__slots__intfloatr   boolr!   r   r   r$   r#   propertyr*   r.   r   r   r   r   r      s    	r   c                   @   s   e Zd ZdS )RateLimitExceededN)r-   r/   r0   r   r   r   r   r7      s    r7   c                	   @   s   e Zd ZU dZeed< dZeed< dZeed< dZ	e
e ed< d	Zeed
< ed	dZeed< ed	dZeed< ed	ejdZeed< ed	ejdZejed< dd Zdde
edef  dededefddZdedef dedef fddZdS )BudgetRateLimiterWithJittera  A budget rate limiter with jitter.

    The jitter is induced by a uniform distribution. The rate limit can be
    specified with ``limit_rate`` and the time scale can be controlled with the
    ``tau`` parameter (which defaults to 1 second). The initial budget is the
    product between ``limit_rate`` and the time-scale parameter ``tau``, which
    is also taken as the maximum budget. By default, the ``RateLimitExceeded``
    exception is raised when the rate limit is exceeded. This can be changed by
    setting ``raise_on_exceed`` to ``False``. The ``on_exceed`` argument can be
    used to pass a callback that is to be called whenever the rate limit is
    exceeded. The ``call_once`` argument controls whether the callback should be
    called only once for every rate limit excess or every time the rate limiter
    is invoked.

    Instances of this class can also be used as decorators.

    Since the initial and maximum budget are set to ``limit_rate * tau``, the
    rate limiter could have an initial burst phase. When this is not desired,
    ``tau`` should be set to ``1 / limit_rate`` to ensure an initial and maximum
    budget of ``1``.
    
limit_rater(   tauTraise_on_exceedN	on_exceedF	call_once)initbudget
max_budget)r>   default_factory	last_timer	   c                 C   sR   | j tdkrtd | _| _n| j r| j | j  | _| _nd | _| _d| _d S )Ninfr(   F)r9   r4   r?   r@   r:   _on_exceed_calledr)   r   r   r   __post_init__   s   
z)BudgetRateLimiterWithJitter.__post_init__f.argskwargsr   c                 O   s   d}| j 1 t }|  j| j|| j  dt   7  _| jdk}| j| jkr,| j| _|| _W d   n1 s9w   Y  |rWd| _|  jd8  _|durU||i |S dS | j	durn| j
sd| 	  n
| jsn| 	  d| _| jrtt tS )z?Make rate-limited calls to a function with the given arguments.Fg      ?r(   NT)r	   r   	monotonicr?   r9   rB   randomr@   rD   r<   r=   r;   r7   )r   rF   rG   rH   should_callnowr   r   r   limit   s,   &


z!BudgetRateLimiterWithJitter.limitc                    s    fdd}|S )Nc                     s   j  g| R i |S r%   )rM   )rG   rH   rF   r   r   r   	limited_f   s   z7BudgetRateLimiterWithJitter.__call__.<locals>.limited_fr   )r   rF   rO   r   rN   r   __call__   s   z$BudgetRateLimiterWithJitter.__call__r%   )r-   r/   r0   r1   r4   __annotations__r:   r;   r5   r<   r   r   r=   r   r?   r@   r   rI   rB   r   r   r	   rE   r   rM   rP   r   r   r   r   r8      s   
 (	&r8   )
__future__r   dataclassesr   r   rJ   r   r   typingr   r   r   objectr   	Exceptionr7   r8   r   r   r   r   <module>   s     