From edb750480f00a1852300dde823673f168e2766f0 Mon Sep 17 00:00:00 2001 From: Munir Abdinur Date: Fri, 20 Dec 2024 14:34:14 -0500 Subject: [PATCH 1/2] chore(tracer): make tracer a singleton --- ddtrace/_trace/tracer.py | 18 ++++++++++++++++++ ddtrace/contrib/grpc/__init__.py | 8 +++----- ddtrace/contrib/vertica/__init__.py | 3 +-- ddtrace/opentracer/tracer.py | 14 +++++++++++--- tests/utils.py | 5 +++++ 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/ddtrace/_trace/tracer.py b/ddtrace/_trace/tracer.py index 6027976d6dc..d7d6cca8f78 100644 --- a/ddtrace/_trace/tracer.py +++ b/ddtrace/_trace/tracer.py @@ -196,6 +196,24 @@ class Tracer(object): """ SHUTDOWN_TIMEOUT = 5 + _instance = None + + def ___new__(cls, *args, **kwargs): + if cls._instance is None: + cls._instance = super(Tracer, cls).__new__(cls) + else: + # ddtrace library does not support context propagation for multiple tracers. + # All instances of ddtrace ContextProviders share the same ContextVars. This means that + # if you create multiple instances of Tracer, spans will be shared between them creating a + # broken experience. + # TODO(mabdinur): Convert this warning to an ValueError in 3.0.0 + deprecate( + "Creating multiple Tracer instances is deprecated", + "Use ddtrace.tracer to access the global tracer instance", + category=DDTraceDeprecationWarning, + removal_version="3.0.0", + ) + return cls._instance def __init__( self, diff --git a/ddtrace/contrib/grpc/__init__.py b/ddtrace/contrib/grpc/__init__.py index c329762316c..ce09c5fb324 100644 --- a/ddtrace/contrib/grpc/__init__.py +++ b/ddtrace/contrib/grpc/__init__.py @@ -45,13 +45,12 @@ ``Pin`` API:: import grpc - from ddtrace import Pin, patch, Tracer + from ddtrace import Pin, patch patch(grpc=True) - custom_tracer = Tracer() # override the pin on the client - Pin.override(grpc.Channel, service='mygrpc', tracer=custom_tracer) + Pin.override(grpc.Channel, service='mygrpc') with grpc.insecure_channel('localhost:50051') as channel: # create stubs and send requests pass @@ -64,10 +63,9 @@ from ddtrace import Pin, patch, Tracer patch(grpc=True) - custom_tracer = Tracer() # override the pin on the server - Pin.override(grpc.Server, service='mygrpc', tracer=custom_tracer) + Pin.override(grpc.Server, service='mygrpc') server = grpc.server(logging_pool.pool(2)) server.add_insecure_port('localhost:50051') add_MyServicer_to_server(MyServicer(), server) diff --git a/ddtrace/contrib/vertica/__init__.py b/ddtrace/contrib/vertica/__init__.py index dfafe39a79f..cae4e15f3d2 100644 --- a/ddtrace/contrib/vertica/__init__.py +++ b/ddtrace/contrib/vertica/__init__.py @@ -32,11 +32,10 @@ import vertica_python - custom_tracer = Tracer() conn = vertica_python.connect(**YOUR_VERTICA_CONFIG) # override the service and tracer to be used - Pin.override(conn, service='myverticaservice', tracer=custom_tracer) + Pin.override(conn, service='myverticaservice') """ from ddtrace.internal.utils.importlib import require_modules diff --git a/ddtrace/opentracer/tracer.py b/ddtrace/opentracer/tracer.py index 489c025037a..110fad2401c 100644 --- a/ddtrace/opentracer/tracer.py +++ b/ddtrace/opentracer/tracer.py @@ -18,6 +18,7 @@ from ddtrace.internal.constants import SPAN_API_OPENTRACING from ddtrace.internal.utils.config import get_application_name from ddtrace.settings import ConfigException +from ddtrace.vendor.debtcollector import deprecate from ..internal.logger import get_logger from .propagation import HTTPPropagator @@ -70,8 +71,8 @@ def __init__( If ``None`` is provided, defaults to :class:`opentracing.scope_managers.ThreadLocalScopeManager`. :param dd_tracer: (optional) the Datadog tracer for this tracer to use. This - should only be passed if a custom Datadog tracer is being used. Defaults - to the global ``ddtrace.tracer`` tracer. + parameter is deprecated and will be removed in v3.0.0. The + to the global tracer (``ddtrace.tracer``) should always be used. """ # Merge the given config with the default into a new dict self._config = DEFAULT_CONFIG.copy() @@ -99,7 +100,14 @@ def __init__( self._scope_manager = scope_manager or ThreadLocalScopeManager() dd_context_provider = get_context_provider_for_scope_manager(self._scope_manager) - self._dd_tracer = dd_tracer or ddtrace.tracer or DatadogTracer() + if dd_tracer is not None: + deprecate( + "The ``dd_tracer`` parameter is deprecated", + message="The global tracer (``ddtrace.tracer``) will be used instead.", + removal_version="3.0.0", + ) + + self._dd_tracer = dd_tracer or ddtrace.tracer self._dd_tracer.set_tags(self._config.get(keys.GLOBAL_TAGS)) # type: ignore[arg-type] self._dd_tracer.configure( enabled=self._config.get(keys.ENABLED), diff --git a/tests/utils.py b/tests/utils.py index de0129f75a3..42d6787d401 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -609,6 +609,11 @@ class DummyTracer(Tracer): DummyTracer is a tracer which uses the DummyWriter by default """ + def ___new__(cls, *args, **kwargs): + # Override the __new__ method to ensure we can have multiple instances of the DummyTracer + cls._instance = super(object, cls).__new__(cls) + return cls._instance + def __init__(self, *args, **kwargs): super(DummyTracer, self).__init__() self._trace_flush_disabled_via_env = not asbool(os.getenv("_DD_TEST_TRACE_FLUSH_ENABLED", True)) From 728a816e08fd43b427cce831dd58ef9b934f73a3 Mon Sep 17 00:00:00 2001 From: Munir Abdinur Date: Fri, 20 Dec 2024 16:07:07 -0500 Subject: [PATCH 2/2] rn --- .../deprecate-multiple-tracer-instances-078b920081ba4a36.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 releasenotes/notes/deprecate-multiple-tracer-instances-078b920081ba4a36.yaml diff --git a/releasenotes/notes/deprecate-multiple-tracer-instances-078b920081ba4a36.yaml b/releasenotes/notes/deprecate-multiple-tracer-instances-078b920081ba4a36.yaml new file mode 100644 index 00000000000..7b96d366269 --- /dev/null +++ b/releasenotes/notes/deprecate-multiple-tracer-instances-078b920081ba4a36.yaml @@ -0,0 +1,4 @@ +--- +deprecations: + - | + tracing: Deprecates the use of multiple tracer instances in the same process. The global tracer (``ddtrace.tracer``) `should be used instead.