o
    i                     @   s   d dl Z d dlmZ d dlmZ d dlmZ d dlmZ e jdk Z	e	r9d dl
mZ d dl
mZ G d	d
 d
eZnG dd
 d
eZdd Ze ZdS )    N)IOLoop)BaseContextProvider)DefaultContextProvider)Span)   r   )StackContextInconsistentError)_statec                       sp   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	 fddZ
dd Z fddZ fddZ  ZS )TracerStackContexta  
        A context manager that manages ``Context`` instances in a thread-local state.
        It must be used every time a Tornado's handler or coroutine is used within a
        tracing Context. It is meant to work like a traditional ``StackContext``,
        preserving the state across asynchronous calls.

        Every time a new manager is initialized, a new ``Context()`` is created for
        this execution flow. A context created in a ``TracerStackContext`` is not
        shared between different threads.

        This implementation follows some suggestions provided here:
        https://github.com/tornadoweb/tornado/issues/1063
        c                 C   s   t |  d | _d S N)r   __init___contextself r   b/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/contrib/internal/tornado/stack_context.pyr       s   

zTracerStackContext.__init__c                 C      dS zM
            Required to preserve the ``StackContext`` protocol.
            Nr   r   r   r   r   enter(      zTracerStackContext.enterc                 C   r   r   r   )r   typevalue	tracebackr   r   r   exit.   r   zTracerStackContext.exitc                 C   s*   t j| _| jd | f | f| _| jt _| S )Nr   )r   contextsold_contextsnew_contextsr   r   r   r   	__enter__4   s   TracerStackContext.__enter__c                 C   s*   t j}| jt _|| jurtdd | _d S )Nz]stack_context inconsistency (may be caused by yield within a "with TracerStackContext" block))r   r   r   r   r   )r   r   r   r   final_contextsr   r   r   __exit__:   s   

TracerStackContext.__exit__c                 C   s   t tjddduS )z5Helper to determine if we are currently in an IO loopinstanceN)getattrr   _currentr   r   r   r   _has_io_loopF   s   zTracerStackContext._has_io_loopc                    s"   |   stt|  S |  duS )z7Helper to determine if we have an active context or notN)r$   superr	   _has_active_context_get_state_active_contextr   	__class__r   r   r&   J   s   z&TracerStackContext._has_active_contextc                 C   sJ   t tjd D ]}t|| jr"|j}t|tr| |  S |  S qdS )zFHelper to get the currently active context from the TracerStackContextr   N)reversedr   r   
isinstancer)   r   r   _update_active)r   stackctxr   r   r   r'   R   s   
z,TracerStackContext._get_state_active_contextc                    s   |   stt|  S |  S )aa  
            Return the ``Context`` from the current execution flow. This method can be
            used inside a Tornado coroutine to retrieve and use the current tracing context.
            If used in a separated Thread, the `_state` thread-local storage is used to
            propagate the current Active context from the `MainThread`.
            )r$   r%   r	   activer'   r   r(   r   r   r/   ]   s   zTracerStackContext.activec                    sF   |   stt| | |S ttjd D ]}t|| jr ||_	q|S )a>  
            Set the active ``Context`` for this async execution. If a ``TracerStackContext``
            is not found, the context is discarded.
            If used in a separated Thread, the `_state` thread-local storage is used to
            propagate the current Active context from the `MainThread`.
            r   )
r$   r%   r	   activater*   r   r   r+   r)   r   )r   r.   	stack_ctxr(   r   r   r0   m   s   zTracerStackContext.activate)__name__
__module____qualname____doc__r   r   r   r   r   r$   r&   r'   r/   r0   __classcell__r   r   r(   r   r	      s    r	   c                   @   s   e Zd Zdd Zdd ZdS )r	   c                 C      d S r
   r   r   r   r   r   r         r   c                 G   r7   r
   r   )r   excr   r   r   r      r8   r    N)r2   r3   r4   r   r   r   r   r   r   r	      s    c                 O   s8   t   | |i |W  d   S 1 sw   Y  dS )z
    Run the given function within a traced StackContext. This function is used to
    trace Tornado web handlers, but can be used in your code to trace coroutines
    execution.
    N)r	   )funcargskwargsr   r   r   run_with_trace_context   s   $r=   )tornadotornado.ioloopr   ddtrace._trace.providerr   r   ddtrace.tracer   version_info_USE_STACK_CONTEXTtornado.stack_contextr   r   r	   r=   context_providerr   r   r   r   <module>   s    p

