diff --git a/sentry_sdk/_init_implementation.py b/sentry_sdk/_init_implementation.py index 4ad110ab56..51bcc9029c 100644 --- a/sentry_sdk/_init_implementation.py +++ b/sentry_sdk/_init_implementation.py @@ -1,13 +1,12 @@ from typing import TYPE_CHECKING import sentry_sdk +from sentry_sdk.consts import ClientConstructor from sentry_sdk.integrations.opentelemetry.scope import setup_scope_context_management if TYPE_CHECKING: from typing import Any, Optional - import sentry_sdk.consts - def _check_python_deprecations(): # type: () -> None @@ -36,7 +35,7 @@ def _init(*args, **kwargs): # Use `ClientConstructor` to define the argument types of `init` and # `ContextManager[Any]` to tell static analyzers about the return type. - class init(sentry_sdk.consts.ClientConstructor): # noqa: N801 + class init(ClientConstructor): # noqa: N801 pass else: diff --git a/sentry_sdk/api.py b/sentry_sdk/api.py index 475bbf5ef5..0555244a7c 100644 --- a/sentry_sdk/api.py +++ b/sentry_sdk/api.py @@ -30,17 +30,7 @@ from typing import Union from typing import Generator - from sentry_sdk.client import BaseClient - from sentry_sdk._types import ( - Event, - Hint, - Breadcrumb, - BreadcrumbHint, - ExcInfo, - MeasurementUnit, - LogLevelStr, - ) - from sentry_sdk.tracing import Span + import sentry_sdk T = TypeVar("T") F = TypeVar("F", bound=Callable[..., Any]) @@ -102,7 +92,7 @@ def clientmethod(f): @scopemethod def get_client(): - # type: () -> BaseClient + # type: () -> sentry_sdk.client.BaseClient return Scope.get_client() @@ -150,8 +140,8 @@ def last_event_id(): @scopemethod def capture_event( - event, # type: Event - hint=None, # type: Optional[Hint] + event, # type: sentry_sdk._types.Event + hint=None, # type: Optional[sentry_sdk._types.Hint] scope=None, # type: Optional[Any] **scope_kwargs, # type: Any ): @@ -162,7 +152,7 @@ def capture_event( @scopemethod def capture_message( message, # type: str - level=None, # type: Optional[LogLevelStr] + level=None, # type: Optional[sentry_sdk._types.LogLevelStr] scope=None, # type: Optional[Any] **scope_kwargs, # type: Any ): @@ -174,7 +164,7 @@ def capture_message( @scopemethod def capture_exception( - error=None, # type: Optional[Union[BaseException, ExcInfo]] + error=None, # type: Optional[Union[BaseException, sentry_sdk._types.ExcInfo]] scope=None, # type: Optional[Any] **scope_kwargs, # type: Any ): @@ -184,8 +174,8 @@ def capture_exception( @scopemethod def add_breadcrumb( - crumb=None, # type: Optional[Breadcrumb] - hint=None, # type: Optional[BreadcrumbHint] + crumb=None, # type: Optional[sentry_sdk._types.Breadcrumb] + hint=None, # type: Optional[sentry_sdk._types.BreadcrumbHint] **kwargs, # type: Any ): # type: (...) -> None @@ -224,7 +214,7 @@ def set_user(value): @scopemethod def set_level(value): - # type: (LogLevelStr) -> None + # type: (sentry_sdk._types.LogLevelStr) -> None return get_isolation_scope().set_level(value) @@ -238,7 +228,7 @@ def flush( def start_span(**kwargs): - # type: (Any) -> Span + # type: (Any) -> sentry_sdk.tracing.Span """ Start and return a span. @@ -255,10 +245,10 @@ def start_span(**kwargs): def start_transaction( - transaction=None, # type: Optional[Span] + transaction=None, # type: Optional[sentry_sdk.tracing.Span] **kwargs, # type: Any ): - # type: (...) -> Span + # type: (...) -> sentry_sdk.tracing.Span """ .. deprecated:: 3.0.0 This function is deprecated and will be removed in a future release. @@ -298,14 +288,14 @@ def start_transaction( def set_measurement(name, value, unit=""): - # type: (str, float, MeasurementUnit) -> None + # type: (str, float, sentry_sdk._types.MeasurementUnit) -> None transaction = get_current_scope().root_span if transaction is not None: transaction.set_measurement(name, value, unit) def get_current_span(scope=None): - # type: (Optional[Scope]) -> Optional[Span] + # type: (Optional[Scope]) -> Optional[sentry_sdk.tracing.Span] """ Returns the currently active span if there is one running, otherwise `None` """ diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 2c164fba3a..5fbd162299 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -478,6 +478,46 @@ class OP: SOCKET_DNS = "socket.dns" +BAGGAGE_HEADER_NAME = "baggage" +SENTRY_TRACE_HEADER_NAME = "sentry-trace" + +DEFAULT_SPAN_ORIGIN = "manual" +DEFAULT_SPAN_NAME = "" + + +# Transaction source +# see https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations +class TransactionSource(str, Enum): + COMPONENT = "component" + CUSTOM = "custom" + ROUTE = "route" + TASK = "task" + URL = "url" + VIEW = "view" + + def __str__(self): + # type: () -> str + return self.value + + +# These are typically high cardinality and the server hates them +LOW_QUALITY_TRANSACTION_SOURCES = [ + TransactionSource.URL, +] + +SOURCE_FOR_STYLE = { + "endpoint": TransactionSource.COMPONENT, + "function_name": TransactionSource.COMPONENT, + "handler_name": TransactionSource.COMPONENT, + "method_and_path_pattern": TransactionSource.ROUTE, + "path": TransactionSource.URL, + "route_name": TransactionSource.COMPONENT, + "route_pattern": TransactionSource.ROUTE, + "uri_template": TransactionSource.ROUTE, + "url": TransactionSource.ROUTE, +} + + # This type exists to trick mypy and PyCharm into thinking `init` and `Client` # take these arguments (even though they take opaque **kwargs) class ClientConstructor: diff --git a/sentry_sdk/integrations/aiohttp.py b/sentry_sdk/integrations/aiohttp.py index 8115063c9c..bcdd964b8d 100644 --- a/sentry_sdk/integrations/aiohttp.py +++ b/sentry_sdk/integrations/aiohttp.py @@ -3,7 +3,14 @@ from functools import wraps import sentry_sdk -from sentry_sdk.consts import OP, SPANSTATUS, SPANDATA +from sentry_sdk.consts import ( + OP, + SPANSTATUS, + SPANDATA, + BAGGAGE_HEADER_NAME, + SOURCE_FOR_STYLE, + TransactionSource, +) from sentry_sdk.integrations import ( _DEFAULT_FAILED_REQUEST_STATUS_CODES, _check_minimum_version, @@ -17,11 +24,6 @@ _request_headers_to_span_attributes, request_body_within_bounds, ) -from sentry_sdk.tracing import ( - BAGGAGE_HEADER_NAME, - SOURCE_FOR_STYLE, - TransactionSource, -) from sentry_sdk.tracing_utils import should_propagate_trace from sentry_sdk.utils import ( capture_internal_exceptions, diff --git a/sentry_sdk/integrations/asgi.py b/sentry_sdk/integrations/asgi.py index 5911b2a84c..c65ce5bed3 100644 --- a/sentry_sdk/integrations/asgi.py +++ b/sentry_sdk/integrations/asgi.py @@ -10,7 +10,7 @@ from functools import partial import sentry_sdk -from sentry_sdk.consts import OP +from sentry_sdk.consts import OP, SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.integrations._asgi_common import ( _get_headers, @@ -23,10 +23,6 @@ _request_headers_to_span_attributes, ) from sentry_sdk.sessions import track_session -from sentry_sdk.tracing import ( - SOURCE_FOR_STYLE, - TransactionSource, -) from sentry_sdk.utils import ( ContextVar, capture_internal_exceptions, diff --git a/sentry_sdk/integrations/bottle.py b/sentry_sdk/integrations/bottle.py index 8a9fc41208..1fefcf0319 100644 --- a/sentry_sdk/integrations/bottle.py +++ b/sentry_sdk/integrations/bottle.py @@ -1,7 +1,7 @@ import functools import sentry_sdk -from sentry_sdk.tracing import SOURCE_FOR_STYLE +from sentry_sdk.consts import SOURCE_FOR_STYLE from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, diff --git a/sentry_sdk/integrations/celery/__init__.py b/sentry_sdk/integrations/celery/__init__.py index bbaf3aec77..95a09e6029 100644 --- a/sentry_sdk/integrations/celery/__init__.py +++ b/sentry_sdk/integrations/celery/__init__.py @@ -4,7 +4,7 @@ import sentry_sdk from sentry_sdk import isolation_scope -from sentry_sdk.consts import OP, SPANSTATUS, SPANDATA +from sentry_sdk.consts import OP, SPANSTATUS, SPANDATA, BAGGAGE_HEADER_NAME from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable from sentry_sdk.integrations.celery.beat import ( _patch_beat_apply_entry, @@ -13,7 +13,7 @@ ) from sentry_sdk.integrations.celery.utils import _now_seconds_since_epoch from sentry_sdk.integrations.logging import ignore_logger -from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, TransactionSource +from sentry_sdk.tracing import TransactionSource from sentry_sdk.tracing_utils import Baggage from sentry_sdk.utils import ( capture_internal_exceptions, diff --git a/sentry_sdk/integrations/django/__init__.py b/sentry_sdk/integrations/django/__init__.py index 0681e734ea..e62ba63f70 100644 --- a/sentry_sdk/integrations/django/__init__.py +++ b/sentry_sdk/integrations/django/__init__.py @@ -6,10 +6,9 @@ from importlib import import_module import sentry_sdk -from sentry_sdk.consts import OP, SPANDATA +from sentry_sdk.consts import OP, SPANDATA, SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.scope import add_global_event_processor, should_send_default_pii from sentry_sdk.serializer import add_global_repr_processor -from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.tracing_utils import add_query_source, record_sql_queries from sentry_sdk.utils import ( AnnotatedValue, diff --git a/sentry_sdk/integrations/falcon.py b/sentry_sdk/integrations/falcon.py index 0b5c9c4fe7..9038c01a3f 100644 --- a/sentry_sdk/integrations/falcon.py +++ b/sentry_sdk/integrations/falcon.py @@ -1,8 +1,8 @@ import sentry_sdk +from sentry_sdk.consts import SOURCE_FOR_STYLE from sentry_sdk.integrations import _check_minimum_version, Integration, DidNotEnable from sentry_sdk.integrations._wsgi_common import RequestExtractor from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware -from sentry_sdk.tracing import SOURCE_FOR_STYLE from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, diff --git a/sentry_sdk/integrations/fastapi.py b/sentry_sdk/integrations/fastapi.py index 4a0080c6fd..0e087e3975 100644 --- a/sentry_sdk/integrations/fastapi.py +++ b/sentry_sdk/integrations/fastapi.py @@ -3,9 +3,9 @@ from functools import wraps import sentry_sdk +from sentry_sdk.consts import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.integrations import DidNotEnable from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.utils import ( transaction_from_function, logger, diff --git a/sentry_sdk/integrations/flask.py b/sentry_sdk/integrations/flask.py index f45ec6db20..9223eacd24 100644 --- a/sentry_sdk/integrations/flask.py +++ b/sentry_sdk/integrations/flask.py @@ -1,4 +1,5 @@ import sentry_sdk +from sentry_sdk.consts import SOURCE_FOR_STYLE from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration from sentry_sdk.integrations._wsgi_common import ( DEFAULT_HTTP_METHODS_TO_CAPTURE, @@ -6,7 +7,6 @@ ) from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, diff --git a/sentry_sdk/integrations/httpx.py b/sentry_sdk/integrations/httpx.py index a7c391851c..988778acd0 100644 --- a/sentry_sdk/integrations/httpx.py +++ b/sentry_sdk/integrations/httpx.py @@ -1,7 +1,6 @@ import sentry_sdk -from sentry_sdk.consts import OP, SPANDATA +from sentry_sdk.consts import OP, SPANDATA, BAGGAGE_HEADER_NAME from sentry_sdk.integrations import Integration, DidNotEnable -from sentry_sdk.tracing import BAGGAGE_HEADER_NAME from sentry_sdk.tracing_utils import Baggage, should_propagate_trace from sentry_sdk.utils import ( SENSITIVE_DATA_SUBSTITUTE, diff --git a/sentry_sdk/integrations/huey.py b/sentry_sdk/integrations/huey.py index fcdbd4f9f9..720d38f8e2 100644 --- a/sentry_sdk/integrations/huey.py +++ b/sentry_sdk/integrations/huey.py @@ -3,14 +3,15 @@ import sentry_sdk from sentry_sdk.api import get_baggage, get_traceparent -from sentry_sdk.consts import OP, SPANSTATUS -from sentry_sdk.integrations import DidNotEnable, Integration -from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import ( +from sentry_sdk.consts import ( + OP, + SPANSTATUS, BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME, TransactionSource, ) +from sentry_sdk.integrations import DidNotEnable, Integration +from sentry_sdk.scope import should_send_default_pii from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, diff --git a/sentry_sdk/integrations/litestar.py b/sentry_sdk/integrations/litestar.py index 484fea46c8..66b7040f6d 100644 --- a/sentry_sdk/integrations/litestar.py +++ b/sentry_sdk/integrations/litestar.py @@ -1,6 +1,6 @@ from collections.abc import Set import sentry_sdk -from sentry_sdk.consts import OP +from sentry_sdk.consts import OP, TransactionSource, SOURCE_FOR_STYLE from sentry_sdk.integrations import ( _DEFAULT_FAILED_REQUEST_STATUS_CODES, DidNotEnable, @@ -9,7 +9,6 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.integrations.logging import ignore_logger from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import TransactionSource, SOURCE_FOR_STYLE from sentry_sdk.utils import ( ensure_integration_enabled, event_from_exception, diff --git a/sentry_sdk/integrations/opentelemetry/scope.py b/sentry_sdk/integrations/opentelemetry/scope.py index 491404529a..f12adc29f0 100644 --- a/sentry_sdk/integrations/opentelemetry/scope.py +++ b/sentry_sdk/integrations/opentelemetry/scope.py @@ -17,17 +17,17 @@ use_span, ) -from sentry_sdk.integrations.opentelemetry.consts import ( +from sentry_sdk.opentelemetry.consts import ( SENTRY_SCOPES_KEY, SENTRY_FORK_ISOLATION_SCOPE_KEY, SENTRY_USE_CURRENT_SCOPE_KEY, SENTRY_USE_ISOLATION_SCOPE_KEY, TRACESTATE_SAMPLED_KEY, ) -from sentry_sdk.integrations.opentelemetry.utils import trace_state_from_baggage from sentry_sdk.opentelemetry.contextvars_context import ( SentryContextVarsRuntimeContext, ) +from sentry_sdk.opentelemetry.utils import trace_state_from_baggage from sentry_sdk.scope import Scope, ScopeType from sentry_sdk.tracing import Span from sentry_sdk._types import TYPE_CHECKING diff --git a/sentry_sdk/integrations/pyramid.py b/sentry_sdk/integrations/pyramid.py index d1475ada65..a4d30e38a4 100644 --- a/sentry_sdk/integrations/pyramid.py +++ b/sentry_sdk/integrations/pyramid.py @@ -4,11 +4,11 @@ import weakref import sentry_sdk +from sentry_sdk.consts import SOURCE_FOR_STYLE from sentry_sdk.integrations import Integration, DidNotEnable from sentry_sdk.integrations._wsgi_common import RequestExtractor from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, diff --git a/sentry_sdk/integrations/quart.py b/sentry_sdk/integrations/quart.py index f7f8ce7902..68c1342216 100644 --- a/sentry_sdk/integrations/quart.py +++ b/sentry_sdk/integrations/quart.py @@ -3,11 +3,11 @@ from functools import wraps import sentry_sdk +from sentry_sdk.consts import SOURCE_FOR_STYLE from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.integrations._wsgi_common import _filter_headers from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE from sentry_sdk.utils import ( capture_internal_exceptions, ensure_integration_enabled, diff --git a/sentry_sdk/integrations/starlette.py b/sentry_sdk/integrations/starlette.py index bdb842f596..e6016a3624 100644 --- a/sentry_sdk/integrations/starlette.py +++ b/sentry_sdk/integrations/starlette.py @@ -5,7 +5,7 @@ from json import JSONDecodeError import sentry_sdk -from sentry_sdk.consts import OP +from sentry_sdk.consts import OP, SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.integrations import ( DidNotEnable, Integration, @@ -18,10 +18,6 @@ ) from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import ( - SOURCE_FOR_STYLE, - TransactionSource, -) from sentry_sdk.utils import ( AnnotatedValue, capture_internal_exceptions, diff --git a/sentry_sdk/integrations/starlite.py b/sentry_sdk/integrations/starlite.py index dae105447b..928c697373 100644 --- a/sentry_sdk/integrations/starlite.py +++ b/sentry_sdk/integrations/starlite.py @@ -1,9 +1,8 @@ import sentry_sdk -from sentry_sdk.consts import OP +from sentry_sdk.consts import OP, SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.integrations import DidNotEnable, Integration from sentry_sdk.integrations.asgi import SentryAsgiMiddleware from sentry_sdk.scope import should_send_default_pii -from sentry_sdk.tracing import SOURCE_FOR_STYLE, TransactionSource from sentry_sdk.utils import ( ensure_integration_enabled, event_from_exception, diff --git a/sentry_sdk/integrations/opentelemetry/consts.py b/sentry_sdk/opentelemetry/consts.py similarity index 91% rename from sentry_sdk/integrations/opentelemetry/consts.py rename to sentry_sdk/opentelemetry/consts.py index d4b2b47768..0e3cb54948 100644 --- a/sentry_sdk/integrations/opentelemetry/consts.py +++ b/sentry_sdk/opentelemetry/consts.py @@ -23,8 +23,6 @@ class SentrySpanAttribute: - # XXX not all of these need separate attributes, we might just use - # existing otel attrs for some DESCRIPTION = "sentry.description" OP = "sentry.op" ORIGIN = "sentry.origin" diff --git a/sentry_sdk/opentelemetry/contextvars_context.py b/sentry_sdk/opentelemetry/contextvars_context.py index 7e61a45bc5..66d59b4ae1 100644 --- a/sentry_sdk/opentelemetry/contextvars_context.py +++ b/sentry_sdk/opentelemetry/contextvars_context.py @@ -5,7 +5,7 @@ from opentelemetry.context.contextvars_context import ContextVarsRuntimeContext import sentry_sdk -from sentry_sdk.integrations.opentelemetry.consts import ( +from sentry_sdk.opentelemetry.consts import ( SENTRY_SCOPES_KEY, SENTRY_FORK_ISOLATION_SCOPE_KEY, SENTRY_USE_CURRENT_SCOPE_KEY, diff --git a/sentry_sdk/opentelemetry/propagator.py b/sentry_sdk/opentelemetry/propagator.py index fcc2009849..2a9ad70434 100644 --- a/sentry_sdk/opentelemetry/propagator.py +++ b/sentry_sdk/opentelemetry/propagator.py @@ -21,15 +21,15 @@ TraceFlags, ) -from sentry_sdk.integrations.opentelemetry.consts import ( +from sentry_sdk.consts import ( + BAGGAGE_HEADER_NAME, + SENTRY_TRACE_HEADER_NAME, +) +from sentry_sdk.opentelemetry.consts import ( SENTRY_BAGGAGE_KEY, SENTRY_TRACE_KEY, SENTRY_SCOPES_KEY, ) -from sentry_sdk.tracing import ( - BAGGAGE_HEADER_NAME, - SENTRY_TRACE_HEADER_NAME, -) from sentry_sdk.tracing_utils import Baggage, extract_sentrytrace_data from typing import TYPE_CHECKING diff --git a/sentry_sdk/opentelemetry/sampler.py b/sentry_sdk/opentelemetry/sampler.py index 83d647f1d8..2afe26d95e 100644 --- a/sentry_sdk/opentelemetry/sampler.py +++ b/sentry_sdk/opentelemetry/sampler.py @@ -6,17 +6,17 @@ from opentelemetry.trace.span import TraceState import sentry_sdk -from sentry_sdk.tracing_utils import ( - _generate_sample_rand, - has_tracing_enabled, -) -from sentry_sdk.utils import is_valid_sample_rate, logger -from sentry_sdk.integrations.opentelemetry.consts import ( +from sentry_sdk.opentelemetry.consts import ( TRACESTATE_SAMPLED_KEY, TRACESTATE_SAMPLE_RAND_KEY, TRACESTATE_SAMPLE_RATE_KEY, SentrySpanAttribute, ) +from sentry_sdk.tracing_utils import ( + _generate_sample_rand, + has_tracing_enabled, +) +from sentry_sdk.utils import is_valid_sample_rate, logger from typing import TYPE_CHECKING diff --git a/sentry_sdk/opentelemetry/span_processor.py b/sentry_sdk/opentelemetry/span_processor.py index ec936125c3..6da616ed87 100644 --- a/sentry_sdk/opentelemetry/span_processor.py +++ b/sentry_sdk/opentelemetry/span_processor.py @@ -12,17 +12,14 @@ from opentelemetry.sdk.trace import Span, ReadableSpan, SpanProcessor import sentry_sdk -from sentry_sdk.consts import SPANDATA -from sentry_sdk.tracing import DEFAULT_SPAN_ORIGIN +from sentry_sdk.consts import SPANDATA, DEFAULT_SPAN_ORIGIN from sentry_sdk.utils import get_current_thread_meta -from sentry_sdk.opentelemetry.sampler import create_sampling_context -from sentry_sdk.profiler.continuous_profiler import ( - try_autostart_continuous_profiler, - get_profiler_id, - try_profile_lifecycle_trace_start, +from sentry_sdk.opentelemetry.consts import ( + OTEL_SENTRY_CONTEXT, + SentrySpanAttribute, ) -from sentry_sdk.profiler.transaction_profiler import Profile -from sentry_sdk.integrations.opentelemetry.utils import ( +from sentry_sdk.opentelemetry.sampler import create_sampling_context +from sentry_sdk.opentelemetry.utils import ( is_sentry_span, convert_from_otel_timestamp, extract_span_attributes, @@ -33,10 +30,12 @@ get_sentry_meta, set_sentry_meta, ) -from sentry_sdk.integrations.opentelemetry.consts import ( - OTEL_SENTRY_CONTEXT, - SentrySpanAttribute, +from sentry_sdk.profiler.continuous_profiler import ( + try_autostart_continuous_profiler, + get_profiler_id, + try_profile_lifecycle_trace_start, ) +from sentry_sdk.profiler.transaction_profiler import Profile from sentry_sdk._types import TYPE_CHECKING if TYPE_CHECKING: diff --git a/sentry_sdk/integrations/opentelemetry/utils.py b/sentry_sdk/opentelemetry/utils.py similarity index 98% rename from sentry_sdk/integrations/opentelemetry/utils.py rename to sentry_sdk/opentelemetry/utils.py index 6e711c34a8..ade9858855 100644 --- a/sentry_sdk/integrations/opentelemetry/utils.py +++ b/sentry_sdk/opentelemetry/utils.py @@ -17,14 +17,15 @@ import sentry_sdk from sentry_sdk.utils import Dsn -from sentry_sdk.consts import SPANSTATUS, OP, SPANDATA -from sentry_sdk.tracing import ( - get_span_status_from_http_code, +from sentry_sdk.consts import ( + SPANSTATUS, + OP, + SPANDATA, DEFAULT_SPAN_ORIGIN, LOW_QUALITY_TRANSACTION_SOURCES, ) -from sentry_sdk.tracing_utils import Baggage -from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute +from sentry_sdk.opentelemetry.consts import SentrySpanAttribute +from sentry_sdk.tracing_utils import Baggage, get_span_status_from_http_code from sentry_sdk._types import TYPE_CHECKING diff --git a/sentry_sdk/scope.py b/sentry_sdk/scope.py index 487b45b583..1f3162605f 100644 --- a/sentry_sdk/scope.py +++ b/sentry_sdk/scope.py @@ -11,7 +11,12 @@ from sentry_sdk._types import AnnotatedValue from sentry_sdk.attachments import Attachment -from sentry_sdk.consts import DEFAULT_MAX_BREADCRUMBS, FALSE_VALUES +from sentry_sdk.consts import ( + DEFAULT_MAX_BREADCRUMBS, + FALSE_VALUES, + BAGGAGE_HEADER_NAME, + SENTRY_TRACE_HEADER_NAME, +) from sentry_sdk.feature_flags import FlagBuffer, DEFAULT_FLAG_CAPACITY from sentry_sdk.profiler.transaction_profiler import Profile from sentry_sdk.session import Session @@ -21,8 +26,6 @@ PropagationContext, ) from sentry_sdk.tracing import ( - BAGGAGE_HEADER_NAME, - SENTRY_TRACE_HEADER_NAME, NoOpSpan, Span, ) diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 37f56453bf..c56a7e729c 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -1,5 +1,4 @@ from datetime import datetime -from enum import Enum import json import warnings @@ -16,7 +15,29 @@ from opentelemetry.sdk.trace import ReadableSpan import sentry_sdk -from sentry_sdk.consts import SPANSTATUS, SPANDATA +from sentry_sdk.consts import ( + DEFAULT_SPAN_NAME, + DEFAULT_SPAN_ORIGIN, + BAGGAGE_HEADER_NAME, + SENTRY_TRACE_HEADER_NAME, + SPANSTATUS, + SPANDATA, + TransactionSource, +) +from sentry_sdk.opentelemetry.consts import ( + TRACESTATE_SAMPLE_RATE_KEY, + SentrySpanAttribute, +) +from sentry_sdk.opentelemetry.utils import ( + baggage_from_trace_state, + convert_from_otel_timestamp, + convert_to_otel_timestamp, + get_trace_context, + get_trace_state, + get_sentry_meta, + serialize_trace_state, +) +from sentry_sdk.tracing_utils import get_span_status_from_http_code from sentry_sdk.utils import ( _serialize_span_attribute, get_current_thread_meta, @@ -48,87 +69,10 @@ from sentry_sdk.tracing_utils import Baggage -BAGGAGE_HEADER_NAME = "baggage" -SENTRY_TRACE_HEADER_NAME = "sentry-trace" - - -# Transaction source -# see https://develop.sentry.dev/sdk/event-payloads/transaction/#transaction-annotations -class TransactionSource(str, Enum): - COMPONENT = "component" - CUSTOM = "custom" - ROUTE = "route" - TASK = "task" - URL = "url" - VIEW = "view" - - def __str__(self): - # type: () -> str - return self.value - - -# These are typically high cardinality and the server hates them -LOW_QUALITY_TRANSACTION_SOURCES = [ - TransactionSource.URL, -] - -SOURCE_FOR_STYLE = { - "endpoint": TransactionSource.COMPONENT, - "function_name": TransactionSource.COMPONENT, - "handler_name": TransactionSource.COMPONENT, - "method_and_path_pattern": TransactionSource.ROUTE, - "path": TransactionSource.URL, - "route_name": TransactionSource.COMPONENT, - "route_pattern": TransactionSource.ROUTE, - "uri_template": TransactionSource.ROUTE, - "url": TransactionSource.ROUTE, -} - -DEFAULT_SPAN_ORIGIN = "manual" -DEFAULT_SPAN_NAME = "" tracer = otel_trace.get_tracer(__name__) -def get_span_status_from_http_code(http_status_code): - # type: (int) -> str - """ - Returns the Sentry status corresponding to the given HTTP status code. - - See: https://develop.sentry.dev/sdk/event-payloads/contexts/#trace-context - """ - if http_status_code < 400: - return SPANSTATUS.OK - - elif 400 <= http_status_code < 500: - if http_status_code == 403: - return SPANSTATUS.PERMISSION_DENIED - elif http_status_code == 404: - return SPANSTATUS.NOT_FOUND - elif http_status_code == 429: - return SPANSTATUS.RESOURCE_EXHAUSTED - elif http_status_code == 413: - return SPANSTATUS.FAILED_PRECONDITION - elif http_status_code == 401: - return SPANSTATUS.UNAUTHENTICATED - elif http_status_code == 409: - return SPANSTATUS.ALREADY_EXISTS - else: - return SPANSTATUS.INVALID_ARGUMENT - - elif 500 <= http_status_code < 600: - if http_status_code == 504: - return SPANSTATUS.DEADLINE_EXCEEDED - elif http_status_code == 501: - return SPANSTATUS.UNIMPLEMENTED - elif http_status_code == 503: - return SPANSTATUS.UNAVAILABLE - else: - return SPANSTATUS.INTERNAL_ERROR - - return SPANSTATUS.UNKNOWN_ERROR - - class NoOpSpan: def __init__(self, **kwargs): # type: (Any) -> None @@ -260,12 +204,6 @@ def __init__( if skip_span: self._otel_span = INVALID_SPAN else: - from sentry_sdk.integrations.opentelemetry.consts import ( - SentrySpanAttribute, - ) - from sentry_sdk.integrations.opentelemetry.utils import ( - convert_to_otel_timestamp, - ) if start_timestamp is not None: # OTel timestamps have nanosecond precision @@ -360,38 +298,26 @@ def __exit__(self, ty, value, tb): @property def description(self): # type: () -> Optional[str] - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - return self.get_attribute(SentrySpanAttribute.DESCRIPTION) @description.setter def description(self, value): # type: (Optional[str]) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - self.set_attribute(SentrySpanAttribute.DESCRIPTION, value) @property def origin(self): # type: () -> Optional[str] - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - return self.get_attribute(SentrySpanAttribute.ORIGIN) @origin.setter def origin(self, value): # type: (Optional[str]) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - self.set_attribute(SentrySpanAttribute.ORIGIN, value) @property def root_span(self): # type: () -> Optional[Span] - from sentry_sdk.integrations.opentelemetry.utils import ( - get_sentry_meta, - ) - root_otel_span = cast( "Optional[OtelSpan]", get_sentry_meta(self._otel_span, "root_span") ) @@ -437,10 +363,6 @@ def sampled(self): @property def sample_rate(self): # type: () -> Optional[float] - from sentry_sdk.integrations.opentelemetry.consts import ( - TRACESTATE_SAMPLE_RATE_KEY, - ) - sample_rate = self._otel_span.get_span_context().trace_state.get( TRACESTATE_SAMPLE_RATE_KEY ) @@ -449,36 +371,26 @@ def sample_rate(self): @property def op(self): # type: () -> Optional[str] - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - return self.get_attribute(SentrySpanAttribute.OP) @op.setter def op(self, value): # type: (Optional[str]) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - self.set_attribute(SentrySpanAttribute.OP, value) @property def name(self): # type: () -> Optional[str] - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - return self.get_attribute(SentrySpanAttribute.NAME) @name.setter def name(self, value): # type: (Optional[str]) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - self.set_attribute(SentrySpanAttribute.NAME, value) @property def source(self): # type: () -> str - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - return ( self.get_attribute(SentrySpanAttribute.SOURCE) or TransactionSource.CUSTOM ) @@ -486,8 +398,6 @@ def source(self): @source.setter def source(self, value): # type: (str) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - self.set_attribute(SentrySpanAttribute.SOURCE, value) @property @@ -500,10 +410,6 @@ def start_timestamp(self): if start_time is None: return None - from sentry_sdk.integrations.opentelemetry.utils import ( - convert_from_otel_timestamp, - ) - return convert_from_otel_timestamp(start_time) @property @@ -516,10 +422,6 @@ def timestamp(self): if end_time is None: return None - from sentry_sdk.integrations.opentelemetry.utils import ( - convert_from_otel_timestamp, - ) - return convert_from_otel_timestamp(end_time) def start_child(self, **kwargs): @@ -529,11 +431,6 @@ def start_child(self, **kwargs): def iter_headers(self): # type: () -> Iterator[Tuple[str, str]] yield SENTRY_TRACE_HEADER_NAME, self.to_traceparent() - - from sentry_sdk.integrations.opentelemetry.utils import ( - serialize_trace_state, - ) - yield BAGGAGE_HEADER_NAME, serialize_trace_state(self.trace_state) def to_traceparent(self): @@ -554,10 +451,6 @@ def to_traceparent(self): @property def trace_state(self): # type: () -> TraceState - from sentry_sdk.integrations.opentelemetry.utils import ( - get_trace_state, - ) - return get_trace_state(self._otel_span) def to_baggage(self): @@ -566,16 +459,10 @@ def to_baggage(self): def get_baggage(self): # type: () -> Baggage - from sentry_sdk.integrations.opentelemetry.utils import ( - baggage_from_trace_state, - ) - return baggage_from_trace_state(self.trace_state) def set_tag(self, key, value): # type: (str, Any) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - self.set_attribute(f"{SentrySpanAttribute.TAG}.{key}", value) def set_data(self, key, value): @@ -642,8 +529,6 @@ def set_status(self, status): def set_measurement(self, name, value, unit=""): # type: (str, float, MeasurementUnit) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - # Stringify value here since OTel expects all seq items to be of one type self.set_attribute( f"{SentrySpanAttribute.MEASUREMENT}.{name}", (str(value), unit) @@ -674,10 +559,6 @@ def is_success(self): def finish(self, end_timestamp=None): # type: (Optional[Union[float, datetime]]) -> None if end_timestamp is not None: - from sentry_sdk.integrations.opentelemetry.utils import ( - convert_to_otel_timestamp, - ) - self._otel_span.end(convert_to_otel_timestamp(end_timestamp)) else: self._otel_span.end() @@ -696,16 +577,10 @@ def get_trace_context(self): if not isinstance(self._otel_span, ReadableSpan): return {} - from sentry_sdk.integrations.opentelemetry.utils import ( - get_trace_context, - ) - return get_trace_context(self._otel_span) def set_context(self, key, value): # type: (str, Any) -> None - from sentry_sdk.integrations.opentelemetry.consts import SentrySpanAttribute - # TODO-neel-potel we cannot add dicts here self.set_attribute(f"{SentrySpanAttribute.CONTEXT}.{key}", value) diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index 27320ac589..c1d60cf269 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -13,7 +13,13 @@ from urllib.parse import quote, unquote import sentry_sdk -from sentry_sdk.consts import OP, SPANDATA +from sentry_sdk.consts import ( + OP, + SPANDATA, + SPANSTATUS, + BAGGAGE_HEADER_NAME, + SENTRY_TRACE_HEADER_NAME, +) from sentry_sdk.utils import ( capture_internal_exceptions, filename_for_module, @@ -803,8 +809,40 @@ def _sample_rand_range(parent_sampled, sample_rate): return sample_rate, 1.0 -# Circular imports -from sentry_sdk.tracing import ( - BAGGAGE_HEADER_NAME, - SENTRY_TRACE_HEADER_NAME, -) +def get_span_status_from_http_code(http_status_code): + # type: (int) -> str + """ + Returns the Sentry status corresponding to the given HTTP status code. + + See: https://develop.sentry.dev/sdk/event-payloads/contexts/#trace-context + """ + if http_status_code < 400: + return SPANSTATUS.OK + + elif 400 <= http_status_code < 500: + if http_status_code == 403: + return SPANSTATUS.PERMISSION_DENIED + elif http_status_code == 404: + return SPANSTATUS.NOT_FOUND + elif http_status_code == 429: + return SPANSTATUS.RESOURCE_EXHAUSTED + elif http_status_code == 413: + return SPANSTATUS.FAILED_PRECONDITION + elif http_status_code == 401: + return SPANSTATUS.UNAUTHENTICATED + elif http_status_code == 409: + return SPANSTATUS.ALREADY_EXISTS + else: + return SPANSTATUS.INVALID_ARGUMENT + + elif 500 <= http_status_code < 600: + if http_status_code == 504: + return SPANSTATUS.DEADLINE_EXCEEDED + elif http_status_code == 501: + return SPANSTATUS.UNIMPLEMENTED + elif http_status_code == 503: + return SPANSTATUS.UNAVAILABLE + else: + return SPANSTATUS.INTERNAL_ERROR + + return SPANSTATUS.UNKNOWN_ERROR diff --git a/tests/integrations/opentelemetry/test_propagator.py b/tests/integrations/opentelemetry/test_propagator.py index f57679cc3e..49437fa896 100644 --- a/tests/integrations/opentelemetry/test_propagator.py +++ b/tests/integrations/opentelemetry/test_propagator.py @@ -6,7 +6,7 @@ from opentelemetry.propagators.textmap import DefaultSetter import sentry_sdk -from sentry_sdk.integrations.opentelemetry.consts import ( +from sentry_sdk.opentelemetry.consts import ( SENTRY_BAGGAGE_KEY, SENTRY_TRACE_KEY, ) diff --git a/tests/integrations/opentelemetry/test_utils.py b/tests/integrations/opentelemetry/test_utils.py index fde66bf590..b7bc055d3c 100644 --- a/tests/integrations/opentelemetry/test_utils.py +++ b/tests/integrations/opentelemetry/test_utils.py @@ -3,7 +3,7 @@ import pytest from opentelemetry.trace import SpanKind, Status, StatusCode -from sentry_sdk.integrations.opentelemetry.utils import ( +from sentry_sdk.opentelemetry.utils import ( extract_span_data, extract_span_status, span_data_for_db_query,