o
    i$                     @   s  U d Z ddl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Zddl	m
Z
 ddl	mZ ddl	mZ ddl	mZ d	Zd
e Zd
e Zde ZeG dd dZe ZdedejfddZi ZdededdfddZG dd dZedZeeeeeef ef Zedd Z e
eef e!d< eej"dd
dZ#dej$de%fdd Z&defd!d"Z'G d#d$ d$e(Z)d%ee de%fd&d'Z*dS )(a  
Logging utilities for internal use.
Usage:
    import ddtrace.internal.logger as logger
    ddlog = logger.get_logger(__name__)

    # Otherwise default is set to 1 minute or DD_TRACE_LOGGING_RATE
    logger.set_tag_rate_limit("waf::init", logger.HOUR)

    # "product" is required, but other keys are optional as well as kwargs exc_info and stack_info
    # supported keys are
    # product: product or integration name. Required
    # more_info : more information to be logged after the main tag. Default is empty string
    # stack_limit: limit the stack trace to this depth for stack_info. Default is 0 (0 is no limit)
    # exec_limit: limit the stack trace to this depth for exec_info. Default is 1, only the top level (0 is no limit)

    info = # format the info string
    ddlog.debug('waf::init', extra={"product": "appsec", "stack_limit": 4, "more_info": info}, stack_info=True)
    # This will log the message only once per hour, counting the number of skipped messages, using "waf::init" as the
    # tag to keep track of the rate limit
    # Different log levels can be used, the rate limit is shared between all invocations and all levels for the same tag

    # example result
    DEBUG appsec::waf::init[some more info] 1 additional messages skipped
    (followed by the 4 first levels of the stack trace)

    Legacy support:
    if extra is not used or product is absent, the log will be treated as legacy and will be logged as is using
    filename and line number of the log call

    N)	dataclass)field)DefaultDict)Optional)Tuple)Union   <      c                   @   sb   e Zd ZU eed< dZee ed< ee	dZ
e	ed f ed< dedee fdd	Zed
d ZdS )LoggerPrefixprefixNlevel)default_factorychildrennamereturnc                 C   sV   | dd d}|d | }|r(|d }|jvr!|jS |j| }|s|jS )z
        Lookup the log level for a given logger name in the trie.

        The name is split by '.' and each part is used to traverse the trie.
        If a part is not found, it returns the level of the closest parent node.
        _.r   )replacelowersplitpopr   r   )selfr   partscurrentpart r   K/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/internal/logger.pylookup:   s   

zLoggerPrefix.lookupc                 C   s   | dd i d}dd t j D D ]6\}}|dd }| d}|j}|rG|d }|vr@| ||s:tt|d nd d	||< || j}|s'q|S )
Nddtrace)r   r   r   c                 s   s0    | ]\}}| d r|dr||fV  qdS )_DD_
_LOG_LEVELN)
startswithendswith).0kvr   r   r   	<genexpr>O   s    
z*LoggerPrefix.build_trie.<locals>.<genexpr>   ir   r   )r   r   )	osenvironitemsr   r   r   r   getattrlogging)clstrielogger_namer   r   r   r   r   r   r   
build_trieK   s    
zLoggerPrefix.build_trie)__name__
__module____qualname__str__annotations__r   r   intr   dictr   r   classmethodr1   r   r   r   r   r   4   s   
 r   r   r   c                 C   s>   t | }|t | drt|  }dur|| |S )z
    Retrieve or create a ``Logger`` instance with consistent behavior for internal use.

    Configure all loggers with a rate limiter filter to prevent excessive logging.

    zddtrace.N)r-   	getLogger	addFilter
log_filterr"   LOG_LEVEL_TRIEr   setLevel)r   loggerr   r   r   r   
get_loggera   s   



r@   tagratec                 C   s   |t | < dS )z1
    Set the rate limit for a specific tag.

    N)_RATE_LIMITS)rA   rB   r   r   r   set_tag_rate_limitx   s   rD   c                   @   s>   e Zd ZdedefddZdd Zdejded	e	fd
dZ
dS )LoggingBucketbucketskippedc                 C   s   || _ || _d S )NrF   rG   )r   rF   rG   r   r   r   __init__   s   
zLoggingBucket.__init__c                 C   s   d| j  d| j dS )NzLoggingBucket(z, )rH   )r   r   r   r   __repr__   s   zLoggingBucket.__repr__recordrB   r   c                 C   s@   t  }|| j |kr|| _| j|_d| _dS |  jd7  _dS )zV
        Determine if the log line should be sampled based on the rate limit.
        r   Tr   F)time	monotonicrF   rG   )r   rL   rB   r   r   r   r   
is_sampled   s   zLoggingBucket.is_sampledN)r2   r3   r4   floatr7   rI   rK   r-   	LogRecordboolrO   r   r   r   r   rE      s    rE   z-infc                   C   s
   t tdS )Nr   )rE   _MINFr   r   r   r   <lambda>   s   
 rT   _bucketsDD_TRACE_LOGGING_RATE)defaultrL   c                 C   sd  t | j}t| jt}|r| t jkrd}nt	| dr"| j}n
| j| j
| j| jf}t| | |}|r| jdd}|rFd| d}nd}| jdd}|r| jd	d}| jd
d}	| jdd}
|	rr| jrrt| j|	| _| d| j | | g}| jr|| j | jr|tj| jd |
pdd d|| _d| _d| _|S | j | | _|S )z
    Function used to determine if a log record should be outputted or not (True = output, False = skip).

    This function will:
      - Rate limit log records based on the logger name, record level, filename, and line number
    TproductrG   r   z [z	 skipped] N	more_infostack_limit
exec_limitr   z::)limit
)r-   r:   r   rC   getmsg_rate_limitgetEffectiveLevelDEBUGhasattrlevelnopathnamelinenorU   rO   __dict__r   
stack_infoformat_stackappendexc_infoextend	tracebackformat_exceptionjoin)rL   r?   
rate_limitmust_be_propagatedkeyrG   skip_strrX   rZ   r[   r\   string_bufferr   r   r   r<      s>   

r<   c                 C   sJ   |  d}t||d d kr| S d|d| d  }|d  d| S )Nr^      r   r   )r   lenrp   )ri   r]   stack	stack_strr   r   r   rj      s
   
rj   c                   @   s   e Zd ZdZdZdZdS )LogInjectionStatefalsetrue
structuredN)r2   r3   r4   DISABLEDENABLED
STRUCTUREDr   r   r   r   r{      s    r{   
raw_configc                 C   s>   | r|    }|tjks|dv rdS |dvrtd| dS )N)r}   1T)r|   0zcInvalid log injection state '%s'. Expected 'true', 'false', or 'structured'. Defaulting to 'false'.F)r   stripr{   r   r-   warning)r   
normalizedr   r   r   get_log_injection_state   s   r   )+__doc__collectionsdataclassesr   r   r-   r)   rM   rn   typingr   r   r   r   SECONDMINUTEHOURDAYr   r1   r=   r5   Loggerr@   rC   r7   rD   rE   rP   rS   key_typedefaultdictrU   r6   getenvra   rQ   rR   r<   rj   objectr{   r   r   r   r   r   <module>   s>     )	5
