o
    i/9                  	   @   s  U d dl mZ d dlmZ d dlmZ 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mZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z# d dl!m$Z$ d dl%m&Z' d dl(m&Z& d dl)m*Z* d dl+m,Z, ee-Z.e#dddZ/dZ0dZ1dZ2dZ3dZ4d Z5d!Z6d"Z7d#Z8d$Z9d%Z:i Z;e<e=e*f e>d&< ee?e@ejAe
 f  ZBd'e@d(ejAe
 d)e=fd*d+ZCd,eBd)e=fd-d.ZDd/e=d)eEfd0d1ZFd'ejAe@ d(ejAe
 d)e?eBejAejG f fd2d3ZHd,eBd)ejIe?e=e
f ddf fd4d5ZJG d6d7 d7eZKeG d8d9 d9eZLd:e,d)eEfd;d<ZMd:e,d)e=fd=d>ZNG d?d@ d@ZOdS )A    )deque)	dataclass)Path)current_thread)	FrameType)TracebackTypeN)LiteralTemplateSegment)LogLineProbe)safe_getattr)Session)DEFAULT_CAPTURE_LIMITS)Snapshot)SignalUploader)UploaderProduct)core)
get_logger)is_user_code)BudgetRateLimiterWithJitter)RateLimitExceeded)config)	HourGlass)Span   F)
limit_rateraise_on_exceed _dd_exception_replay_snapshot_idzerror.debug_info_capturedz_dd.debug.error.trace_capturedz_dd.debug.error.snapshot_countz_dd.debug.error.exception_hashz$_dd.debug.error.exception_capture_idz_dd.debug.error.%d.snapshot_idz_dd.debug.error.%d.functionz_dd.debug.error.%d.filez_dd.debug.error.%d.lineg      @EXCEPTION_IDENT_LIMITERexctbreturnc                 C   s\   d}|}|dur$|j }|d> t|jd> |jB A }|dM }|j}|dustt| d> |B S )a  Compute the identity of an exception.

    We use the exception type and the traceback to generate a unique identifier
    that we can use to identify the exception. This can be used to rate limit
    the number of times we capture information of the same exception.
    r   Nr      l    @   )tb_frameidf_codef_lastitb_nexttype)r   r   h_tbframe r+   W/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/debugging/_exception/replay.pyexception_ident?   s   r-   chainc                 C   s0   d}| D ]\}}|d> t ||A }|dM }q|S )Nr   r   l	    )r-   )r.   r(   r   r   r+   r+   r,   exception_chain_identP   s
   
r/   	exc_identc              
   C   s0  z{t | }|d u r6ttd }t | < |  W tt dkr2tt dd d}|d d D ]}t |= q,dS dS | rYW tt dkrUtt dd d}|d d D ]}t |= qOdS dS |  W tt dkrxtt dd d}|d d D ]}t |= qrdS dS tt dkrtt dd d}|d d D ]}t |= qw w )	N)durationi   c                 S   s   t |  S )N)r   )kr+   r+   r,   <lambda>m   s    z!limit_exception.<locals>.<lambda>)key   FT)r   getr   EXCEPTION_IDENT_LIMITturnlensorted	trickling)r0   hgsorted_keysr2   r+   r+   r,   limit_exceptionX   sD   
r>   c                 C   s  t  }t }| durWt| |vrW|t|  || |f t| d }dur0|t|d} }nt| d }durKt| ddsH|t|d} }nd} nd} | durWt| |vsd}|r}|d \} }z| j}W ||fS  ty|   t	  | _}Y ||fS w ||fS )zUnwind the exception chain and assign it an ID.

    The chain goes from "cause to effect", meaning that every cause for an
    exception is put first.
    N	__cause____traceback____context____suppress_context__Fr   )
r   setr#   add
appendleftr
   
_dd_exc_idAttributeErroruuiduuid4)r   r   r.   seencausecontextexc_id_r+   r+   r,   unwind_exception_chainr   s0   rO   c                 c   s    d}| D ]?\}}t tjd}|du s|jdu rq|}|dur+|| |j}|dus|t|7 }|}|rD| }||fV  |d8 }|s5qdS )zGet the frames from the exception chain.

    For each exception in the chain we collect the maximum number of frames
    configured, starting from the point where the exception was thrown.
    r   )maxlenNr   )r   global_config_span_traceback_max_sizer"   appendr&   r9   pop)r.   frame_countrN   r   local_framesr)   frame_indexr*   r+   r+   r,   "get_tb_frames_from_exception_chain   s(   

rX   c                   @   s(   e Zd Zedejdedd fddZdS )SpanExceptionProberM   r*   r   c                 C   sh   t |}|jj}|j}|jj}d| d| d| d| d	}| |di |||t|gdg td dtd	d
S )Nzexception info for z, in z, line z (exception ID )r   Tg        inf)probe_idversiontagssource_filelinetemplatesegmentstake_snapshotcapture_expressionslimits	conditioncondition_error_raterate)strr$   co_filenamef_linenoco_namer   r   float)clsrM   r*   _exc_idfilenamer`   namemessager+   r+   r,   build   s(   zSpanExceptionProbe.buildN)__name__
__module____qualname__classmethodrH   UUIDr   rs   r+   r+   r+   r,   rY      s    rY   c                       sJ   e Zd ZU dZdZejej e	d< e
deeejf f fddZ  ZS )SpanExceptionSnapshotsnapshotNrM   r   c                    s    t  j}|dt| ji |S )NexceptionId)superdataupdateri   rM   )selfr}   	__class__r+   r,   r}      s   zSpanExceptionSnapshot.data)rt   ru   rv   __type__rM   tOptionalrH   rx   __annotations__propertydictri   Anyr}   __classcell__r+   r+   r   r,   ry      s
   
 &ry   spanc                 C   s   | j }|d u r	dS |t}|dkrdS |dkrdS |d u r6t r$dS t tu}|tt	|
  |S dt d| }t|)NFfalsetrueTzunexpected value for z: )_local_rootget_tagCAPTURE_TRACE_TAGr   
from_traceGLOBAL_RATE_LIMITERlimitr   _set_tag_strri   lower
ValueError)r   rootinfo_capturedresultmsgr+   r+   r,   can_capture   s    
r   c                 C   s0   | j }|d u r	dS |t }d u rdS t|S )Nr   )r   
get_metricSNAPSHOT_COUNT_TAGint)r   r   countr+   r+   r,   get_snapshot_count   s   r   c                   @   s   e Zd ZU eZdZejd  ed< 			dde	de
dejd	ed
ededefddZde	dee dedeje
 ddf
ddZedddZedddZdS )SpanExceptionHandlerN	_instancer   TFr   r   rM   seq_nronly_user_codecached_onlyr   c                 C   s  z~|j }|j}|rtt|jsW dS d }	|jtd  }
d u rU|r%W dS tt	
|||t ||d}	|	  | j  }d u rHtd W dS ||	 |	j |jt< }
|t| |
 |t| |j |t| |j |t| t|j |	d uW S  ty   td Y dS w )NFT)prober*   threadtrace_contextrM   z8No collector available to push exception replay snapshotz)Error capturing exception replay snapshot)r"   r$   r   r   rj   f_localsr6   SNAPSHOT_KEYry   rY   rs   r   do_line__uploader__get_collectorlogerrorpushrH   r   FRAME_SNAPSHOT_ID_TAGFRAME_FUNCTION_TAGrl   FRAME_FILE_TAGFRAME_LINE_TAGri   	tb_lineno	Exception	exception)r   r   r   rM   r   r   r   r*   coderz   snapshot_id	collectorr+   r+   r,   !_attach_tb_frame_snapshot_to_span  s>   	
	



z6SpanExceptionHandler._attach_tb_frame_snapshot_to_span	_exc_typer   	tracebackc                 C   s.  | tdkst|sd S |jp|}t||\}}|r|d u r!d S t|}t|r+d S t|}	t|D ]'\}
}|	t	j
k }| j||||
| d}|sM|rM n|	|7 }	|rZ|	t	j
krZ nq3|	sl|d url|	| j|||dd7 }	|	r|td |tt| |tt| |j}|d ur|t|	 d S d S d S )Nr   )r   F)r   )r   DEBUG_INFO_TAGr   r@   rO   r/   r>   r   rX   r   
max_framesr   r   EXCEPTION_HASH_TAGri   EXCEPTION_ID_TAGr   
set_metricr   )r   r   r   r   r   r   r.   rM   r0   frames_capturedr   r)   has_snapshot_budgethas_capturedr   r+   r+   r,   on_span_exceptionH  s@   

z&SpanExceptionHandler.on_span_exceptionc                 C   sR   | j d urtd d S td |  }|jtj tjd|j	t
d || _ d S )Nz$SpanExceptionHandler already enabledzEnabling SpanExceptionHandlerspan.exception)rq   )r   r   debugr   registerr   EXCEPTION_REPLAYr   onr   rt   rn   instancer+   r+   r,   enable  s   



zSpanExceptionHandler.enablec                 C   sN   | j d u rtd d S td | j }td|j |jtj	 d | _ d S )Nz%SpanExceptionHandler already disabledzDisabling SpanExceptionHandlerr   )
r   r   r   r   reset_listenersr   r   
unregisterr   r   r   r+   r+   r,   disable  s   



zSpanExceptionHandler.disable)r   TF)r   N)rt   ru   rv   r   r   r   r   r   r   r   r   rH   rx   r   boolr   r'   BaseExceptionr   rw   r   r   r+   r+   r+   r,   r     sH   
 
8
9r   )Pcollectionsr   dataclassesr   pathlibr   	threadingr   typesr   r   typingr   rH   ddtrace.debugging._probe.modelr   r	   ddtrace.debugging._safetyr
   ddtrace.debugging._sessionr   "ddtrace.debugging._signal.snapshotr   r   ddtrace.debugging._uploaderr   r   ddtrace.internalr   ddtrace.internal.loggerr   ddtrace.internal.packagesr   ddtrace.internal.rate_limiterr   RateLimiterr   !ddtrace.internal.settings._configr   rQ   *ddtrace.internal.settings.exception_replayddtrace.internal.utils.timer   ddtrace.tracer   rt   r   r   r   r   r   r   r   r   r   r   r   r   r7   r   r   r   r   tupler   r   ExceptionChainr-   r/   r   r>   rx   rO   	GeneratorrX   rY   ry   r   r   r   r+   r+   r+   r,   <module>   sx    
&'"