U 췀g3@s>ddlmZmZddlmZddlmZmZddlmZddlm Z m Z ddl m Z ddlmZmZmZmZddlmZmZdd lmZmZdd lmZmZdd lmZmZdd lm Z dd l!m"Z"m#Z$ddl%m&Z&ddl'm(Z)erddlm*Z*m+Z+m,Z,ddl-m.Z/ddl0m1Z1m2Z2dZ3dZ4dZ5ddZ6Gddde Z7dS))datetimetimezone)time) TYPE_CHECKINGcast) get_value) SpanProcessor ReadableSpan)SpanAttributes)format_span_idformat_trace_idget_current_spanSpanKind)INVALID_SPAN_IDINVALID_TRACE_ID) get_clientstart_transaction) INSTRUMENTER SPANSTATUS)SENTRY_BAGGAGE_KEYSENTRY_TRACE_KEYadd_global_event_processor) TransactionSpan)Dsn) parse_url)AnyOptionalUnion)context)EventHintZotel z auto.otelcCst}|jdtjkr|St|dr4|ddkr4|St}|sB|S|}|jtks^|j t krb|S| t |j d}|s||S| di}| di||S)N instrumentertypeZ transactioncontextstrace)roptionsrOTELhasattrr get_span_contexttrace_idrspan_idrgetr setdefaultupdateZget_trace_context)event otel_span_mapclient otel_spanctx sentry_spanr&r7b/opt/hc_python/lib/python3.8/site-packages/sentry_sdk/integrations/opentelemetry/span_processor.py!link_trace_context_to_error_event(s" r9cszeZdZdZiZiZfddZddZddZdd d Z d d Z d dZ ddZ ddZ ddZddZddZZS)SentrySpanProcessorzZ Converts OTel spans into Sentry spans so they can be sent to the Sentry backend. cst|dst||_|jS)Ninstance)r*super__new__r;)cls __class__r7r8r=Ps zSentrySpanProcessor.__new__cstfdd}dS)Ncs t|jS)N)r9r2)r1hintselfr7r8global_event_processorYsz.global_event_processorr)rCrDr7rBr8__init__WszSentrySpanProcessor.__init__cCspttd}t|jD]N}|j|tkr>|j|q||tkr|j|D]}|j|dqVqdS)z? Prune spans that have been open for too long. <N) intrlist open_spanskeyssetpopSPAN_MAX_TIME_OPEN_MINUTESr2)rCZcurrent_time_minutesZspan_start_minutesr-r7r7r8_prune_old_spans^s z$SentrySpanProcessor._prune_old_spansNc CsPt}|jsdSzt|j}Wntk r4YdSX|jdtjkrJdS|jsXdS| |rfdS| ||}|d}|r|j |nd}d}|j dk rt|j dtj}d} |r|j|d|j|tjtd} n(t|j|d||d|d|tjtd} | |j |d<|j dk rDt|j dd } |j| t|d|dS) Nr$parent_span_ideAr-)r-namestart_timestampr$originr,baggage)rQr-rOr,rTrRr$rSrF)rdsnr Exceptionr(rr)r+is_valid_is_sentry_span_get_trace_datar2r. start_timer fromtimestamprutcZ start_childrQ SPAN_ORIGINrrGrIr/rKaddrN) rCr4parent_contextr3_ trace_datarOZsentry_parent_spanrRr6span_start_in_minutesr7r7r8on_startpsf       zSentrySpanProcessor.on_startcCs t}|jdtjkrdS|}|js,dSt|j}|j |d}|sLdS|j |_ | ||t |tr|j |_ |t|||||n |||d}|jdk rt|jdtj}|j|d|jdk rt|jdd}|j|t|| dS)Nr$rP) end_timestamprF)!rr(rr)r+rWr r-r2rLrQop_update_span_with_otel_status isinstancerZ set_contextOPEN_TELEMETRY_CONTEXT_get_otel_context"_update_transaction_with_otel_data_update_span_with_otel_dataZend_timerr[rr\finishrZrGrIr/rKdiscardrN)rCr4r3 span_contextr-r6rdrbr7r7r8on_endsB        zSentrySpanProcessor.on_endcCsZd}|jdk r|jtj}td|}d}t}|jrBt|jj}|rV|rV||krVdSdS)zs Break infinite loop: HTTP requests to Sentry are caught by OTel and send again to Sentry. N Optional[str]TF) attributesr.r HTTP_URLrrrUrnetloc)rCr4Z otel_span_urlZdsn_urlr3r7r7r8rXs   z#SentrySpanProcessor._is_sentry_spancCs4i}|jrt|j|d<|jjr0t|jj|d<|S)z Returns the OTel context for Sentry. See: https://develop.sentry.dev/sdk/performance/opentelemetry/#step-5-add-opentelemetry-context rqresource)rqdictrt)rCr4r5r7r7r8ris z%SentrySpanProcessor._get_otel_contextc Csi}|}t|j}||d<t|j}||d<|jrBt|jjnd}||d<tt|}td|}|rn|dnd|d<tt |} | |d<|S)z^ Extracts tracing information from one OTel span and its parent OTel context. r-r,NrOz!dict[str, Union[str, bool, None]]Zparent_sampledrT) r+r r-r r,parentrrrr) rCr4r_rarnr-r,rOZsentry_trace_datarTr7r7r8rYs      z#SentrySpanProcessor._get_trace_datacCs4|jjr dS|jjr$|tjdS|tjdS)z? Set the Sentry span status from the OTel span N)statusZis_unsetZis_okZ set_statusrOKINTERNAL_ERROR)rCr6r4r7r7r8rf$s  z1SentrySpanProcessor._update_span_with_otel_statuscCs|d|j|j}|j}|jdk r|jD]\}}|||q0|jtj}td|}|jtj }|rjd}|jt j kr|d7}n|jt j kr|d7}|}|jtj d} | r|d| 7}|jtjd} | r|d| 7}| s>| s>|jtjd} td| } | r>t| } d| j| j| j} |d| 7}|jtjd} td | } | r|| n.|rd }|jtjd}td|}|r|}||_||_dS) 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.kindNrphttp.server.clientz {}z {}://{}{} Optional[int]db)set_datakindrQrqitemsr.r HTTP_METHODrZ DB_SYSTEMrSERVERCLIENTZ NET_PEER_NAMEformatZ HTTP_TARGETrrurlparseschemerspathHTTP_STATUS_CODEset_http_statusZ DB_STATEMENTre description)rCr6r4rerkeyval http_methodZdb_queryZ peer_nametargeturl parsed_url status_codeZ statementr7r7r8rk2s`          z/SentrySpanProcessor._update_span_with_otel_datacCs~|jdkrdS|jtj}|rz|jtj}td|}|rF||d}|jtj kr`|d7}n|jtj krt|d7}||_ dS)Nr}rzr{r|) rqr.r rrrrrrrrre)rCr6r4rrrer7r7r8rjss      z6SentrySpanProcessor._update_transaction_with_otel_data)N)__name__ __module__ __qualname____doc__r2rIr=rErNrcrorXrirYrfrkrj __classcell__r7r7r?r8r:Es  C.Ar:N)8rrrtypingrrZopentelemetry.contextrZopentelemetry.sdk.tracerr ZOTelSpanZopentelemetry.semconv.tracer Zopentelemetry.tracer r r rZopentelemetry.trace.spanrrZ sentry_sdkrrZsentry_sdk.constsrrZ,sentry_sdk.integrations.opentelemetry.constsrrZsentry_sdk.scoperZsentry_sdk.tracingrrZ SentrySpanZsentry_sdk.utilsrZ urllib3.utilrrrrrZ opentelemetryr Z context_apiZsentry_sdk._typesr!r"rhrMr]r9r:r7r7r7r8s.