8000 Fix circular imports for sphinx by sl0thentr0py · Pull Request #3986 · getsentry/sentry-python · GitHub
[go: up one dir, main page]

Skip to content

Fix circular imports for sphinx #3986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import sphinx.ext.autodoc # noqa: F401
import sphinx.ext.intersphinx # noqa: F401
import urllib3.exceptions # noqa: F401
import importlib_metadata # noqa: F401
import opentelemetry.sdk.metrics._internal # noqa: F401

typing.TYPE_CHECKING = True

Expand Down
5 changes: 3 additions & 2 deletions sentry_sdk/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from sentry_sdk.crons import monitor

# TODO-neel-potel make 2 scope strategies/impls and switch
from sentry_sdk.scope import Scope as BaseScope
from sentry_sdk.integrations.opentelemetry.scope import (
PotelScope as Scope,
new_scope,
Expand Down Expand Up @@ -123,7 +124,7 @@ def is_initialized():

@scopemethod
def get_global_scope():
# type: () -> Scope
# type: () -> BaseScope
return Scope.get_global_scope()


Expand Down Expand Up @@ -239,7 +240,7 @@ def flush(


def start_span(**kwargs):
# type: (type.Any) -> Span
# type: (Any) -> Span
"""
Start and return a span.

Expand Down
2 changes: 1 addition & 1 deletion sentry_sdk/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ def _prepare_event(

for key in "release", "environment", "server_name", "dist":
if event.get(key) is None and self.options[key] is not None:
event[key] = str(self.options[key]).strip() # type: ignore[literal-required]
event[key] = str(self.options[key]).strip()
if event.get("sdk") is None:
sdk_info = dict(SDK_INFO)
sdk_info["integrations"] = sorted(self.integrations.keys())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

if TYPE_CHECKING:
from typing import Optional
from sentry_sdk.integrations.opentelemetry.scope import PotelScope
import sentry_sdk.integrations.opentelemetry.scope as scope


class SentryContextVarsRuntimeContext(ContextVarsRuntimeContext):
Expand All @@ -29,16 +29,16 @@ def attach(self, context):

should_use_isolation_scope = context.pop(SENTRY_USE_ISOLATION_SCOPE_KEY, None)
should_use_isolation_scope = cast(
"Optional[PotelScope]", should_use_isolation_scope
"Optional[scope.PotelScope]", should_use_isolation_scope
)

should_use_current_scope = context.pop(SENTRY_USE_CURRENT_SCOPE_KEY, None)
should_use_current_scope = cast(
"Optional[PotelScope]", should_use_current_scope
"Optional[scope.PotelScope]", should_use_current_scope
)

if scopes:
scopes = cast("tuple[PotelScope, PotelScope]", scopes)
scopes = cast("tuple[scope.PotelScope, scope.PotelScope]", scopes)
(current_scope, isolation_scope) = scopes
else:
current_scope = sentry_sdk.get_current_scope()
Expand Down
4 changes: 2 additions & 2 deletions sentry_sdk/integrations/opentelemetry/propagator.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

if TYPE_CHECKING:
from typing import Optional, Set
from sentry_sdk.integrations.opentelemetry.scope import PotelScope
import sentry_sdk.integrations.opentelemetry.scope as scope


class SentryPropagator(TextMapPropagator):
Expand Down Expand Up @@ -94,7 +94,7 @@ def inject(self, carrier, context=None, setter=default_setter):

scopes = get_value(SENTRY_SCOPES_KEY, context)
if scopes:
scopes = cast("tuple[PotelScope, PotelScope]", scopes)
scopes = cast("tuple[scope.PotelScope, scope.PotelScope]", scopes)
(current_scope, _) = scopes

# TODO-neel-potel check trace_propagation_targets
Expand Down
34 changes: 23 additions & 11 deletions sentry_sdk/integrations/opentelemetry/scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from sentry_sdk.integrations.opentelemetry.utils import trace_state_from_baggage
from sentry_sdk.scope import Scope, ScopeType
from sentry_sdk.tracing import Span
from sentry_sdk.utils import logger
from sentry_sdk._types import TYPE_CHECKING

if TYPE_CHECKING:
Expand All @@ -41,23 +42,25 @@
class PotelScope(Scope):
@classmethod
def _get_scopes(cls):
# type: () -> Optional[Tuple[Scope, Scope]]
# type: () -> Optional[Tuple[PotelScope, PotelScope]]
"""
Returns the current scopes tuple on the otel context. Internal use only.
"""
return cast("Optional[Tuple[Scope, Scope]]", get_value(SENTRY_SCOPES_KEY))
return cast(
"Optional[Tuple[PotelScope, PotelScope]]", get_value(SENTRY_SCOPES_KEY)
)

@classmethod
def get_current_scope(cls):
# type: () -> Scope
# type: () -> PotelScope
"""
Returns the current scope.
"""
return cls._get_current_scope() or _INITIAL_CURRENT_SCOPE

@classmethod
def _get_current_scope(cls):
# type: () -> Optional[Scope]
# type: () -> Optional[PotelScope]
"""
Returns the current scope without creating a new one. Internal use only.
"""
Expand All @@ -66,15 +69,15 @@ def _get_current_scope(cls):

@classmethod
def get_isolation_scope(cls):
# type: () -> Scope
# type: () -> PotelScope
"""
Returns the isolation scope.
"""
return cls._get_isolation_scope() or _INITIAL_ISOLATION_SCOPE

@classmethod
def _get_isolation_scope(cls):
# type: () -> Optional[Scope]
# type: () -> Optional[PotelScope]
"""
Returns the isolation scope without creating a new one. Internal use only.
"""
Expand All @@ -84,6 +87,11 @@ def _get_isolation_scope(cls):
@contextmanager
def continue_trace(self, environ_or_headers):
# type: (Dict[str, Any]) -> Generator[None, None, None]
"""
Sets the propagation context from environment or headers to continue an incoming trace.
Any span started within this context manager will use the same trace_id, parent_span_id
and inherit the sampling decision from the incoming trace.
"""
self.generate_propagation_context(environ_or_headers)

span_context = self._incoming_otel_span_context()
Expand Down Expand Up @@ -118,8 +126,8 @@ def _incoming_otel_span_context(self):
trace_state = trace_state.add(TRACESTATE_SAMPLED_KEY, "deferred")

span_context = SpanContext(
trace_id=int(self._propagation_context.trace_id, 16), # type: ignore
span_id=int(self._propagation_context.parent_span_id, 16), # type: ignore
trace_id=int(self._propagation_context.trace_id, 16),
span_id=int(self._propagation_context.parent_span_id, 16),
is_remote=True,
trace_flags=trace_flags,
trace_state=trace_state,
Expand All @@ -134,18 +142,22 @@ def start_transaction(self, **kwargs):
This function is deprecated and will be removed in a future release.
Use :py:meth:`sentry_sdk.start_span` instead.
"""
logger.warning(
"The `start_transaction` method is deprecated, please use `sentry_sdk.start_span instead.`"
)
return self.start_span(**kwargs)

def start_span(self, **kwargs):
# type: (Any) -> Span
return Span(**kwargs, scope=self)
return Span(**kwargs)


_INITIAL_CURRENT_SCOPE = None
_INITIAL_ISOLATION_SCOPE = None
_INITIAL_CURRENT_SCOPE = PotelScope(ty=ScopeType.CURRENT)
_INITIAL_ISOLATION_SCOPE = PotelScope(ty=ScopeType.ISOLATION)


def setup_initial_scopes():
# type: () -> None
global _INITIAL_CURRENT_SCOPE, _INITIAL_ISOLATION_SCOPE
_INITIAL_CURRENT_SCOPE = PotelScope(ty=ScopeType.CURRENT)
_INITIAL_ISOLATION_SCOPE = PotelScope(ty=ScopeType.ISOLATION)
Expand Down
35 changes: 20 additions & 15 deletions sentry_sdk/integrations/opentelemetry/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def convert_from_otel_timestamp(time):


def convert_to_otel_timestamp(time):
# type: (Union[datetime.datetime, float]) -> int
# type: (Union[datetime, float]) -> int
"""Convert a datetime to an OTel timestamp (with nanosecond precision)."""
if isinstance(time, datetime):
return int(time.timestamp() * 1e9)
Expand All @@ -121,9 +121,12 @@ def extract_span_data(span):
if span.attributes is None:
return (op, description, status, http_status, origin)

op = span.attributes.get(SentrySpanAttribute.OP) or op
description = span.attributes.get(SentrySpanAttribute.DESCRIPTION) or description
origin = span.attributes.get(SentrySpanAttribute.ORIGIN)
attribute_op = cast("Optional[str]", span.attributes.get(SentrySpanAttribute.OP))
op = attribute_op or op
description = cast(
"str", span.attributes.get(SentrySpanAttribute.DESCRIPTION) or description
)
origin = cast("Optional[str]", span.attributes.get(SentrySpanAttribute.ORIGIN))

http_method = span.attributes.get(SpanAttributes.HTTP_METHOD)
http_method = cast("Optional[str]", http_method)
Expand All @@ -137,7 +140,7 @@ def extract_span_data(span):
rpc_service = span.attributes.get(SpanAttributes.RPC_SERVICE)
if rpc_service:
return (
span.attributes.get(SentrySpanAttribute.OP) or "rpc",
attribute_op or "rpc",
description,
status,
http_status,
Expand All @@ -147,7 +150,7 @@ def extract_span_data(span):
messaging_system = span.attributes.get(SpanAttributes.MESSAGING_SYSTEM)
if messaging_system:
return (
span.attributes.get(SentrySpanAttribute.OP) or "message",
attribute_op or "message",
description,
status,
http_status,
Expand All @@ -165,7 +168,7 @@ def span_data_for_http_method(span):
# type: (ReadableSpan) -> OtelExtractedSpanData
span_attributes = span.attributes or {}

op = span_attributes.get(SentrySpanAttribute.OP)
op = cast("Optional[str]", span_attributes.get(SentrySpanAttribute.OP))
if op is None:
op = "http"

Expand All @@ -183,6 +186,7 @@ def span_data_for_http_method(span):
description = span_attributes.get(
SentrySpanAttribute.DESCRIPTION
) or span_attributes.get(SentrySpanAttribute.NAME)
description = cast("Optional[str]", description)
if description is None:
description = f"{http_method}"

Expand All @@ -205,7 +209,7 @@ def span_data_for_http_method(span):

status, http_status = extract_span_status(span)

origin = span_attributes.get(SentrySpanAttribute.ORIGIN)
origin = cast("Optional[str]", span_attributes.get(SentrySpanAttribute.ORIGIN))

return (op, description, status, http_status, origin)

Expand All @@ -214,13 +218,13 @@ def span_data_for_db_query(span):
# type: (ReadableSpan) -> OtelExtractedSpanData
span_attributes = span.attributes or {}

op = span_attributes.get(SentrySpanAttribute.OP, OP.DB)
op = cast("str", span_attributes.get(SentrySpanAttribute.OP, OP.DB))

statement = span_attributes.get(SpanAttributes.DB_STATEMENT, None)
statement = cast("Optional[str]", statement)

description = statement or span.name
origin = span_attributes.get(SentrySpanAttribute.ORIGIN)
origin = cast("Optional[str]", span_attributes.get(SentrySpanAttribute.ORIGIN))

return (op, description, None, None, origin)

Expand Down Expand Up @@ -293,19 +297,20 @@ def extract_span_attributes(span, namespace):
"""
Extract Sentry-specific span attributes and make them look the way Sentry expects.
"""
extracted_attrs = {}
extracted_attrs = {} # type: dict[str, Any]

for attr, value in (span.attributes or {}).items():
if attr.startswith(namespace):
key = attr[len(namespace) + 1 :]

if namespace == SentrySpanAttribute.MEASUREMENT:
value = {
value = cast("tuple[str, str]", value)
extracted_attrs[key] = {
"value": float(value[0]),
"unit": value[1],
}

extracted_attrs[key] = value
else:
extracted_attrs[key] = value

return extracted_attrs

Expand Down Expand Up @@ -457,7 +462,7 @@ def set_sentry_meta(span, key, value):
# type: (Union[AbstractSpan, ReadableSpan], str, Any) -> None
sentry_meta = getattr(span, "_sentry_meta", {})
sentry_meta[key] = value
span._sentry_meta = sentry_meta
span._sentry_meta = sentry_meta # type: ignore[union-attr]


def get_profile_context(span):
Expand Down
Loading
Loading
0