o
    iZ                     @  s2  d dl mZ d dlZd dlmZmZmZ d dlmZm	Z	 d dl
m
Z
mZmZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ erNd dlmZ eeB eB eB ee B ee B ee B ee B ZdZG dd deddZ edddG dd dZ!ee!gef Z"edddG dd dZ#ee#Z$dS )    )annotationsN)CallableIteratorSequence)	dataclassfield)datetime	timedeltatimezone)cache)indent)TYPE_CHECKINGAny)TypeAdapter)	TypedDict)ReadableSpan)SpanNodeSpanTree	SpanQueryc                   @  s   e Zd ZU dZded< ded< ded< ded< ded	< d
ed< d
ed< d ed< ded< ded< ded< ded< d ed< d ed< d ed< d ed< 	 ded< ded< d ed< d ed< d ed< ded< ded< d ed< d ed < d ed!< d"S )#r   zA serializable query for filtering SpanNodes based on various conditions.

    All fields are optional and combined with AND logic by default.
    strname_equalsname_containsname_matches_regexzdict[str, Any]has_attributesz	list[str]has_attribute_keysztimedelta | floatmin_durationmax_durationnot_zlist[SpanQuery]and_or_intmin_child_countmax_child_countsome_child_hasall_children_haveno_child_hasstop_recursing_whenmin_descendant_countmax_descendant_countsome_descendant_hasall_descendants_haveno_descendant_has	min_depth	max_depthsome_ancestor_hasall_ancestors_haveno_ancestor_hasN)__name__
__module____qualname____doc____annotations__ r6   r6   c/var/www/html/karishye-ai-python/venv/lib/python3.10/site-packages/pydantic_evals/otel/span_tree.pyr      s:   
 r   F)totalT)reprkw_onlyc                   @  s  e Zd ZU dZded< ded< ded< ded< d	ed
< d	ed< ded< ed[ddZed\ddZed\ddZed\ddZ	ed]ddZ
ed^ddZdd Zed_d"d#Zd`d&d'Zdad*d+Zdbd-d.Zdcd0d1Zddd3d4Z	5dedfd8d9Z	5dedgd:d;Z	5dedhd<d=Zdid>d?Z	5dedfd@dAZ	5dedgdBdCZ	5dedhdDdEZdidFdGZdjdIdJZdkdLdMZ	N	O	O	O	OdldmdUdVZd]dWdXZd]dYdZZ d5S )nr   z`A node in the span tree; provides references to parents/children for easy traversal and queries.r   namer    trace_idspan_idz
int | Noneparent_span_idr   start_timestampend_timestampzdict[str, AttributeValue]
attributesreturnr	   c                 C  s   | j | j S )zHReturn the span's duration as a timedelta, or None if start/end not set.)r@   r?   selfr6   r6   r7   duration]   s   zSpanNode.durationlist[SpanNode]c                 C     t | j S N)listchildren_by_idvaluesrC   r6   r6   r7   childrenb      zSpanNode.childrenc                 C     |  dd S )z1Return all descendants of this node in DFS order.c                 S     dS NTr6   _r6   r6   r7   <lambda>i       z&SpanNode.descendants.<locals>.<lambda>)find_descendantsrC   r6   r6   r7   descendantsf      zSpanNode.descendantsc                 C  rN   )z"Return all ancestors of this node.c                 S  rO   rP   r6   rQ   r6   r6   r7   rS   n   rT   z$SpanNode.ancestors.<locals>.<lambda>)find_ancestorsrC   r6   r6   r7   	ancestorsk   rW   zSpanNode.ancestorsc                 C  s   | j dd| jdS N032x:016x)r<   r=   rC   r6   r6   r7   node_keyp   s   zSpanNode.node_key
str | Nonec                 C  s$   | j d u rd S | jdd| j dS rZ   )r>   r<   rC   r6   r6   r7   parent_node_keyt   s   $zSpanNode.parent_node_keyc                 C  s   d | _ i | _d S rH   )parentrJ   rC   r6   r6   r7   __post_init__{   s   
zSpanNode.__post_init__spanr   c              
   C  s   | j d us	J d| jd usJ d| jd usJ dt| j| j j| j j| jr+| jjnd tj	| jd t
jdtj	| jd t
jdt| jpEi dS )NzSpan has no contextzSpan has no start timezSpan has no end timeg    eA)tz)r;   r<   r=   r>   r?   r@   rA   )context
start_timeend_timer   r;   r<   r=   ra   r   fromtimestampr
   utcdictrA   )rc   r6   r6   r7   from_readable_span   s   zSpanNode.from_readable_spanchildNonec                 C  sf   |j | j ksJ d|j dd| j d|j| jks(J d|jdd| jd|| j|j< | |_dS )z4Attach a child node to this node's list of children.ztraces don't match: r[   z != zparent span mismatch: r]   N)r<   r>   r=   rJ   r^   ra   )rD   rl   r6   r6   r7   	add_child   s   (
zSpanNode.add_child	predicateSpanQuery | SpanPredicatec                 C     t | |S )z?Return all immediate children that satisfy the given predicate.)rI   _filter_childrenrD   ro   r6   r6   r7   find_children   rM   zSpanNode.find_childrenSpanNode | Nonec                 C     t | |dS )z[Return the first immediate child that satisfies the given predicate, or None if none match.N)nextrr   rs   r6   r6   r7   first_child      zSpanNode.first_childboolc                 C     |  |duS )zIReturns True if there is at least one child that satisfies the predicate.N)rx   rs   r6   r6   r7   	any_child   rM   zSpanNode.any_childIterator[SpanNode]c                   s    fdd| j D S )Nc                 3  s    | ]
}|  r|V  qd S rH   matches.0rl   ro   r6   r7   	<genexpr>   s    z,SpanNode._filter_children.<locals>.<genexpr>)rL   rs   r6   r   r7   rr      s   zSpanNode._filter_childrenNr&    SpanQuery | SpanPredicate | Nonec                 C     t | ||S )zJReturn all descendant nodes that satisfy the given predicate in DFS order.)rI   _filter_descendantsrD   ro   r&   r6   r6   r7   rU         zSpanNode.find_descendantsc                 C     t | ||dS )zlDFS: Return the first descendant (in DFS order) that satisfies the given predicate, or `None` if none match.N)rw   r   r   r6   r6   r7   first_descendant      zSpanNode.first_descendantc                 C     |  ||duS )zPReturns `True` if there is at least one descendant that satisfies the predicate.N)r   r   r6   r6   r7   any_descendant   r   zSpanNode.any_descendantc                 c  sT    t | j}|r(| }||r|V  |d ur||rq||j |sd S d S rH   )rI   rL   popr   extend)rD   ro   r&   stacknoder6   r6   r7   r      s   

zSpanNode._filter_descendantsc                 C  r   )z6Return all ancestors that satisfy the given predicate.)rI   _filter_ancestorsr   r6   r6   r7   rX      r   zSpanNode.find_ancestorsc                 C  r   )zXReturn the closest ancestor that satisfies the given predicate, or `None` if none match.N)rw   r   r   r6   r6   r7   first_ancestor   r   zSpanNode.first_ancestorc                 C  r   )z5Returns True if any ancestor satisfies the predicate.N)r   r   r6   r6   r7   any_ancestor   r   zSpanNode.any_ancestorc                 c  sD    | j }|r ||r|V  |d ur||rd S |j }|sd S d S rH   )ra   r   )rD   ro   r&   r   r6   r6   r7   r      s   
zSpanNode._filter_ancestorsqueryc                 C  s   t |r|| S | |S )zACheck if the span node matches the query conditions or predicate.)callable_matches_query)rD   r   r6   r6   r7   r      s   
zSpanNode.matchesr   c                   sJ   d }rtdkrtdt	fdd|D S  d }r*	|r*dS  d }r@	fd	d
|D }t|s@dS  d }rN	j|krNdS  d }r\|	jvr\dS  d }rlt|	jsldS  d }	rt	fdd|		 D sdS  d }
rt	fdd|
D sdS  d }durt
|tst|d}	j|k rdS  d }durt
|tst|d}	j|krdS  d }rt	j|k rdS  d }rt	j|krdS  d rtfdd	jD sdS  d rtfdd	jD sdS  d r-tfdd	jD r-dS t	fddt	fd d!} d" }rQt |k rQdS  d# }rct |krcdS  d$ rztfd%d| D szdS  d& rtfd'd| D sdS  d( rtfd)d| D rdS t	fd*d+t	fd,d-} d. }rt |k rdS  d/ }rt |krdS  d0 
rt
fd1d| D sdS  d2  rt fd3d| D sdS  d4 r#tfd5d| D r#dS d6S )7z/Check if the span matches the query conditions.r      zGCannot combine 'or_' conditions with other conditions at the same levelc                 3  s    | ]}  |V  qd S rH   r   r   qrC   r6   r7   r      s    z*SpanNode._matches_query.<locals>.<genexpr>r   Fr   c                   s   g | ]}  |qS r6   r   r   rC   r6   r7   
<listcomp>       z+SpanNode._matches_query.<locals>.<listcomp>r   r   r   r   c                 3  s$    | ]\}} j ||kV  qd S rH   )rA   get)r   keyvaluerC   r6   r7   r     s    
r   c                 3  s    | ]}| j v V  qd S rH   )rA   )r   r   rC   r6   r7   r         

r   N)secondsr   r!   r"   r#   c                 3      | ]}|  V  qd S rH   r   r   )r#   r6   r7   r   '  r   r$   c                 3  r   rH   r   r   )r$   r6   r7   r   +  r   r%   c                 3  r   rH   r   r   )r%   r6   r7   r   /  r   c                         j S rH   )rV   r6   rC   r6   r7   rV   6     z,SpanNode._matches_query.<locals>.descendantsc                    $    d} | rdd | S   S )Nr&   c                 S  rO   rP   r6   rQ   r6   r6   r7   rS   >  rT   zESpanNode._matches_query.<locals>.pruned_descendants.<locals>.<lambda>)r   r   r&   )rV   r   rD   r6   r7   pruned_descendants:  s
   
z3SpanNode._matches_query.<locals>.pruned_descendantsr'   r(   r)   c                 3  r   rH   r   r   
descendant)r)   r6   r7   r   E  r   r*   c                 3  r   rH   r   r   )r*   r6   r7   r   I  r   r+   c                 3  r   rH   r   r   )r+   r6   r7   r   M  r   c                     r   rH   )rY   r6   rC   r6   r7   rY   T  r   z*SpanNode._matches_query.<locals>.ancestorsc                    r   )Nr&   c                 S  rO   rP   r6   rQ   r6   r6   r7   rS   [  rT   zCSpanNode._matches_query.<locals>.pruned_ancestors.<locals>.<lambda>)r   r   r   )rY   r   rD   r6   r7   pruned_ancestorsX  s   
z1SpanNode._matches_query.<locals>.pruned_ancestorsr,   r-   r.   c                 3  r   rH   r   r   ancestor)r.   r6   r7   r   a  r   r/   c                 3  r   rH   r   r   )r/   r6   r7   r   e  r   r0   c                 3  r   rH   r   r   )r0   r6   r7   r   i  r   T)r   len
ValueErroranyr   allr;   rematchitems
isinstancer	   rE   rL   r   )rD   r   r   r   r   resultsr   r   r   r   has_attributes_keysr   r   r!   r"   r   r'   r(   r   r,   r-   r6   )r/   r$   r*   rY   rV   r0   r%   r+   r   rD   r.   r#   r)   r7   r      s   








  


  


zSpanNode._matches_queryTFinclude_childreninclude_trace_idinclude_span_idinclude_start_timestampinclude_durationc           	      C  s   d| j g}|r|d| jdd |r!|d| jdd |r.|d| j  |r:|d| j d g }|rb| jrb|d	 | jD ]}|t|j	|||||d
d qI|d n| jrj|d |d d
d
|g|S )zReturn an XML-like string representation of the node.

        Optionally includes children, trace_id, span_id, start_timestamp, and duration.
        <SpanNode name=z
trace_id='r[   'z	span_id='r]   zstart_timestamp=z
duration='>r   r   r   r   r     z</SpanNode>zchildren=...z/>
 )r;   appendr<   r=   r?   	isoformatrE   rL   r   repr_xmljoin)	rD   r   r   r   r   r   first_line_partsextra_linesrl   r6   r6   r7   r   s  s<   




zSpanNode.repr_xmlc                 C  s6   | j rd| jd| jddS d| jd| jddS )Nr   z
 span_id='r]   z'>...</SpanNode>z' />)rL   r;   r=   rC   r6   r6   r7   __str__  s   zSpanNode.__str__c                 C     |   S rH   r   rC   r6   r6   r7   __repr__     zSpanNode.__repr__)rB   r	   )rB   rF   )rB   r   )rB   r_   )rc   r   rB   r   )rl   r   rB   rm   ro   rp   rB   rF   ro   rp   rB   ru   ro   rp   rB   rz   ro   rp   rB   r}   rH   )ro   rp   r&   r   rB   rF   )ro   rp   r&   r   rB   ru   )ro   rp   r&   r   rB   rz   )ro   rp   r&   r   rB   r}   )r   rp   rB   rz   )r   r   rB   rz   TFFFFr   rz   r   rz   r   rz   r   rz   r   rz   rB   r   )!r1   r2   r3   r4   r5   propertyrE   rL   rV   rY   r^   r`   rb   staticmethodrk   rn   rt   rx   r|   rr   rU   r   r   r   rX   r   r   r   r   r   r   r   r   r6   r6   r6   r7   r   Q   sl   
 








 
-r   c                   @  s   e Zd ZU dZeedZded< eedZ	ded< dd Z
d2ddZd3ddZdd Zd4ddZd5ddZd6ddZd7dd Zd8d!d"Z	#	$	$	$	$d9d:d+d,Zd-d. Zd/d0 Zd1S );r   zA container that builds a hierarchy of SpanNode objects from a list of finished spans.

    You can then search or iterate the tree to make your assertions (using DFS for traversal).
    )default_factoryrF   rootszdict[str, SpanNode]nodes_by_idc                 C  s   |    d S rH   )_rebuild_treerC   r6   r6   r7   rb     s   zSpanTree.__post_init__spansrB   rm   c                 C  s"   |D ]}|| j |j< q|   dS )z?Add a list of spans to the tree, rebuilding the tree structure.N)r   r^   r   )rD   r   rc   r6   r6   r7   	add_spans  s   zSpanTree.add_spansreadable_spanslist[ReadableSpan]c                 C  s   |  dd |D  d S )Nc                 S  s   g | ]}t |qS r6   )r   rk   )r   rc   r6   r6   r7   r     r   z/SpanTree.add_readable_spans.<locals>.<listcomp>)r   )rD   r   r6   r6   r7   add_readable_spans  s   zSpanTree.add_readable_spansc                 C  s   t | j }|jdd d dd |D | _| j D ]}|j}|d ur4| j|}|d ur4|| qg | _| j D ]}|j}|d u sK|| jvrQ| j| q=d S )Nc                 S  s   | j ptjS rH   )r?   r   min)r   r6   r6   r7   rS     s    z(SpanTree._rebuild_tree.<locals>.<lambda>)r   c                 S  s   i | ]}|j |qS r6   )r^   )r   r   r6   r6   r7   
<dictcomp>  s    z*SpanTree._rebuild_tree.<locals>.<dictcomp>)	rI   r   rK   sortr`   r   rn   r   r   )rD   nodesr   r`   parent_noder6   r6   r7   r     s"   
zSpanTree._rebuild_treero   rp   c                 C  rq   )zaFind all nodes in the entire tree that match the predicate, scanning from each root in DFS order.)rI   _filterrs   r6   r6   r7   find  rM   zSpanTree.findru   c                 C  rv   )zpFind the first node that matches a predicate, scanning from each root in DFS order. Returns `None` if not found.N)rw   r   rs   r6   r6   r7   first  ry   zSpanTree.firstrz   c                 C  r{   )z;Returns True if any node in the tree matches the predicate.N)r   rs   r6   r6   r7   r     rM   zSpanTree.anyr}   c                 c  s     | D ]
}| |r|V  qd S rH   r~   )rD   ro   r   r6   r6   r7   r     s   
zSpanTree._filterc                 C  rG   )z.Return an iterator over all nodes in the tree.)iterr   rK   rC   r6   r6   r7   __iter__  rM   zSpanTree.__iter__TFr   r   r   r   r   r   c                   s:   | j sdS dg fdd| j D d}d|S )zReturn an XML-like string representation of the tree, optionally including children, trace_id, span_id, duration, and timestamps.z<SpanTree />z
<SpanTree>c              
     s&   g | ]}t |j d dqS )r   r   )r   r   )r   rootr   r   r   r   r   r6   r7   r     s    z%SpanTree.repr_xml.<locals>.<listcomp>z</SpanTree>r   )r   r   )rD   r   r   r   r   r   
repr_partsr6   r   r7   r     s   	
zSpanTree.repr_xmlc                 C  s   dt | j dt | j dS )Nz<SpanTree num_roots=z total_spans=z />)r   r   r   rC   r6   r6   r7   r     s   zSpanTree.__str__c                 C  r   rH   r   rC   r6   r6   r7   r     r   zSpanTree.__repr__N)r   rF   rB   rm   )r   r   r   r   r   r   )rB   r}   r   r   )r1   r2   r3   r4   r   rI   r   r5   rj   r   rb   r   r   r   r   r   r   r   r   r   r   r   r6   r6   r6   r7   r     s*   
 






	r   )%
__future__r   r   collections.abcr   r   r   dataclassesr   r   r   r	   r
   	functoolsr   textwrapr   typingr   r   pydanticr   typing_extensionsr   opentelemetry.sdk.tracer   r   rz   r    floatAttributeValue__all__r   r   SpanPredicater   SPAN_TREE_ADAPTERr6   r6   r6   r7   <module>   s0    0
8  Z
n