Skip to content

Commit

Permalink
Merge branch '3.x-staging' into yunkim/fix-langchain-deprecated-cost
Browse files Browse the repository at this point in the history
  • Loading branch information
Yun-Kim authored Feb 5, 2025
2 parents 517d8c9 + 25e7e2e commit ec1bd48
Show file tree
Hide file tree
Showing 97 changed files with 888 additions and 635 deletions.
70 changes: 39 additions & 31 deletions ddtrace/_trace/pin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import wrapt

import ddtrace
from ddtrace.vendor.debtcollector import deprecate

from ..internal.logger import get_logger

Expand All @@ -32,25 +31,17 @@ class Pin(object):
>>> conn = sqlite.connect('/tmp/image.db')
"""

__slots__ = ["tags", "tracer", "_target", "_config", "_initialized"]
__slots__ = ["tags", "_tracer", "_target", "_config", "_initialized"]

def __init__(
self,
service=None, # type: Optional[str]
tags=None, # type: Optional[Dict[str, str]]
tracer=None,
_config=None, # type: Optional[Dict[str, Any]]
):
# type: (...) -> None
if tracer is not None and tracer is not ddtrace.tracer:
deprecate(
"Initializing ddtrace.trace.Pin with `tracer` argument is deprecated",
message="All Pin instances should use the global tracer instance",
removal_version="3.0.0",
)
tracer = tracer or ddtrace.tracer
self.tags = tags
self.tracer = tracer
self._tracer = ddtrace.tracer
self._target = None # type: Optional[int]
# keep the configuration attribute internal because the
# public API to access it is not the Pin class
Expand All @@ -68,10 +59,14 @@ def service(self):
return self._config["service_name"]

def __setattr__(self, name, value):
if getattr(self, "_initialized", False) and name != "_target":
if getattr(self, "_initialized", False) and name not in ("_target", "_tracer"):
raise AttributeError("can't mutate a pin, use override() or clone() instead")
super(Pin, self).__setattr__(name, value)

@property
def tracer(self):
return self._tracer

def __repr__(self):
return "Pin(service=%s, tags=%s, tracer=%s)" % (self.service, self.tags, self.tracer)

Expand Down Expand Up @@ -127,7 +122,6 @@ def override(
obj, # type: Any
service=None, # type: Optional[str]
tags=None, # type: Optional[Dict[str, str]]
tracer=None,
):
# type: (...) -> None
"""Override an object with the given attributes.
Expand All @@ -139,20 +133,32 @@ def override(
>>> # Override a pin for a specific connection
>>> Pin.override(conn, service='user-db')
"""
if tracer is not None:
deprecate(
"Calling ddtrace.trace.Pin.override(...) with the `tracer` argument is deprecated",
message="All Pin instances should use the global tracer instance",
removal_version="3.0.0",
)
Pin._override(obj, service=service, tags=tags)

@classmethod
def _override(
cls,
obj, # type: Any
service=None, # type: Optional[str]
tags=None, # type: Optional[Dict[str, str]]
tracer=None,
):
# type: (...) -> None
"""
Internal method that allows overriding the global tracer in tests
"""
if not obj:
return

pin = cls.get_from(obj)
if pin is None:
Pin(service=service, tags=tags, tracer=tracer).onto(obj)
pin = Pin(service=service, tags=tags)
else:
pin.clone(service=service, tags=tags, tracer=tracer).onto(obj)
pin = pin.clone(service=service, tags=tags)

if tracer:
pin._tracer = tracer
pin.onto(obj)

def enabled(self):
# type: () -> bool
Expand Down Expand Up @@ -198,21 +204,22 @@ def clone(
self,
service=None, # type: Optional[str]
tags=None, # type: Optional[Dict[str, str]]
tracer=None,
):
# type: (...) -> Pin
"""Return a clone of the pin with the given attributes replaced."""
return self._clone(service=service, tags=tags)

def _clone(
self,
service=None, # type: Optional[str]
tags=None, # type: Optional[Dict[str, str]]
tracer=None,
):
"""Internal method that can clone the tracer from an existing Pin. This is used in tests"""
# do a shallow copy of Pin dicts
if not tags and self.tags:
tags = self.tags.copy()

if tracer is not None:
deprecate(
"Initializing ddtrace.trace.Pin with `tracer` argument is deprecated",
message="All Pin instances should use the global tracer instance",
removal_version="3.0.0",
)

# we use a copy instead of a deepcopy because we expect configurations
# to have only a root level dictionary without nested objects. Using
# deepcopy introduces a big overhead:
Expand All @@ -221,9 +228,10 @@ def clone(
# deepcopy: 0.2787208557128906
config = self._config.copy()

return Pin(
pin = Pin(
service=service or self.service,
tags=tags,
tracer=tracer or self.tracer, # do not clone the Tracer
_config=config,
)
pin._tracer = tracer or self.tracer
return pin
8 changes: 2 additions & 6 deletions ddtrace/contrib/internal/asgi/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,8 @@ async def __call__(self, scope, receive, send):
if scope["type"] == "http":
operation_name = schematize_url_operation(operation_name, direction=SpanDirection.INBOUND, protocol="http")

# Calling ddtrace.trace.Pin(...) with the `tracer` argument is deprecated
# Remove this if statement when the `tracer` argument is removed
if self.tracer is ddtrace.tracer:
pin = ddtrace.trace.Pin(service="asgi")
else:
pin = ddtrace.trace.Pin(service="asgi", tracer=self.tracer)
pin = ddtrace.trace.Pin(service="asgi")
pin._tracer = self.tracer

with core.context_with_data(
"asgi.__call__",
Expand Down
10 changes: 3 additions & 7 deletions ddtrace/contrib/internal/django/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import wrapt
from wrapt.importer import when_imported

import ddtrace
from ddtrace import config
from ddtrace.appsec._utils import _UserInfoRetriever
from ddtrace.constants import SPAN_KIND
Expand Down Expand Up @@ -149,12 +148,9 @@ def cursor(django, pin, func, instance, args, kwargs):
tags = {"django.db.vendor": vendor, "django.db.alias": alias}
tags.update(getattr(conn, "_datadog_tags", {}))

# Calling ddtrace.pin.Pin(...) with the `tracer` argument generates a deprecation warning.
# Remove this if statement when the `tracer` argument is removed
if pin.tracer is ddtrace.tracer:
pin = Pin(service, tags=tags)
else:
pin = Pin(service, tags=tags, tracer=pin.tracer)
tracer = pin.tracer
pin = Pin(service, tags=tags)
pin._tracer = tracer

cursor = func(*args, **kwargs)

Expand Down
11 changes: 5 additions & 6 deletions ddtrace/contrib/internal/mongoengine/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ def __call__(self, *args, **kwargs):
client = self.__wrapped__(*args, **kwargs)
pin = ddtrace.trace.Pin.get_from(self)
if pin:
# Calling ddtrace.trace.Pin(...) with the `tracer` argument generates a deprecation warning.
# Remove this if statement when the `tracer` argument is removed
if pin.tracer is ddtrace.tracer:
ddtrace.trace.Pin(service=pin.service).onto(client)
else:
ddtrace.trace.Pin(service=pin.service, tracer=pin.tracer).onto(client)
tracer = pin.tracer
pp = ddtrace.trace.Pin(service=pin.service)
if tracer is not None:
pp._tracer = tracer
pp.onto(client)

return client
8 changes: 2 additions & 6 deletions ddtrace/contrib/internal/pylibmc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,8 @@ def __init__(self, client=None, service=memcached.SERVICE, tracer=None, *args, *
super(TracedClient, self).__init__(client)

schematized_service = schematize_service_name(service)
# Calling ddtrace.trace.Pin(...) with the `tracer` argument generates a deprecation warning.
# Remove this if statement when the `tracer` argument is removed
if tracer is ddtrace.tracer:
pin = ddtrace.trace.Pin(service=schematized_service)
else:
pin = ddtrace.trace.Pin(service=schematized_service, tracer=tracer)
pin = ddtrace.trace.Pin(service=schematized_service)
pin._tracer = tracer
pin.onto(self)

# attempt to collect the pool of urls this client talks to
Expand Down
9 changes: 3 additions & 6 deletions ddtrace/contrib/internal/sqlalchemy/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,9 @@ def __init__(self, tracer, service, engine):
self.name = schematize_database_operation("%s.query" % self.vendor, database_provider=self.vendor)

# attach the PIN
# Calling ddtrace.trace.Pin(...) with the `tracer` argument generates a deprecation warning.
# Remove this if statement when the `tracer` argument is removed
if self.tracer is ddtrace.tracer:
Pin(service=self.service).onto(engine)
else:
Pin(tracer=tracer, service=self.service).onto(engine)
pin = Pin(service=self.service)
pin._tracer = self.tracer
pin.onto(engine)

listen(engine, "before_cursor_execute", self._before_cur_exec)
listen(engine, "after_cursor_execute", self._after_cur_exec)
Expand Down
10 changes: 3 additions & 7 deletions ddtrace/contrib/internal/tornado/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ def tracer_config(__init__, app, args, kwargs):
if tags:
tracer.set_tags(tags)

# configure the PIN object for template rendering
# Required for backwards compatibility. Remove the else clause when
# the `ddtrace.trace.Pin` object no longer accepts the Pin argument.
if tracer is ddtrace.tracer:
ddtrace.trace.Pin(service=service).onto(template)
else:
ddtrace.trace.Pin(service=service, tracer=tracer).onto(template)
pin = ddtrace.trace.Pin(service=service)
pin._tracer = tracer
pin.onto(template)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
upgrade:
- |
tracing: Removes support for overriding the global tracer in ``ddtrace.trace.Pin``
2 changes: 1 addition & 1 deletion tests/appsec/contrib_appsec/django_app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def login_user(request):
def new_service(request, service_name: str):
import ddtrace

ddtrace.trace.Pin.override(django, service=service_name, tracer=ddtrace.tracer)
ddtrace.trace.Pin._override(django, service=service_name, tracer=ddtrace.tracer)
return HttpResponse(service_name, status=200)


Expand Down
2 changes: 1 addition & 1 deletion tests/appsec/contrib_appsec/fastapi_app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async def multi_view_no_param(request: Request): # noqa: B008
async def new_service(service_name: str, request: Request): # noqa: B008
import ddtrace

ddtrace.trace.Pin.override(app, service=service_name, tracer=ddtrace.tracer)
ddtrace.trace.Pin._override(app, service=service_name, tracer=ddtrace.tracer)
return HTMLResponse(service_name, 200)

async def slow_numbers(minimum, maximum):
Expand Down
2 changes: 1 addition & 1 deletion tests/appsec/contrib_appsec/flask_app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def multi_view(param_int=0, param_str=""):
def new_service(service_name: str):
import ddtrace

ddtrace.trace.Pin.override(Flask, service=service_name, tracer=ddtrace.tracer)
ddtrace.trace.Pin._override(Flask, service=service_name, tracer=ddtrace.tracer)
return service_name


Expand Down
2 changes: 1 addition & 1 deletion tests/appsec/contrib_appsec/test_flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def setUp(self):
self.app = app
self.app.test_client_class = DDFlaskTestClient
self.client = self.app.test_client()
Pin.override(self.app, tracer=self.tracer)
Pin._override(self.app, tracer=self.tracer)

def tearDown(self):
super(BaseFlaskTestCase, self).tearDown()
Expand Down
4 changes: 2 additions & 2 deletions tests/appsec/contrib_appsec/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1568,7 +1568,7 @@ def test_tracer():
@contextmanager
def post_tracer(interface):
original_tracer = getattr(ddtrace.trace.Pin.get_from(interface.framework), "tracer", None)
ddtrace.trace.Pin.override(interface.framework, tracer=interface.tracer)
ddtrace.trace.Pin._override(interface.framework, tracer=interface.tracer)
yield
if original_tracer is not None:
ddtrace.trace.Pin.override(interface.framework, tracer=original_tracer)
ddtrace.trace.Pin._override(interface.framework, tracer=original_tracer)
4 changes: 2 additions & 2 deletions tests/appsec/integrations/django_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def tracer():
# Patch Django and override tracer to be our test tracer
pin = Pin.get_from(django)
original_tracer = pin.tracer
Pin.override(django, tracer=tracer)
Pin._override(django, tracer=tracer)

# Yield to our test
yield tracer
Expand All @@ -59,7 +59,7 @@ def tracer():
# Reset the tracer pinned to Django and unpatch
# DEV: unable to properly unpatch and reload django app with each test
# unpatch()
Pin.override(django, tracer=original_tracer)
Pin._override(django, tracer=original_tracer)


@pytest.fixture
Expand Down
4 changes: 2 additions & 2 deletions tests/contrib/aiobotocore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ async def aiobotocore_client(service, tracer):
client, aiobotocore.session.ClientCreatorContext
):
async with client as client:
Pin.override(client, tracer=tracer)
Pin._override(client, tracer=tracer)
await yield_(client)

else:
Pin.override(client, tracer=tracer)
Pin._override(client, tracer=tracer)
try:
await yield_(client)
finally:
Expand Down
2 changes: 1 addition & 1 deletion tests/contrib/aiohttp/test_aiohttp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def test_configure_service_name_pin(ddtrace_run_python_code_in_subprocess):
async def test():
async with aiohttp.ClientSession() as session:
Pin.override(session, service="pin-custom-svc")
Pin._override(session, service="pin-custom-svc")
async with session.get(URL_200) as resp:
pass
Expand Down
4 changes: 2 additions & 2 deletions tests/contrib/aiohttp_jinja2/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
def patched_app_tracer_jinja(patched_app_tracer): # noqa: F811
app, tracer = patched_app_tracer
patch()
Pin.override(aiohttp_jinja2, tracer=tracer)
Pin._override(aiohttp_jinja2, tracer=tracer)
yield app, tracer
unpatch()

Expand All @@ -22,6 +22,6 @@ def patched_app_tracer_jinja(patched_app_tracer): # noqa: F811
def untraced_app_tracer_jinja(untraced_app_tracer): # noqa: F811
patch()
app, tracer = untraced_app_tracer
Pin.override(aiohttp_jinja2, tracer=tracer)
Pin._override(aiohttp_jinja2, tracer=tracer)
yield app, tracer
unpatch()
4 changes: 2 additions & 2 deletions tests/contrib/aiohttp_jinja2/test_aiohttp_jinja2.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async def test_template_rendering(untraced_app_tracer_jinja, aiohttp_client):

async def test_template_rendering_snapshot(untraced_app_tracer_jinja, aiohttp_client, snapshot_context):
app, _ = untraced_app_tracer_jinja
Pin.override(aiohttp_jinja2, tracer=tracer)
Pin._override(aiohttp_jinja2, tracer=tracer)
with snapshot_context():
client = await aiohttp_client(app)
# it should trace a template rendering
Expand All @@ -51,7 +51,7 @@ async def test_template_rendering_snapshot_patched_server(
use_global_tracer,
):
app, _ = patched_app_tracer_jinja
Pin.override(aiohttp_jinja2, tracer=tracer)
Pin._override(aiohttp_jinja2, tracer=tracer)
# Ignore meta.http.url tag as the port is not fixed on the server
with snapshot_context(ignores=["meta.http.url", "meta.http.useragent"]):
client = await aiohttp_client(app)
Expand Down
Loading

0 comments on commit ec1bd48

Please sign in to comment.