o
    BDi3                     @   s<  d dl m Z mZ d dlmZ d dlmZmZ d dlmZ d dlm	Z	m
Z d dlmZ d dlmZmZmZmZ d dlmZmZ d d	lmZmZ d d
lmZmZ d dlmZ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rd dlm*Z*m+Z+m,Z, d dl-m.Z/ d dl0m1Z1m2Z2 dZ3dZ4dZ5dd Z6G dd de	Z7dS )    )datetimetimezone)time)TYPE_CHECKINGcast)	get_value)SpanProcessorReadableSpan)SpanAttributes)format_span_idformat_trace_idget_current_spanSpanKind)INVALID_SPAN_IDINVALID_TRACE_ID)
get_clientstart_transaction)INSTRUMENTER
SPANSTATUS)SENTRY_BAGGAGE_KEYSENTRY_TRACE_KEYadd_global_event_processor)TransactionSpan)Dsn)	parse_url)AnyOptionalUnion)context)EventHintotel
   z	auto.otelc                 C   s   t  }|jd tjkr| S t| dr| d dkr| S t }|s!| S | }|jtks/|j	t
kr1| S |t|j	d }|s>| S | di }|di |  | S )Ninstrumentertypetransactioncontextstrace)r   optionsr   OTELhasattrr   get_span_contexttrace_idr   span_idr   getr   
setdefaultupdateget_trace_context)eventotel_span_mapclient	otel_spanctxsentry_spanr(    r:   m/var/www/Datamplify/venv/lib/python3.10/site-packages/sentry_sdk/integrations/opentelemetry/span_processor.py!link_trace_context_to_error_event(   s"   r<   c                       sz   e Zd ZdZi Zi Z fddZdd Zdd Zdd	d
Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Z  ZS )SentrySpanProcessorzZ
    Converts OTel spans into Sentry spans so they can be sent to the Sentry backend.
    c                    s   t | dst | | _| jS )Ninstance)r,   super__new__r>   )cls	__class__r:   r;   r@   P   s   
zSentrySpanProcessor.__new__c                    s   t  fdd}d S )Nc                    s   t |  jS N)r<   r5   )r4   hintselfr:   r;   global_event_processorY   s   z<SentrySpanProcessor.__init__.<locals>.global_event_processorr   )rG   rH   r:   rF   r;   __init__W   s   zSentrySpanProcessor.__init__c                 C   sp   t t d }t| j D ]'}| j| t kr| j| q|| tkr5| j|D ]	}| j|d q+qdS )z?
        Prune spans that have been open for too long.
        <   N)	intr   list
open_spanskeyssetpopSPAN_MAX_TIME_OPEN_MINUTESr5   )rG   current_time_minutesspan_start_minutesr/   r:   r:   r;   _prune_old_spans^   s   z$SentrySpanProcessor._prune_old_spansNc              
   C   sL  t  }|jsd S zt|j}W n
 ty   Y d S w |jd tjkr$d S | js+d S | 	|r2d S | 
||}|d }|rD| j|nd }d }|jd urWt|jd tj}d }	|rj|j|d |j|tjtd}	nt|j|d ||d |d |tjtd}	|	| j|d < |jd urt|jd d	 }
| j|
t |d  |   d S )
Nr%   parent_span_id    eAr/   )r/   namestart_timestampr%   originr.   baggage)rW   r/   rU   r.   rZ   rX   r%   rY   rJ   )r   dsnr   	Exceptionr*   r   r+   r-   is_valid_is_sentry_span_get_trace_datar5   r0   
start_timer   fromtimestampr   utcstart_childrW   SPAN_ORIGINr   rK   rM   r1   rO   addrT   )rG   r7   parent_contextr6   _
trace_datarU   sentry_parent_spanrX   r9   span_start_in_minutesr:   r:   r;   on_startp   sf   



zSentrySpanProcessor.on_startc                 C   s
  t  }|jd tjkrd S | }|jsd S t|j}| j	|d }|s&d S |j
|_| || t|trI|j
|_
|t| | | || n| || d }|jd ur`t|jd tj}|j|d |jd urt|jd d }| j|t | |    d S )Nr%   rV   )end_timestamprJ   )!r   r*   r   r+   r-   r]   r   r/   r5   rP   rW   op_update_span_with_otel_status
isinstancer   set_contextOPEN_TELEMETRY_CONTEXT_get_otel_context"_update_transaction_with_otel_data_update_span_with_otel_dataend_timer   ra   r   rb   finishr`   rK   rM   r1   rO   discardrT   )rG   r7   r6   span_contextr/   r9   rl   rj   r:   r:   r;   on_end   s>   




zSentrySpanProcessor.on_endc                 C   sZ   d}|j dur|j tj}td|}d}t }|jr!t|jj}|r+|r+||v r+dS dS )zs
        Break infinite loop:
        HTTP requests to Sentry are caught by OTel and send again to Sentry.
        NOptional[str]TF)	
attributesr0   r
   HTTP_URLr   r   r[   r   netloc)rG   r7   otel_span_urldsn_urlr6   r:   r:   r;   r^      s   

z#SentrySpanProcessor._is_sentry_spanc                 C   s4   i }|j rt|j |d< |jj rt|jj |d< |S )z
        Returns the OTel context for Sentry.
        See: https://develop.sentry.dev/sdk/performance/opentelemetry/#step-5-add-opentelemetry-context
        r{   resource)r{   dictr   )rG   r7   r8   r:   r:   r;   rr      s   z%SentrySpanProcessor._get_otel_contextc           
      C   s   i }|  }t|j}||d< t|j}||d< |jr!t|jjnd}||d< tt|}td|}|r7|d nd|d< tt	|}	|	|d< |S )z^
        Extracts tracing information from one OTel span and its parent OTel context.
        r/   r.   NrU   z!dict[str, Union[str, bool, None]]parent_sampledrZ   )
r-   r   r/   r   r.   parentr   r   r   r   )
rG   r7   rf   rh   rx   r/   r.   rU   sentry_trace_datarZ   r:   r:   r;   r_     s    




z#SentrySpanProcessor._get_trace_datac                 C   s4   |j jrdS |j jr|tj dS |tj dS )z?
        Set the Sentry span status from the OTel span
        N)statusis_unsetis_ok
set_statusr   OKINTERNAL_ERROR)rG   r9   r7   r:   r:   r;   rn   $  s   z1SentrySpanProcessor._update_span_with_otel_statusc                 C   s  | d|j |j}|j}|jdur|j D ]
\}}| || q|jtj}td|}|jtj	}|rd}|jt
jkrD|d7 }n
|jt
jkrN|d7 }|}|jtjd}	|	ra|d|	7 }|jtjd}
|
rr|d|
7 }|	s|
s|jtjd}td|}|rt|}d|j|j|j}|d|7 }|jtjd}td	|}|r|| n|rd
}|jtjd}td|}|r|}||_||_dS )z
        Convert OTel span data and update the Sentry span with it.
        This should eventually happen on the server when ingesting the spans.
        z	otel.kindNrz   http.server.clientz {}z	{}://{}{}Optional[int]db)set_datakindrW   r{   itemsr0   r
   HTTP_METHODr   	DB_SYSTEMr   SERVERCLIENTNET_PEER_NAMEformatHTTP_TARGETr|   urlparseschemer}   pathHTTP_STATUS_CODEset_http_statusDB_STATEMENTrm   description)rG   r9   r7   rm   r   keyvalhttp_methoddb_query	peer_nametargeturl
parsed_urlstatus_code	statementr:   r:   r;   rt   2  s\   







z/SentrySpanProcessor._update_span_with_otel_datac                 C   s   |j d u rd S |j tj}|r?|j tj}td|}|r#|| d}|jtj	kr0|d7 }n
|jtj
kr:|d7 }||_d S d S )Nr   r   r   r   )r{   r0   r
   r   r   r   r   r   r   r   r   rm   )rG   r9   r7   r   r   rm   r:   r:   r;   rs   s  s   




z6SentrySpanProcessor._update_transaction_with_otel_datarD   )__name__
__module____qualname____doc__r5   rM   r@   rI   rT   rk   ry   r^   rr   r_   rn   rt   rs   __classcell__r:   r:   rB   r;   r=   E   s    
C.Ar=   N)8r   r   r   typingr   r   opentelemetry.contextr   opentelemetry.sdk.tracer   r	   OTelSpanopentelemetry.semconv.tracer
   opentelemetry.tracer   r   r   r   opentelemetry.trace.spanr   r   
sentry_sdkr   r   sentry_sdk.constsr   r   ,sentry_sdk.integrations.opentelemetry.constsr   r   sentry_sdk.scoper   sentry_sdk.tracingr   r   
SentrySpansentry_sdk.utilsr   urllib3.utilr   r   r   r   r   opentelemetryr    context_apisentry_sdk._typesr!   r"   rq   rQ   rd   r<   r=   r:   r:   r:   r;   <module>   s0    