o
    iU                     @   s  d dl Z d dlZd dlmZ d dlZd dlZd dl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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  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/m0Z0 ddl&m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 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@mAZA dd$lBmCZC dd%lDmEZE dd&lDmFZF dd'lGmHZH d(d)lImJZJ d(d*lImKZK d(d+lImLZL d(d,lImMZM e
r:d d-lNmOZO d d.lPmQZQ d(d/lDmRZR e9eSZTd0ZUd1ed2 d3eVd4dfd5d6ZWG d7d8 d8eXZYd9ZZd:d; Z[d<e\d4eVfd=d>Z]G d?d@ d@e j^dAZ_G dBdC dCe_Z`G dDdE dEe*jae_ZbG dFdG dGecZdG dHdI dIe j^dAZeG dJdK dKebeeZfG dLdM dMebZgG dNdO dOe*jae_eeZhd4eifdPdQZjd4eifdRdSZkdWdTeeedgdf  d4e_fdUdVZldS )X    N)defaultdict)TYPE_CHECKING)Any)Callable)Optional)TextIO)config)forksafe)
in_ray_job)get_hostname)get_runtime_id)ai_guard_config)fibonacci_backoff_with_jitter)__version__   )_KEEP_SPANS_RATE_KEY   )compat)periodic)service)
BufferFull)BufferItemTooLarge)get_connection)_HTTPLIB_NO_TRACE_REQUEST)get_dogstatsd_client)JSONEncoderV2)get_git_tags)
get_logger)has_aws_lambda_agent_extension)in_aws_lambda)in_azure_function)in_gcp_function)ServiceStatusError)SimpleMovingAverage)parse_tags_str)Response)
verify_url)	StopWatch   )WRITER_CLIENTS)AgentlessWriterClient)AgentWriterClientV4)WriterClientBase)Span)	DogStatsd)ConnectionType<   log_func).Nmsgreturnc                 O   sp   z| |g|R i | W dS  t y7   z|r|| n|}td| tjd W Y dS  t y6   Y Y dS w w )a  
    Safely log a message, handling closed I/O streams gracefully.

    During interpreter shutdown or when test frameworks (like pytest) close
    captured stdout/stderr streams, logging calls may fail with:
        ValueError: I/O operation on closed file

    This can happen when a background thread (e.g., the periodic writer thread)
    attempts to log after the main process has started shutting down but before
    the Python interpreter has begun finalization (Py_IsFinalizing()).

    This wrapper catches such errors and attempts to print to stderr as a
    fallback. If stderr is also closed, the message is silently dropped.

    Args:
        log_func: The logger method to call (e.g., log.debug, log.warning, log.error)
        msg: The log message format string
        *args: Arguments for the format string
        **kwargs: Keyword arguments passed to the logger (e.g., exc_info, extra)
    z%[ddtrace] I/O closed, could not log: )fileN)
ValueErrorprintsysstderr)r1   r2   argskwargsformatted_msg r<   R/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/internal/writer/writer.py_safelogD   s   r>   c                   @   s   e Zd ZdS )NoEncodableSpansErrorN)__name__
__module____qualname__r<   r<   r<   r=   r?   c   s    r?   
   c                    sN   t | dr
| jdu rtd| j}| j t|t  fdd}|S )z
    Wrap a bound method so that it is called via a weakref to its instance.
    If the instance has been garbage-collected, the hook is a no-op.
    __self__Nz,make_weak_method_hook expects a bound methodc                     s(    }|d u r	d S  |g| R i |S Nr<   )r9   r:   instfuncinstance_refr<   r=   hookz   s   z#make_weak_method_hook.<locals>.hook)hasattrrD   	TypeError__func__weakrefref	functoolswraps)bound_methodinstancerJ   r<   rG   r=   make_weak_method_hookn   s   
rT   nbytesc                 C   sp   d}g d}| dkr&|t |d k r&| d } |d7 }| dkr&|t |d k sd|  dd}d	||| f S )
zReturn a human-readable size.r   )BKBMBGBTB  r(   g     @@z%.2f0.z%s%s)lenrstrip)rU   isuffixesfr<   r<   r=   _human_size   s   rc   c                   @   sz   e Zd Zejddee dd fddZejddee ddfddZ	ejdd	ee
d
  ddfddZejdddZdS )TraceWriterNappsec_enabledr3   c                 C      d S rE   r<   selfre   r<   r<   r=   recreate      zTraceWriter.recreatetimeoutc                 C   rf   rE   r<   rh   rk   r<   r<   r=   stop   rj   zTraceWriter.stopspansr-   c                 C   rf   rE   r<   )rh   rn   r<   r<   r=   write   rj   zTraceWriter.writec                 C   rf   rE   r<   rh   r<   r<   r=   flush_queue   rj   zTraceWriter.flush_queuerE   r3   N)r@   rA   rB   abcabstractmethodr   boolri   floatrm   listro   rq   r<   r<   r<   r=   rd      s    rd   )	metaclassc                   @   sz   e Zd ZejfdeddfddZddee dd fddZ	dd	ee
 ddfd
dZddeed  ddfddZdddZdS )	LogWriteroutr3   Nc                 C   s   t  | _|| _d S rE   )r   encoderrz   )rh   rz   r<   r<   r=   __init__   s   
zLogWriter.__init__re   c                 C   s   | j | jd}|S )zCreate a new instance of :class:`LogWriter` using the same settings from this instance

        :rtype: :class:`LogWriter`
        :returns: A new :class:`LogWriter` instance
        )rz   )	__class__rz   )rh   re   writerr<   r<   r=   ri      s   zLogWriter.recreaterk   c                 C   rf   rE   r<   rl   r<   r<   r=   rm         zLogWriter.stoprn   r-   c                 C   s4   |sd S | j |g}| j|d  | j  d S )N
)r{   encode_tracesrz   ro   flush)rh   rn   encodedr<   r<   r=   ro      s
   zLogWriter.writec                 C   rf   rE   r<   rp   r<   r<   r=   rq      r   zLogWriter.flush_queuerE   rr   )r@   rA   rB   r7   stdoutr   r|   r   ru   ri   rv   rm   rw   ro   rq   r<   r<   r<   r=   ry      s    
	ry   c                       s  e Zd ZU dZeed< dZdZdZ										dKded	e	e
 d
ee dee dee dee ded dedee deeeef  dededdf fddZdLddZedd Zedd ZdLddZdMd!ed"ed#ee	 ddfd$d%ZdNd&d'Zd(d) ZdNd*d+Zd,edeeef d-e
d.edef
d/d0Zd"ed-e
deeef fd1d2Zd3ed"ed-e
defd4d5ZdLd6d7ZdLd-e
d8ee	d9  ddfd:d;Z dOd<efd=d>Z!dOd-e
d<eddfd?d@Z"	dOdAee dBed-e
d<eddf
dCdDZ#dEdF Z$	dLdee ddf fdGdHZ%dIdJ Z&  Z'S )P
HTTPWriterz,Writer to an arbitrary HTTP intake endpoint.
intake_urlr   PUTtracerNFTclientsprocessing_intervalbuffer_sizemax_payload_sizerk   	dogstatsdr.   	sync_modereuse_connectionsheadersreport_metricsuse_gzipr3   c                    s   |d u rt j}|d u rtj}tt| j|d || _|| _|| _	|| _
|
p&i | _|| _|| _|| _tt| _|| _tt| _|| _d | _t | _t| jd| j d| j  d dd d| j| _|	d u rkt j | _!d S |	| _!d S )Nintervalg-?gS?r   c                 S   s
   t | tS rE   )
isinstancer%   )resultr<   r<   r=   <lambda>   s   
 z%HTTPWriter.__init__.<locals>.<lambda>)attemptsinitial_waituntil)"r   _trace_writer_interval_secondsagent_configtrace_agent_timeout_secondssuperr   r|   r   _intake_accepts_gzip_buffer_size_max_payload_size_headers_timeout_clientsr   r   int_metrics_report_metricsr#   DEFAULT_SMA_WINDOW	_drop_sma
_sync_mode_conn	threadingRLock	_conn_lckr   RETRY_ATTEMPTSr   _send_payload_send_payload_with_backoff_trace_writer_connection_reuse_reuse_connections)rh   r   r   r   r   r   rk   r   r   r   r   r   r   r}   r<   r=   r|      s<   



zHTTPWriter.__init__c                 C   s    d | ||r|jS | jS Nz{}/{})format_intake_urlENDPOINT	_endpointrh   clientr<   r<   r=   _intake_endpoint   s    zHTTPWriter._intake_endpointc                 C      | j d jS Nr   r   r   rp   r<   r<   r=   r        zHTTPWriter._endpointc                 C   r   r   r   r{   rp   r<   r<   r=   _encoder  r   zHTTPWriter._encoderc                 C   s   |r
t |dr
|jS | jS )Nr   )rK   r   r   r   r<   r<   r=   r   
  s   zHTTPWriter._intake_urlr(   namecounttagsc                 C   >   | j sd S tjr| jr| jjd| j|f ||d d S d S d S Nzdatadog.%s.%sr   r   r   _health_metrics_enabledr   distributionSTATSD_NAMESPACErh   r   r   r   r<   r<   r=   _metrics_dist  
    zHTTPWriter._metrics_distc                 C   `   | j d }| j d }tdd | jD }t|| | d}| j|| d| j d< || j d< d S )Naccepted_tracessent_tracesc                 S      g | ]}t |jqS r<   r^   r{   .0r   r<   r<   r=   
<listcomp>      z-HTTPWriter._set_drop_rate.<locals>.<listcomp>r   r   sumr   maxr   setrh   acceptedsentr   droppedr<   r<   r=   _set_drop_rate     


zHTTPWriter._set_drop_ratec                 C   $   |rd| j   |d jt< d S d S Ng      ?r   r   getr   r   rh   tracer<   r<   r=   _set_keep_rate   s   zHTTPWriter._set_keep_ratec                 C   sR   | j  | jr| j  d | _W d    d S W d    d S 1 s"w   Y  d S rE   )r   r   closerp   r<   r<   r=   _reset_connection&  s   
"zHTTPWriter._reset_connectiondatar   no_tracec           
      C   sr  t  }|  | j | jd u r+ttjd| j| j t	| 
|| j| _t| jt| zzzmi }t|dr=|jr=||j || ttjd| j|j|tt| | j| j|j|| | j }| }|| jkrotj}	ntj}	t|	d|j|jtt||| | t|W W | js|   W  d    S  t y   |    w | js|   w w 1 sw   Y  d S )Nz4creating new intake connection to %s with timeout %dr   z@Sending request: Method=%s Endpoint=%s Headers=%s PayloadSize=%sz*Got response: %d %s sent %s in %.5fs to %s)!r'   startr   r   r>   logdebugr   r   r   r   setattrr   rK   r   updateHTTP_METHODr   rc   r^   requestgetresponseelapsedr   warningstatusreasonr   r%   from_http_responser   r   	Exception)
rh   r   r   r   r   swfinal_headersresptr1   r<   r<   r=   _put,  sr   





2
zHTTPWriter._putc                 C   s6   | j  }|d|jji t|dr||j  |S )NContent-Typer   )r   copyr   r{   content_typerK   rh   r   r   r   r<   r<   r=   _get_finalized_headersj  s
   

z!HTTPWriter._get_finalized_headerspayloadc                 C   s  |  ||}| d | j|||dd}|jdkr%| jdd|j gd n| dt| | jd	  |7  < |jd
vr|jdkrd}| ||j|jf}tj	rh|d7 }t
|trc|t| f7 }n||f7 }ttj|g|R dddii | dt| | d| |S )Nzhttp.requestsT)r     http.errorsztype:%sr   http.sent.bytesr       zFfailed to send traces to intake at %s: HTTP error status %s, reason %s, payload %sextrasend_to_telemetryFhttp.dropped.byteshttp.dropped.traces)r  r   r   r   r^   r   r   r   r   _trace_writer_log_err_payloadr   bytesbinasciihexlifydecoder>   r   error)rh   r  r   r   r   responser2   log_argsr<   r<   r=   r   q  s,   



zHTTPWriter._send_payloadc                 C   0   | j D ]	}| j||d q| jr|   d S d S N)rn   r   _write_with_clientr   rq   rh   rn   r   r<   r<   r=   ro     
   
zHTTPWriter.writern   r-   c                 C   s  |d u rd S | j du r#z| jtjjkr|   W n
 tjy"   Y nw | d | jd  d7  < | 	| z|j
| W n tyr } z(|jd }ttjd||j
j | jdddgd	 | jd
|dgd	 W Y d }~d S d }~w ty } z2|jd }ttjdt|j
|j
j|j
j|| jj | jdddgd	 | jd
|dgd	 W Y d }~d S d }~w ty   | jdddgd	 Y d S w | dd | dt| d S )NFwriter.accepted.tracesr   r(   r   Atrace (%db) larger than payload buffer item limit (%db), droppingbuffer.dropped.tracesreason:t_too_bigr   buffer.dropped.bytes[trace buffer (%s traces %db/%db) cannot fit trace of size %db, dropping (writer status: %s)reason:fullreason:incompatiblebuffer.accepted.tracesbuffer.accepted.spans)r   r   r   ServiceStatusRUNNINGr   r"   r   r   r   r{   putr   r9   r>   r   r   max_item_sizer   r^   sizemax_sizevaluer?   rh   r   rn   epayload_sizer<   r<   r=   r    sZ   



 
	 zHTTPWriter._write_with_client	raise_excc                 C   4   z| j D ]	}| j||d qW |   d S |   w Nr4  r   _flush_queue_with_clientr   rh   r4  r   r<   r<   r=   rq     
   
zHTTPWriter.flush_queuec              	   C      t |j}z|j  }sW d S W n ty+   ttjd|jdd | d| Y d S w |D ]}|\}}| j||||d q.d S Nz&failed to encode trace with encoder %rTexc_infoencoder.dropped.traces)r   r4  	r^   r{   encoder   r>   r   r  r   _flush_single_payloadrh   r   r4  n_tracesencoded_tracesr  encoded_datar<   r<   r=   r9    s   
z#HTTPWriter._flush_queue_with_clientr   rE  c                 C   s`  |d u rd S | j r@zt|}tj|dd}ttjd|t| d| jd< W n ty?   ttj	d|j
dd | d	| Y d S w z`z	| ||| W n4 ty~   | jd
dgd | dt| | d| |rj ttj	d|| || jdddid Y nw W | dt| | d| d S W | dt| | d| d S | dt| | d| w )N   )compresslevelz/Original size in bytes: %s, Compressed size: %sgzipzContent-Encodingz)failed to compress traces with encoder %rTr>  r@  r  ztype:errr   r  r  zCfailed to send, dropping %d traces to intake at %s after %d retriesr  F)r?  r  r	  zhttp.sent.traces)r   r^   rJ  compressr>   r   r   r   r   r  r{   r   r   r   r   )rh   r   rE  r   r4  original_sizer<   r<   r=   rC    sN   

z HTTPWriter._flush_single_payloadc                 C      | j dd d S NFr7  rq   rp   r<   r<   r=   r        zHTTPWriter.periodicc                    s   t t|   | j|d d S N)rk   )r   r   _stop_servicejoinrl   r   r<   r=   rR    s   zHTTPWriter._stop_servicec                 C   s"   z|    W |   d S |   w rE   )r   r   rp   r<   r<   r=   on_shutdown  s   
zHTTPWriter.on_shutdown)
NNNNNFNNTFrE   r(   Nrr   F)(r@   rA   rB   __doc__str__annotations__r   r   r   rw   r,   r   rv   r   ru   dictr|   r   propertyr   r   r   r   r   r   r   r  r%   r   r  r   ro   r  rq   r9  rC  r   rR  rT  __classcell__r<   r<   r   r=   r      s   
 	

3


 

&>
" 0
+r   c                   @   s&   e Zd Zdeeef ddfddZdS )AgentResponserate_by_servicer3   Nc                 C   s
   || _ d S rE   r^  )rh   r^  r<   r<   r=   r|     s   
zAgentResponse.__init__)r@   rA   rB   rZ  rX  rv   r|   r<   r<   r<   r=   r]    s    r]  c                   @   s\   e Zd ZU eed< eed< eed< ejdee ddfddZ	ejdd
eddfddZ
dS )AgentWriterInterfacer   _api_versionr   tokenr3   Nc                 C   rf   rE   r<   rh   rb  r<   r<   r=   set_test_session_token'  rj   z+AgentWriterInterface.set_test_session_tokenFr4  c                 C   rf   rE   r<   )rh   r4  r<   r<   r=   rq   +  rj   z AgentWriterInterface.flush_queuerV  )r@   rA   rB   rX  rY  ru   rs   rt   r   rd  rq   r<   r<   r<   r=   r`  "  s   
 r`  c                       s2  e Zd ZdZdZdZdZ											d*ded	ee	 d
ee
 dee
 dee	 ded dededee dee deeeef  deeegdf  ddf fddZd+dee defddZedd Zdd Zdef fdd Z fd!d"Zd#e
d$edeeef f fd%d&Zd'ee ddfd(d)Z  ZS ),AgentWritera  
    The Datadog Agent supports (at the time of writing this) receiving trace
    payloads up to 50MB. A trace payload is just a list of traces and the agent
    expects a trace to be complete. That is, all spans with the same trace_id
    should be in the same trace.
    r   r   r   NTFr   r   r   r   rk   r   r.   r   r   api_versionr   r   response_callbackr3   c                    s  |d u rt j}|d u rtj}|d ur|dkrtd|d ur&|dkr&tdtjdp1tjd}d}|sEt sEt	 sEt
jsEt
jsEtjrGd}|	pMt jpM|| _tjrZtd d| _|re| jdkretd	|pit j}|pnt j}| jtvrtd
| jdtt  tt d | _t| j ||}dtjtjtdd}|r|| |d|j j!i t"j#$d}|d ur|t%| || _&|| _'t(t)| j*||g|||||||
||d d S )Nr   #Writer buffer size must be positive!Max payload size must be positivewincygwinv0.5v0.4TSetting api version to v0.4; DD_TRACE_NATIVE_SPAN_EVENTS is not compatible with v0.5There is a known compatibility issue with v0.5 API and Windows, please see https://github.com/DataDog/dd-trace-py/issues/4829 for more details.=Unsupported api version: '%s'. The supported versions are: %r, pythonyes)Datadog-Meta-LangDatadog-Meta-Lang-VersionDatadog-Meta-Lang-InterpreterDatadog-Meta-Tracer-Versionz!Datadog-Client-Computed-Top-Levelr  #_DD_TRACE_WRITER_ADDITIONAL_HEADERSr   r   r   r   r   rk   r   r   r   r   r   )+r   r   r   r   r5   r7   platform
startswithr!   r    
asm_config_asm_enabled_iast_enabledr   _ai_guard_enabled
_trace_apira  trace_native_span_eventsr   r   RuntimeError_trace_writer_buffer_size_trace_writer_payload_sizer)   rS  sortedkeysr   PYTHON_VERSIONPYTHON_INTERPRETERr   r   r{   r  osenvironr   r$   _response_cbr   r   re  r|   )rh   r   r   r   r   rk   r   r   r   rf  r   r   rg  
is_windowsdefault_api_versionr   r   additional_header_strr   r<   r=   r|   <  s   






zAgentWriter.__init__re   c                 C   sb   z|    W n	 ty   Y nw |rdn| j}| j| j| j| j| j| j| j	| j
|| j| j| jdS )Nrm  )r   r   r   r   rk   r   r   rf  r   r   rg  )rm   r"   ra  r}   r   	_intervalr   r   r   r   r   r   r   r  rh   re   rf  r<   r<   r=   ri     s&   zAgentWriter.recreatec                 C   s   | j d dS )N)r   )r   rp   r<   r<   r=   _agent_endpoint  r   zAgentWriter._agent_endpointc                 C   sP   |j dkrt| j| jg| _ttjd|j |j d S ttj	d|j |j| j
 d S )Nv0.5/tracesF  Calling endpoint '%s' but received %s; downgrading API. Dropping trace payload due to the downgrade to an incompatible API version (from v0.5 to v0.4). To avoid this from happening in the future, either ensure that the Datadog agent has a v0.5/traces endpoint available, or explicitly set the trace API version to, e.g., v0.4.@unsupported endpoint '%s': received response %s from intake (%s))r   r+   r   r   r   r>   r   r   r   r  r   )rh   r  r   r<   r<   r=   
_downgrade  s   

zAgentWriter._downgradec                    sj   t t| |||}|jdv r| || |S |jdk r3| jr3| }|r3d|v r3| t|d d |S )Nr
  r  r^  r_  )r   re  r   r   r  r  get_jsonr]  )rh   r  r   r   r  raw_respr   r<   r=   r     s   


zAgentWriter._send_payloadc                    sJ   t t|   ztjrddlm} |  W d S W d S  tjy$   Y d S w )Nr   )enable_appsec_rc)	r   re  r   r}  _asm_rc_enabled#ddtrace.appsec._remoteconfigurationr  r   r"   )rh   r  r   r<   r=   r     s   zAgentWriter.startr   r   c                    s"   t t| ||}t||d< |S )NzX-Datadog-Trace-Count)r   re  r  rX  r  r   r<   r=   r    s   z"AgentWriter._get_finalized_headersrb  c                 C   s   |pd| j d< d S )N X-Datadog-Test-Session-Token)r   rc  r<   r<   r=   rd    s   z"AgentWriter.set_test_session_token)NNNNNTFNNNNrE   )r@   rA   rB   rW  r   r   r   rX  r   rv   r   ru   rZ  r   r]  r|   r   ri   r[  r  r  r%   r   r   r,   r  rd  r\  r<   r<   r   r=   re  0  sf    	
`
"re  c                       s   e Zd ZdZdZdZdZ								dded	ed
ee	 dee
 dee
 dee	 ded dededee ddf fddZddee dd fddZ  ZS )AgentlessTraceWriterzj
    HTTP writer for agentless JSON span intake. Used when _DD_APM_TRACING_AGENTLESS_ENABLED is true.
    POSTzpublic-trace-http-intake.logsi   NTFr   api_keyr   r   r   rk   r   r.   r   r   r   r3   c                    sl   t |ptj| j}|ptj}t||}|jj|dtj	tj
td}tt| j||g||||||	|
||d d S )Nrs  )r  
dd-api-keyru  rv  rw  rx  rz  )minr   r  MAX_BUFFER_SIZEr  r*   r{   r  r   r  r  r   r   r  r|   )rh   r   r  r   r   r   rk   r   r   r   r   r   r   r   r<   r=   r|     s.   



zAgentlessTraceWriter.__init__re   c                 C   sV   z|    W n	 ty   Y nw | j| j| jd | j| j| j| j| j	| j
| j| jd
S )Nr  )
r   r  r   r   r   rk   r   r   r   r   )rm   r"   r}   r   r   r  r   r   r   r   r   r   r   rg   r<   r<   r=   ri   '  s"   zAgentlessTraceWriter.recreate)NNNNNTFNrE   )r@   rA   rB   rW  r   INTAKE_HOSTr  rX  r   rv   r   ru   r|   ri   r\  r<   r<   r   r=   r    sJ    	
 &r  c                       s   e Zd ZdZdZ											dPdedee ded	ee	 d
ee	 ded dedee dedee
egdf  dee dee ddf fddZdd Zdd ZdejfddZdee ddfddZdQdee dd fd d!Zd"d# ZdQd$d%Zed&d' Zed(d) ZdRd+ed,e	d-ee ddfd.d/ZdSd0d1Zd2d3 Zd4ed,e	d5efd6d7ZdQd8eed9  ddfd:d;Z dQd5ed8eed9  ddfd<d=Z!dTd>efd?d@Z"dTd5ed>eddfdAdBZ#	dTdCee dDe	d5ed>eddf
dEdFZ$dGdH Z%	dQdIee ddf fdJdKZ& fdLdMZ'dNdO Z(  Z)S )UNativeWriterz@Writer using a native trace exporter to send traces to an agent.r   NFTr   r   compute_stats_enabledr   r   r   r.   r   rf  r   rg  test_session_tokenstats_opt_outr3   c              	      s  |d u rt j}|d ur|dkrtd|d ur|dkrtdtjdp*tjd}d}|s>t s>t s>tj	s>tj
s>tjr@d}|pFt jpF|| _tjrStd d| _|r^| jdkr^td	|pbt j}|pgt j}| jtvrtd
| jdtt  tt d | _t| j ||}tjd}|d u r|d urt|}d|v r|d }tt| j |d || _!|| _"|| _#|| _$|g| _%|| _&t't(| _)|	| _*t+t,| _-|| _.|| _/|
| _0|| _1t2| j3}|| _4t56| | 7 | _8d S )Nr   rh  ri  rj  rk  rl  rm  rn  ro  rp  rq  rr  ry  r  r   )9r   r   r5   r7   r{  r|  r!   r    r}  r~  r  r   r  r  ra  r   r  r   r   r  r  r  r)   rS  r  r  r  r  r   r$   r   r  r|   r   r   r   _test_session_tokenr   r   r   r   r   r   r#   r   r   r   _compute_stats_enabledr  _stats_opt_outrT   before_fork_hook
_fork_hookr	   register_before_fork_create_exporter	_exporter)rh   r   r   r  r   r   r   r   rf  r   rg  r  r  r  r  r   r  additional_headerr  r   r<   r=   r|   ?  s|   







zNativeWriter.__init__c                 C   s    | j tjjkr| j  dS dS )z
        This hook is used to shut down the native runtime before forking when the service is not running.
        When the PeriodicService is running, the native runtime is shut down by the PeriodicThread logic.
        N)r   r   r*  r+  r  stop_workerrp   r<   r<   r=   r    s   zNativeWriter.before_fork_hookc                 C   s(   t | dr| jrt| j d S d S d S )Nr  )rK   r  r	   unregister_before_forkrp   r<   r<   r=   __del__  s   zNativeWriter.__del__c                 C   s(  t  \}}}t | jt dt	j
t	jt| | j| j}tjr6|tj tjr?|tj tjrH|tj | jdurS|| j | jr[|  n| jrrt t!"dped}t#|d }|$| tj%rt&j'(drt#tj)d }|*|t+  tj,r|-  |. S )z
        Create a new TraceExporter with the current configuration.
        :return: A configured TraceExporter instance.
        rs  N_DD_TRACE_STATS_WRITER_INTERVALg      $@g    eAlinuxr[   )/r   nativeTraceExporterBuilderset_urlr   set_hostnamer   set_languageset_language_versionr   r  set_language_interpreterr  set_tracer_versionr   set_git_commit_shaset_client_computed_top_levelset_input_formatra  set_output_formatr   r   set_serviceenvset_envversionset_app_versionr  rd  r  set_client_computed_statsr  rv   r  getenvr   enable_stats_telemetry_enabledr7   r{  r|  _telemetry_heartbeat_intervalenable_telemetryr   r   enable_health_metricsbuild)rh   _
commit_shabuilderstats_intervalbucket_size_nsheartbeat_msr<   r<   r=   r    sF   


zNativeWriter._create_exporterrb  c                 C   s   || _ | j  |  | _dS )z
        Set the test session token and recreate the exporter with the new configuration.
        :param token: The test session token to use for authentication.
        N)r  r  r  r  rc  r<   r<   r=   rd    s   
z#NativeWriter.set_test_session_tokenre   c                 C   sf   z|    W n	 ty   Y nw |rdn| j}| j| j| j| j| j| j| j	| j
|| j| j| j| jdS )Nrm  )r   r   r  r   r   r   r   rf  r   rg  r  r  )rm   r"   ra  r}   r   r  r  r   r   r   r   r   r  r  r  r  r<   r<   r=   ri     s(   zNativeWriter.recreatec                 C   s\   |j dkr!t| j| jg| _d| _|  | _tt	j
d|j | d S tt	jd|j || j d S )Nr  rm  r  r  )r   r+   r   r   r   ra  r  r  r>   r   r   r  r   )rh   r   r   r<   r<   r=   r    s"   


zNativeWriter._downgradec                 C   s   d | j|r
|jS | jS r   )r   r   r   r   r   r<   r<   r=   r     s   zNativeWriter._intake_endpointc                 C   r   r   r   rp   r<   r<   r=   r     r   zNativeWriter._endpointc                 C   r   r   r   rp   r<   r<   r=   r     r   zNativeWriter._encoderr(   r   r   r   c                 C   r   r   r   r   r<   r<   r=   r   !  r   zNativeWriter._metrics_distc                 C   r   )Nr   r   c                 S   r   r<   r   r   r<   r<   r=   r   *  r   z/NativeWriter._set_drop_rate.<locals>.<listcomp>r   r   r   r<   r<   r=   r   '  r   zNativeWriter._set_drop_ratec                 C   r   r   r   r   r<   r<   r=   r   2  s   zNativeWriter._set_keep_rater  r   c           	   
   C   s  zRz| j |}W n> tjyG } z1ztt|dd jdddd }W n   ||dks4|dkr;| || n|W Y d }~nd }~ww W | jd  |7  < n
| jd  |7  < w | j	r{t
|d	}| }|r}d
|v r| 	t|d
 d d S d S d S d S )N,r   :r(   )maxsplitr  r  r   )bodyr^  r_  )r  sendr  RequestErrorr   rX  splitr  r   r  r%   r  r]  )	rh   r  r   r   response_bodyr2  coder  r  r<   r<   r=   r   7  s4   ((
zNativeWriter._send_payloadrn   r-   c                 C   r  r  r  r  r<   r<   r=   ro   R  r  zNativeWriter.writec                 C   s  |d u rd S | j du r)z| jtjjkr|   W n tjy(   ttj	d Y nw | 
d | jd  d7  < | | z|j| W n tyx } z(|jd }ttj	d||jj | j
ddd	gd
 | j
d|d	gd
 W Y d }~d S d }~w ty } z2|jd }ttj	dt|j|jj|jj|| jj | j
dddgd
 | j
d|dgd
 W Y d }~d S d }~w ty   | j
dddgd
 Y d S w | 
dd | 
dt| d S )NFzfailed to start writer servicer   r   r(   r   r!  r"  r#  r   r$  r%  r&  r'  r(  r)  )r   r   r   r*  r+  r   r"   r>   r   r   r   r   r   r{   r,  r   r9   r-  r   r^   r.  r/  r0  r?   r1  r<   r<   r=   r  X  sZ   



 
	 zNativeWriter._write_with_clientr4  c                 C   r5  r6  r8  r:  r<   r<   r=   rq     r;  zNativeWriter.flush_queuec              	   C   r<  r=  rA  rD  r<   r<   r=   r9    s   
z%NativeWriter._flush_queue_with_clientr   rE  c              
   C   s   |d u rd S z
|  ||| W d S  tyR } z6|r d}|| |t|f}tjr8|d7 }|t| f7 }t	t
j|g|R dddii W Y d }~d S d }~ww )Nz6failed to send, dropping %d traces to intake at %s: %sr  r  r  F)r   r   r   rX  r   r  r  r  r  r>   r   r  )rh   r   rE  r   r4  r2  r2   r  r<   r<   r=   rC    s$   ,z"NativeWriter._flush_single_payloadc                 C   rM  rN  rO  rp   r<   r<   r=   r     rP  zNativeWriter.periodicrk   c              	      sl   z#t t|   | j|d W | j  | jr"t| j d | _d S d S | j  | jr5t| j d | _w rQ  )	r   r  rR  rS  r  r  r  r	   r  rl   r   r<   r=   rR    s   


zNativeWriter._stop_servicec                    sV   t  j|i | dtjdd f fdd} jd usJ | jt j j_d S )Nworkerr3   c                    s.   t tj|   t tj|   j  d S rE   )r   r   PeriodicThread_before_forkrS  r  r  )r  )r}   rh   r<   r=   r    s   z1NativeWriter._start_service.<locals>._before_fork)r   _start_servicer   r  _worker__get__typer  )rh   r9   r:   r  r   rp   r=   r    s   zNativeWriter._start_servicec              	   C   s*   z|    W | jd d S | jd w )Nl    ^e )r   r  shutdownrp   r<   r<   r=   rT    s   
zNativeWriter.on_shutdown)NFNNNFNTNNFrE   rU  rr   rV  )*r@   rA   rB   rW  r   rX  r   rv   ru   r   r   r]  r|   r  r  r  TraceExporterr  rd  ri   r  r   r[  r   r   rw   r   r   r   r  r,   r   ro   r  rq   r9  rC  r   rR  r  rT  r\  r<   r<   r   r=   r  :  s    	
_.	


 
 0
r  c                   C   sN   t jdst jdst jdrdS t rt rdS t s"t r$dS t S )zReturns whether the LogWriter should be used in the environment by
    default.

    The LogWriter is required by default in AWS Lambdas when the Datadog Agent extension
    is not available in the Lambda.
    DD_AGENT_HOSTDATADOG_TRACE_AGENT_HOSTNAMEDD_TRACE_AGENT_URLF)r  r  r   r   r   r!   r    r<   r<   r<   r=   _use_log_writer  s   


r  c                   C   s   t  rt pt pt pt S )a  Returns, if an `AgentWriter` is to be used, whether it should be run
     in synchronous mode by default.

    There are only three cases in which this is desirable:

    - AWS Lambdas can have the Datadog agent installed via an extension.
      When it's available traces must be sent synchronously to ensure all
      are received before the Lambda terminates.
    - Google Cloud Functions and Azure Functions have a mini-agent spun up by the tracer.
      Similarly to AWS Lambdas, sync mode should be used to avoid data loss.
    - Ray Job run different processes that can be killed at any time. Traces must be sent
      synchronously to ensure all are received before an actor/a worker is killed
    )r   r   r!   r    r
   r<   r<   r<   r=   _use_sync_mode  s   r  rg  c              	   C   s   t  rt S tjr-tjr(dtjtj}t	| t|tjt
tjt tj dS td t	tj tjrIttjt
tjt tjtj | tjdS i }tjsQtjrUd|d< ttjt
tjt |tj | dS )Nzhttps://{}.{})r   r  r   r   r   zQAPM Agentless enabled but DD_API_KEY is not set. Agentless mode will be disabled.)r   r   r   r  r   rg  r  rt  zDatadog-Client-Computed-Stats)r   r   r   r   r   rg  )r  ry   r   _trace_agentless_enabled_dd_api_keyr   r  r  _dd_siter&   r   r   dogstatsd_urlr  r}  _apm_opt_outr   r   trace_agent_url_trace_writer_nativer  _trace_compute_statsre  )rg  r   r   r<   r<   r=   create_trace_writer  sH   


r  rE   )mrs   r  collectionsr   rP   rJ  r  r7   r   typingr   r   r   r   r   rN   ddtracer   ddtrace.internalr	   %ddtrace.internal.dist_computing.utilsr
   ddtrace.internal.hostnamer   ddtrace.internal.nativeinternalr  ddtrace.internal.runtimer    ddtrace.internal.settings._agentr   ddtrace.internal.settings.asmr   r}  ddtrace.internal.utils.retryr   ddtrace.versionr   	constantsr   r  r   r   r   	_encodingr   r   agentr   r   r   r   encodingr   gitmetadatar   loggerr   
serverlessr   r   r    r!   r"   smar#   utils.formatsr$   
utils.httpr%   r&   
utils.timer'   writer_clientr)   r*   r+   r,   ddtrace.tracer-   ddtrace.vendor.dogstatsdr.   r/   r@   r   LOG_ERR_INTERVALrX  r>   r   r?   r   rT   rv   rc   ABCMetard   ry   PeriodicServicer   objectr]  r`  re  r  r  ru   r  r  r  r<   r<   r<   r=   <module>   s      \ GD   $&