|
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, custom_sampling_context=None, **kwargs): |
| 102 | + # type: (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