
    j                        d dl Z d dlZd dlmZmZmZmZ d dlmZm	Z	  G d d      Z
 e
       Zej                  Zej                  Zej                  Zej                  Zej                   Zej"                  Zej$                  Zej&                  Zej(                  Zej*                  Zde
fdZej.                  dej0                  d	ee	j2                     ded
   fd       Zy)    N)ListOptional	GeneratorTuple)spantracec                   b   e Zd ZdZddZdedefdZdeddfdZde	e
j                     fdZ	 dd	e	e   de	e
j                     fd
Zde
j                  ddfdZdefdZdefdZde	ej&                     fdZ	 dd	e	e   de	ej&                     fdZde	ej&                     ddfdZddZddZy)OpikContextStoragea  
    Manages span and trace context using Python's contextvars.

    ## IMPORTANT: Working with ContextVars

    This class uses ContextVars to maintain isolated stacks across different
    execution contexts (like threads or async tasks). To ensure proper isolation and safety,
    this implementation uses immutable tuples for stack storage.

    ### DO use immutable data structures and create-new-set pattern:

    For adding elements:
    ```python
    # Get current tuple and create a new one with added element
    stack = spans_stack_context.get()
    spans_stack_context.set(stack + (new_element,))
    ```

    For removing elements:
    ```python
    # Get current tuple and create a new one without the last element
    stack = spans_stack_context.get()
    spans_stack_context.set(stack[:-1])
    ```

    The methods in this class follow these patterns and provide a safe API
    for manipulating the context stacks.
    returnNc                     t        j                  dd       | _        t               }t        j                  d|      | _        y )Ncurrent_trace_data)defaultspans_data_stack)contextvars
ContextVar_current_trace_data_contexttuple_spans_data_stack_context)selfdefault_span_stacks     m/Users/manta/Documents/Projects/TheRoad-I1/backend/.venv/lib/python3.12/site-packages/opik/context_storage.py__init__zOpikContextStorage.__init__&   sC     ""#7F 	( 9> ""#5?QR 	&    span_idc                 \    t        fd| j                  j                         D              S )Nc              3   <   K   | ]  }|j                   k(    y wN)id).0r   r   s     r   	<genexpr>z2OpikContextStorage._has_span_id.<locals>.<genexpr>0   s     W2V$477g%2Vs   )anyr   get)r   r   s    `r   _has_span_idzOpikContextStorage._has_span_id/   s#    W$2P2P2T2T2VWWWr   c                     | j                  |      sy| j                  j                         }g }|D ]$  }|j                  |       |j                  |k(  s$ n | j                  j                  t        |             y)a\  
        If span with the given id exists in the stack, eliminates the spans from the stack
        until the span with the given id is at the top.

        Intended to be used in the modules that perform unsafe manipulations with the
        span data stack (when there is a risk of missing the pop operation, e.g. in callback-based integrations).

        When the id of the span that SHOULD be on top is known, we can trim
        the stack to remove hanged spans if there are any.

        Args:
            span_id: The id of the span to trim the stack to.
        Returns:
            None
        N)r#   r   r"   appendr   setr   )r   r   stacknew_stack_list	span_datas        r   $trim_span_data_stack_to_certain_spanz7OpikContextStorage.trim_span_data_stack_to_certain_span2   sp        )..224.0I!!),||w& 
 	&&**5+@Ar   c                 b    | j                         ry | j                  j                         }|d   S )N)span_data_stack_emptyr   r"   )r   r'   s     r   top_span_dataz OpikContextStorage.top_span_dataN   s/    %%'..224Ryr   	ensure_idc                    | j                         ry|=| j                  j                         }| j                  j                  |dd        |d   S | j	                         j
                  |k(  r| j                         S d}|S )a  
        Pops the span from the stack.
        Args:
            ensure_id: If provided, it will pop the span only if it has the given id.
                Intended to be used in the modules that perform unsafe manipulations with the
                span data stack (when there is a risk of missing the add or pop operation,
                e.g. in callback-based integrations), to make sure the correct span is popped.
        Returns:
            The span that was popped from the stack or None.
        Nr,   )r-   r   r"   r&   r.   r   pop_span_data)r   r/   r'   'STACK_IS_EMPTY_OR_THE_ID_DOES_NOT_MATCHs       r   r1   z OpikContextStorage.pop_span_dataT   s     %%'22668E**..uSbz:9""i/%%''26/66r   r   c                 v    | j                   j                         }| j                   j                  ||fz          y r   )r   r"   r&   )r   r   r'   s      r   add_span_dataz OpikContextStorage.add_span_datap   s0    ..224&&**5D7?;r   c                 N    t        | j                  j                               dk(  S )Nr   lenr   r"   r   s    r   r-   z(OpikContextStorage.span_data_stack_emptyt   s!    4115578A==r   c                 H    t        | j                  j                               S r   r6   r8   s    r   span_data_stack_sizez'OpikContextStorage.span_data_stack_sizew   s    41155788r   c                 :    | j                   j                         }|S r   )r   r"   )r   
trace_datas     r   get_trace_dataz!OpikContextStorage.get_trace_dataz   s    5599;
r   c                     | j                   j                         }|y||j                  |k7  ry| j                  d       |S )a  
        Pops the trace from the context.
        Args:
            ensure_id: If provided, it will pop the trace only if it has the given id.
                Intended to be used in the modules that perform unsafe manipulations with the
                trace data (when there is a risk of missing the set operation,
                e.g. in callback-based integrations), to make sure the correct trace is popped.
        Returns:
            The trace that was popped from the context or None.
        N)r   r"   r   set_trace_data)r   r/   r<   s      r   pop_trace_dataz!OpikContextStorage.pop_trace_data~   sI     5599;
 Z]]i%?D!r   r   c                 :    | j                   j                  |       y r   )r   r&   )r   r   s     r   r?   z!OpikContextStorage.set_trace_data   s    ((,,U3r   c                 J    | j                   j                  t                      y r   )r   r&   r   r8   s    r   clear_spanszOpikContextStorage.clear_spans   s    &&**573r   c                 Z    | j                   j                  d        | j                          y r   )r   r&   rC   r8   s    r   	clear_allzOpikContextStorage.clear_all   s"    ((,,T2r   )r   Nr   )__name__
__module____qualname____doc__r   strboolr#   r*   r   r   SpanDatar.   r1   r4   r-   intr:   r   	TraceDatar=   r@   r?   rC   rE    r   r   r
   r
      s   :SXC XD XBC BD B8x6  $(7C=7 
$--	 78<$-- <D <>t >9c 9 9 
 *.!#	%//	"04HU__$= 4$ 44r   r
   r   c                      t         S r   )_context_storagerO   r   r   get_current_context_instancerR      s    r   r)   r<   )NNNc              #      K   	 t               }|t        |       t        |        d t        |       t                y# t               t                w xY ww)z
    Temporarily adds span and trace data to the context.
    If trace_data is None, it has no effect on the current trace in the context.
    N)r   )r=   r?   r4   r1   )r)   r<   original_traces      r   temporary_contextrU      sI     ')!,i ~& 	~&s   A'A AAA)r   
contextlibtypingr   r   r   r   opik.api_objectsr   r   r
   rQ   r.   r1   r4   r-   r=   r@   r?   rE   r:   r*   rR   contextmanagerrL   rN   rU   rO   r   r   <module>rZ      s      3 3 (V Vr &'  .. .. ..(>> !00!00!00&&	'<< 99 %
&8  }}*25??*C  r   