Skip to content

Commit 28effd6

Browse files
committed
Skeletons for new components
1 parent 852cdc7 commit 28effd6

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from opentelemetry.context.context import Context # type: ignore
2+
from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext # type: ignore
3+
4+
5+
class SentryContextVarsRuntimeContext(ContextVarsRuntimeContext): # type: ignore
6+
def attach(self, context):
7+
# type: (Context) -> object
8+
# TODO-neel-potel do scope management
9+
return super().attach(context)
10+
11+
def detach(self, token):
12+
# type: (object) -> None
13+
# TODO-neel-potel not sure if we need anything here, see later
14+
super().detach(token)

Diff for: sentry_sdk/integrations/opentelemetry/integration.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
from importlib import import_module
99

1010
from sentry_sdk.integrations import DidNotEnable, Integration
11-
from sentry_sdk.integrations.opentelemetry.span_processor import SentrySpanProcessor
11+
from sentry_sdk.integrations.opentelemetry.potel_span_processor import (
12+
PotelSentrySpanProcessor,
13+
)
14+
from sentry_sdk.integrations.opentelemetry.contextvars_context import (
15+
SentryContextVarsRuntimeContext,
16+
)
1217
from sentry_sdk.integrations.opentelemetry.propagator import SentryPropagator
1318
from sentry_sdk.utils import logger, _get_installed_modules
1419
from sentry_sdk._types import TYPE_CHECKING
@@ -21,6 +26,7 @@
2126
)
2227
from opentelemetry.propagate import set_global_textmap # type: ignore
2328
from opentelemetry.sdk.trace import TracerProvider # type: ignore
29+
from opentelemetry import context
2430
except ImportError:
2531
raise DidNotEnable("opentelemetry not installed")
2632

@@ -165,9 +171,14 @@ def _import_by_path(path):
165171

166172
def _setup_sentry_tracing():
167173
# type: () -> None
174+
175+
# TODO-neel-potel make sure lifecycle is correct
176+
# TODO-neel-potel contribute upstream so this is not necessary
177+
context._RUNTIME_CONTEXT = SentryContextVarsRuntimeContext()
178+
168179
provider = TracerProvider()
169180

170-
provider.add_span_processor(SentrySpanProcessor())
181+
provider.add_span_processor(PotelSentrySpanProcessor())
171182

172183
trace.set_tracer_provider(provider)
173184

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from opentelemetry.trace import Span # type: ignore
2+
3+
4+
class PotelSentrySpanExporter:
5+
"""
6+
A Sentry-specific exporter that converts OpenTelemetry Spans to Sentry Spans & Transactions.
7+
"""
8+
9+
def __init__(self):
10+
# type: () -> None
11+
pass
12+
13+
def export(self, span):
14+
# type: (Span) -> None
15+
pass
16+
17+
def flush(self, timeout_millis):
18+
# type: (int) -> bool
19+
return True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from opentelemetry.sdk.trace import SpanProcessor # type: ignore
2+
from opentelemetry.context import Context # type: ignore
3+
from opentelemetry.trace import Span # type: ignore
4+
5+
from sentry_sdk.integrations.opentelemetry.potel_span_exporter import (
6+
PotelSentrySpanExporter,
7+
)
8+
from sentry_sdk._types import TYPE_CHECKING
9+
10+
if TYPE_CHECKING:
11+
from typing import Optional
12+
13+
14+
class PotelSentrySpanProcessor(SpanProcessor): # type: ignore
15+
"""
16+
Converts OTel spans into Sentry spans so they can be sent to the Sentry backend.
17+
"""
18+
19+
def __new__(cls):
20+
# type: () -> PotelSentrySpanProcessor
21+
if not hasattr(cls, "instance"):
22+
cls.instance = super().__new__(cls)
23+
24+
return cls.instance
25+
26+
def __init__(self):
27+
# type: () -> None
28+
self._exporter = PotelSentrySpanExporter()
29+
30+
def on_start(self, span, parent_context=None):
31+
# type: (Span, Optional[Context]) -> None
32+
pass
33+
34+
def on_end(self, span):
35+
# type: (Span) -> None
36+
self._exporter.export(span)
37+
38+
# TODO-neel-potel not sure we need a clear like JS
39+
def shutdown(self):
40+
# type: () -> None
41+
pass
42+
43+
# TODO-neel-potel change default? this is 30 sec
44+
# TODO-neel-potel call this in client.flush
45+
def force_flush(self, timeout_millis=30000):
46+
# type: (int) -> bool
47+
return self._exporter.flush(timeout_millis)

0 commit comments

Comments
 (0)