|
2 | 2 | from contextlib import contextmanager
|
3 | 3 |
|
4 | 4 | from opentelemetry.context import get_value, set_value, attach, detach, get_current
|
| 5 | +from opentelemetry.trace import SpanContext, NonRecordingSpan, TraceFlags, use_span |
5 | 6 |
|
6 | 7 | from sentry_sdk.scope import Scope, ScopeType
|
| 8 | +from sentry_sdk.tracing import POTelSpan |
7 | 9 | from sentry_sdk.integrations.opentelemetry.consts import (
|
8 | 10 | SENTRY_SCOPES_KEY,
|
9 | 11 | SENTRY_FORK_ISOLATION_SCOPE_KEY,
|
|
14 | 16 | if TYPE_CHECKING:
|
15 | 17 | from typing import Tuple, Optional, Generator, Dict, Any
|
16 | 18 |
|
| 19 | + from sentry_sdk._types import SamplingContext |
| 20 | + |
17 | 21 |
|
18 | 22 | class PotelScope(Scope):
|
19 | 23 | @classmethod
|
@@ -61,10 +65,43 @@ def _get_isolation_scope(cls):
|
61 | 65 | @contextmanager
|
62 | 66 | def continue_trace(self, environ_or_headers):
|
63 | 67 | # type: (Dict[str, Any]) -> Generator[None, None, None]
|
64 |
| - with new_scope() as scope: |
65 |
| - scope.generate_propagation_context(environ_or_headers) |
66 |
| - # TODO-neel-potel add remote span on context |
| 68 | + self.generate_propagation_context(environ_or_headers) |
| 69 | + |
| 70 | + span_context = self._incoming_otel_span_context() |
| 71 | + if span_context is None: |
67 | 72 | yield
|
| 73 | + else: |
| 74 | + with use_span(NonRecordingSpan(span_context)): |
| 75 | + yield |
| 76 | + |
| 77 | + def _incoming_otel_span_context(self): |
| 78 | + # type: () -> Optional[SpanContext] |
| 79 | + if self._propagation_context is None: |
| 80 | + return None |
| 81 | + # If sentry-trace extraction didn't have a parent_span_id, we don't have an upstream header |
| 82 | + if self._propagation_context.parent_span_id is None: |
| 83 | + return None |
| 84 | + |
| 85 | + trace_flags = TraceFlags( |
| 86 | + TraceFlags.SAMPLED |
| 87 | + if self._propagation_context.parent_sampled |
| 88 | + else TraceFlags.DEFAULT |
| 89 | + ) |
| 90 | + |
| 91 | + # TODO-neel-potel tracestate |
| 92 | + span_context = SpanContext( |
| 93 | + trace_id=int(self._propagation_context.trace_id, 16), # type: ignore |
| 94 | + span_id=int(self._propagation_context.parent_span_id, 16), # type: ignore |
| 95 | + is_remote=True, |
| 96 | + trace_flags=trace_flags, |
| 97 | + ) |
| 98 | + |
| 99 | + return span_context |
| 100 | + |
| 101 | + def start_span(self, span=None, custom_sampling_context=None, **kwargs): |
| 102 | + # type: (Optional[POTelSpan], Optional[SamplingContext], Any) -> POTelSpan |
| 103 | + # TODO-neel-potel ideally want to remove the span argument, discuss with ivana |
| 104 | + return POTelSpan(**kwargs, scope=self) |
68 | 105 |
|
69 | 106 |
|
70 | 107 | _INITIAL_CURRENT_SCOPE = PotelScope(ty=ScopeType.CURRENT)
|
|
0 commit comments