From c27b14bfb9883a38fe5164171c7df68e631f8e02 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:41:29 -0500 Subject: [PATCH] feat(aiohttp): add client integration (#3362) (#3408) This PR adds support for aiohttp client. Work was long ago started on this in (#294 (thank you @thehesiod!!!). There were a number of issues in the library that led to not being able to merge in the work such as async context management, service naming, integration configuration and more which have all since been addressed. #294 and later #1372 included additional support for ClientResponse and StreamReader which are omitted here with the intention of introducing them as follow ups. Co-authored-by: Alexander Mohr Co-authored-by: Kyle Verhoog Co-authored-by: Alexander Mohr --- .circleci/config.yml | 2 + ddtrace/contrib/aiohttp/__init__.py | 40 +++- ddtrace/contrib/aiohttp/patch.py | 116 ++++++++++- ddtrace/contrib/trace_utils_async.py | 39 ++++ docs/index.rst | 4 +- .../notes/aiohttp-98ae9ce70dda1dbc.yaml | 6 + riotfile.py | 31 ++- tests/contrib/aiohttp/conftest.py | 10 +- tests/contrib/aiohttp/test_aiohttp_client.py | 189 ++++++++++++++++++ tests/contrib/config.py | 5 + ....test_aiohttp_client.test_200_request.json | 36 ++++ ..._aiohttp_client.test_200_request_post.json | 36 ++++ ....test_aiohttp_client.test_500_request.json | 37 ++++ ...est_configure_global_service_name_env.json | 36 ++++ ...lient.test_configure_service_name_pin.json | 36 ++++ ...st_aiohttp_client.test_trace_multiple.json | 108 ++++++++++ ...t_aiohttp_client.test_trace_parenting.json | 48 +++++ ...iohttp_client.test_trace_query_string.json | 37 ++++ 18 files changed, 803 insertions(+), 13 deletions(-) create mode 100644 ddtrace/contrib/trace_utils_async.py create mode 100644 releasenotes/notes/aiohttp-98ae9ce70dda1dbc.yaml create mode 100644 tests/contrib/aiohttp/test_aiohttp_client.py create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request.json create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request_post.json create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_500_request.json create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_global_service_name_env.json create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_service_name_pin.json create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_multiple.json create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_parenting.json create mode 100644 tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_query_string.json diff --git a/.circleci/config.yml b/.circleci/config.yml index 7584cb2a625..dcdc9da263f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -469,10 +469,12 @@ jobs: aiohttp: <<: *machine_executor + parallelism: 6 steps: - run_test: pattern: 'aiohttp' snapshot: true + docker_services: 'httpbin_local' asgi: <<: *contrib_job_small diff --git a/ddtrace/contrib/aiohttp/__init__.py b/ddtrace/contrib/aiohttp/__init__.py index 04ac34c72a6..fa81b649913 100644 --- a/ddtrace/contrib/aiohttp/__init__.py +++ b/ddtrace/contrib/aiohttp/__init__.py @@ -1,7 +1,43 @@ """ -The ``aiohttp`` integration traces all requests defined in the application handlers. +The ``aiohttp`` integration traces requests made with the client or to the server. -Automatic instrumentation is not available for ``aiohttp.web.Application``, instead +The client is automatically instrumented while the server must be manually instrumented using middleware. + +Client +****** + +Enabling +~~~~~~~~ + +The client integration is enabled automatically when using +:ref:`ddtrace-run` or :func:`patch_all()`. + +Or use :func:`patch()` to manually enable the integration:: + + from ddtrace import patch + patch(aiohttp=True) + + +Global Configuration +~~~~~~~~~~~~~~~~~~~~ + +.. py:data:: ddtrace.config.aiohttp_client['distributed_tracing'] + + Include distributed tracing headers in requests sent from the aiohttp client. + + This option can also be set with the ``DD_AIOHTTP_CLIENT_DISTRIBUTED_TRACING`` + environment variable. + + Default: ``True`` + + +Server +****** + +Enabling +~~~~~~~~ + +Automatic instrumentation is not available for the server, instead the provided ``trace_app`` function must be used:: from aiohttp import web diff --git a/ddtrace/contrib/aiohttp/patch.py b/ddtrace/contrib/aiohttp/patch.py index 17034bb86f1..7e7b5bcef5f 100644 --- a/ddtrace/contrib/aiohttp/patch.py +++ b/ddtrace/contrib/aiohttp/patch.py @@ -1,25 +1,139 @@ +import os + +from yarl import URL + from ddtrace import config from ddtrace.internal.logger import get_logger +from ddtrace.internal.utils import get_argument_value +from ddtrace.internal.utils.formats import asbool +from ddtrace.vendor import wrapt + +from ...ext import SpanTypes +from ...internal.compat import parse +from ...pin import Pin +from ...propagation.http import HTTPPropagator +from ..trace_utils import ext_service +from ..trace_utils import set_http_meta +from ..trace_utils import unwrap +from ..trace_utils import with_traced_module as with_traced_module_sync +from ..trace_utils import wrap +from ..trace_utils_async import with_traced_module log = get_logger(__name__) +# Server config config._add( "aiohttp", + dict(distributed_tracing=True), +) + +config._add( + "aiohttp_client", dict( - distributed_tracing=True, + distributed_tracing=asbool(os.getenv("DD_AIOHTTP_CLIENT_DISTRIBUTED_TRACING", True)), ), ) +class _WrappedConnectorClass(wrapt.ObjectProxy): + def __init__(self, obj, pin): + super().__init__(obj) + pin.onto(self) + + async def connect(self, req, *args, **kwargs): + pin = Pin.get_from(self) + with pin.tracer.trace("%s.connect" % self.__class__.__name__): + result = await self.__wrapped__.connect(req, *args, **kwargs) + return result + + async def _create_connection(self, req, *args, **kwargs): + pin = Pin.get_from(self) + with pin.tracer.trace("%s._create_connection" % self.__class__.__name__): + result = await self.__wrapped__._create_connection(req, *args, **kwargs) + return result + + +@with_traced_module +async def _traced_clientsession_request(aiohttp, pin, func, instance, args, kwargs): + method = get_argument_value(args, kwargs, 0, "method") # type: str + url = URL(get_argument_value(args, kwargs, 1, "url")) # type: URL + params = kwargs.get("params") + headers = kwargs.get("headers") or {} + + with pin.tracer.trace( + "aiohttp.request", span_type=SpanTypes.HTTP, service=ext_service(pin, config.aiohttp_client) + ) as span: + if pin._config["distributed_tracing"]: + HTTPPropagator.inject(span.context, headers) + kwargs["headers"] = headers + + # Params can be included separate of the URL so the URL has to be constructed + # with the passed params. + url_str = str(url.update_query(params) if params else url) + parsed_url = parse.urlparse(url_str) + set_http_meta( + span, + config.aiohttp_client, + method=method, + url=url_str, + query=parsed_url.query, + request_headers=headers, + ) + resp = await func(*args, **kwargs) # type: aiohttp.ClientResponse + set_http_meta( + span, config.aiohttp_client, response_headers=resp.headers, status_code=resp.status, status_msg=resp.reason + ) + return resp + + +@with_traced_module_sync +def _traced_clientsession_init(aiohttp, pin, func, instance, args, kwargs): + func(*args, **kwargs) + instance._connector = _WrappedConnectorClass(instance._connector, pin) + + +def _patch_client(aiohttp): + Pin().onto(aiohttp) + pin = Pin(_config=config.aiohttp_client.copy()) + pin.onto(aiohttp.ClientSession) + + wrap("aiohttp", "ClientSession.__init__", _traced_clientsession_init(aiohttp)) + wrap("aiohttp", "ClientSession._request", _traced_clientsession_request(aiohttp)) + + def patch(): + # Legacy patch aiohttp_jinja2 from ddtrace.contrib.aiohttp_jinja2 import patch as aiohttp_jinja2_patch aiohttp_jinja2_patch() + import aiohttp + + if getattr(aiohttp, "_datadog_patch", False): + return + + _patch_client(aiohttp) + + setattr(aiohttp, "_datadog_patch", True) + + +def _unpatch_client(aiohttp): + unwrap(aiohttp.ClientSession, "__init__") + unwrap(aiohttp.ClientSession, "_request") + def unpatch(): from ddtrace.contrib.aiohttp_jinja2 import unpatch as aiohttp_jinja2_unpatch aiohttp_jinja2_unpatch() + + import aiohttp + + if not getattr(aiohttp, "_datadog_patch", False): + return + + _unpatch_client(aiohttp) + + setattr(aiohttp, "_datadog_patch", False) diff --git a/ddtrace/contrib/trace_utils_async.py b/ddtrace/contrib/trace_utils_async.py new file mode 100644 index 00000000000..63a3325db50 --- /dev/null +++ b/ddtrace/contrib/trace_utils_async.py @@ -0,0 +1,39 @@ +""" +async tracing utils + +Note that this module should only be imported in Python 3.5+. +""" +from ddtrace import Pin +from ddtrace.internal.logger import get_logger + + +log = get_logger(__name__) + + +def with_traced_module(func): + """Async version of trace_utils.with_traced_module. + Usage:: + + @with_traced_module + async def my_traced_wrapper(django, pin, func, instance, args, kwargs): + # Do tracing stuff + pass + + def patch(): + import django + wrap(django.somefunc, my_traced_wrapper(django)) + """ + + def with_mod(mod): + async def wrapper(wrapped, instance, args, kwargs): + pin = Pin._find(instance, mod) + if pin and not pin.enabled(): + return await wrapped(*args, **kwargs) + elif not pin: + log.debug("Pin not found for traced method %r", wrapped) + return await wrapped(*args, **kwargs) + return await func(mod, pin, wrapped, instance, args, kwargs) + + return wrapper + + return with_mod diff --git a/docs/index.rst b/docs/index.rst index 13ee20e0133..8cac37c97ad 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -42,7 +42,9 @@ contacting support. +==================================================+===============+================+ | :ref:`aiobotocore` | >= 0.2.3 | No | +--------------------------------------------------+---------------+----------------+ -| :ref:`aiohttp` | >= 2.0 | No | +| :ref:`aiohttp` (client) | >= 2.0 | Yes | ++--------------------------------------------------+---------------+----------------+ +| :ref:`aiohttp` (server) | >= 2.0 | No | +--------------------------------------------------+---------------+----------------+ | :ref:`aiopg` | >= 0.12.0, | Yes | | | <= 0.16 | | diff --git a/releasenotes/notes/aiohttp-98ae9ce70dda1dbc.yaml b/releasenotes/notes/aiohttp-98ae9ce70dda1dbc.yaml new file mode 100644 index 00000000000..dd3838c41d5 --- /dev/null +++ b/releasenotes/notes/aiohttp-98ae9ce70dda1dbc.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + aiohttp: add client integration. This integration traces requests made using the aiohttp client and includes support + for distributed tracing. See `the documentation `_ + for more information. diff --git a/riotfile.py b/riotfile.py index d9689b3adc8..419153a1db8 100644 --- a/riotfile.py +++ b/riotfile.py @@ -1400,11 +1400,34 @@ def select_pys(min_version=MIN_PYTHON_VERSION, max_version=MAX_PYTHON_VERSION): }, ), Venv( - # Python 3.5 is deprecated for aiohttp >= 3.0 - pys=select_pys(min_version="3.6", max_version="3.9"), + # pytest-asyncio is incompatible with aiohttp 3.0+ in Python 3.6 + pys="3.6", + pkgs={ + "aiohttp": [ + "~=3.0", + "~=3.2", + "~=3.4", + "~=3.6", + "~=3.8", + latest, + ], + "aiohttp_jinja2": latest, + "yarl": "~=1.0", + }, + ), + Venv( + pys=select_pys(min_version="3.7", max_version="3.10"), pkgs={ - "aiohttp": ["~=3.0", "~=3.1", "~=3.2", "~=3.3", "~=3.4", "~=3.5", "~=3.6"], - "aiohttp_jinja2": "~=0.15", + "pytest-asyncio": [latest], + "aiohttp": [ + "~=3.0", + "~=3.2", + "~=3.4", + "~=3.6", + "~=3.8", + latest, + ], + "aiohttp_jinja2": latest, "yarl": "~=1.0", }, ), diff --git a/tests/contrib/aiohttp/conftest.py b/tests/contrib/aiohttp/conftest.py index 06f0b3afd84..1446e34643a 100644 --- a/tests/contrib/aiohttp/conftest.py +++ b/tests/contrib/aiohttp/conftest.py @@ -3,7 +3,7 @@ import pytest from ddtrace.contrib.aiohttp.middlewares import trace_app -from ddtrace.contrib.aiohttp.patch import patch +from ddtrace.contrib.aiohttp_jinja2.patch import patch as patch_jinja2 from ddtrace.internal.utils import version from ddtrace.pin import Pin @@ -24,7 +24,7 @@ def app_tracer(tracer, loop): @pytest.fixture def patched_app_tracer(app_tracer): - patch() + patch_jinja2() app, tracer = app_tracer Pin.override(aiohttp_jinja2, tracer=tracer) return app, tracer @@ -34,7 +34,7 @@ def patched_app_tracer(app_tracer): @pytest.fixture def untraced_app_tracer(tracer, loop): - patch() + patch_jinja2() app = setup_app() Pin.override(aiohttp_jinja2, tracer=tracer) return app, tracer @@ -53,7 +53,7 @@ async def app_tracer(tracer, loop): @pytest.fixture async def patched_app_tracer(app_tracer): - patch() + patch_jinja2() app, tracer = app_tracer Pin.override(aiohttp_jinja2, tracer=tracer) return app, tracer @@ -63,7 +63,7 @@ async def patched_app_tracer(app_tracer): @pytest.fixture async def untraced_app_tracer(tracer, loop): - patch() + patch_jinja2() app = setup_app() Pin.override(aiohttp_jinja2, tracer=tracer) return app, tracer diff --git a/tests/contrib/aiohttp/test_aiohttp_client.py b/tests/contrib/aiohttp/test_aiohttp_client.py new file mode 100644 index 00000000000..10264dd0cfe --- /dev/null +++ b/tests/contrib/aiohttp/test_aiohttp_client.py @@ -0,0 +1,189 @@ +import os +import sys + +import aiohttp +import pytest + +from ddtrace import Pin +from ddtrace.contrib.aiohttp import patch +from ddtrace.contrib.aiohttp import unpatch +from tests.utils import override_http_config + +from ..config import HTTPBIN_CONFIG + + +HOST = HTTPBIN_CONFIG["host"] +PORT = HTTPBIN_CONFIG["port"] +SOCKET = "{}:{}".format(HOST, PORT) +URL = "http://{}".format(SOCKET) +URL_200 = "{}/status/200".format(URL) +URL_500 = "{}/status/500".format(URL) + + +@pytest.fixture(autouse=True) +def patch_aiohttp_client(): + patch() + yield + unpatch() + + +@pytest.mark.asyncio +async def test_200_request(snapshot_context): + with snapshot_context(): + async with aiohttp.ClientSession() as session: + async with session.get(URL_200) as resp: + assert resp.status == 200 + + +@pytest.mark.asyncio +async def test_200_request_post(snapshot_context): + with snapshot_context(): + async with aiohttp.ClientSession() as session: + async with session.post(URL_200) as resp: + assert resp.status == 200 + + +@pytest.mark.asyncio +async def test_500_request(snapshot_context): + with snapshot_context(): + async with aiohttp.ClientSession() as session: + async with session.get(URL_500) as resp: + assert resp.status == 500 + + +@pytest.mark.asyncio +async def test_200_request_distributed_tracing(tracer): + async with aiohttp.ClientSession() as session: + async with session.get("%s/headers" % URL) as resp: + assert resp.status == 200 + headers = await resp.json() + for h in ("x-datadog-trace-id", "x-datadog-parent-id", "x-datadog-sampling-priority"): + assert h not in headers + + +@pytest.mark.asyncio +@pytest.mark.parametrize("variant", ["pin", "global"]) +async def test_distributed_tracing_disabled(ddtrace_run_python_code_in_subprocess, variant): + code = """ +import asyncio +import sys +import aiohttp +from ddtrace import Pin +from tests.contrib.aiohttp.test_aiohttp_client import URL + +async def test(): + async with aiohttp.ClientSession() as session: + async with session.get("%s/headers" % URL) as resp: + assert resp.status == 200 + headers = await resp.json() + + for h in ("x-datadog-trace-id", "x-datadog-parent-id", "x-datadog-sampling-priority"): + assert h not in headers + +if sys.version_info >= (3, 7, 0): + asyncio.run(test()) +else: + asyncio.get_event_loop().run_until_complete(test()) + """ + env = os.environ.copy() + if variant == "global": + env["DD_AIOHTTP_CLIENT_DISTRIBUTED_TRACING"] = "false" + out, err, status, pid = ddtrace_run_python_code_in_subprocess(code, env=env) + assert status == 0, err + assert err == b"" + + +@pytest.mark.snapshot(async_mode=False) +def test_configure_global_service_name_env(ddtrace_run_python_code_in_subprocess): + """ + When only setting DD_SERVICE + The value from DD_SERVICE is used + """ + code = """ +import asyncio +import sys +import aiohttp +from tests.contrib.aiohttp.test_aiohttp_client import URL_200 +async def test(): + async with aiohttp.ClientSession() as session: + async with session.get(URL_200) as resp: + pass + +if sys.version_info >= (3, 7, 0): + asyncio.run(test()) +else: + asyncio.get_event_loop().run_until_complete(test()) + """ + env = os.environ.copy() + env["DD_SERVICE"] = "global-service-name" + out, err, status, pid = ddtrace_run_python_code_in_subprocess(code, env=env) + assert status == 0, err + assert err == b"" + + +@pytest.mark.snapshot(async_mode=False) +def test_configure_service_name_pin(ddtrace_run_python_code_in_subprocess): + code = """ +import asyncio +import sys +import aiohttp +from ddtrace import Pin +from tests.contrib.aiohttp.test_aiohttp_client import URL_200 + +async def test(): + async with aiohttp.ClientSession() as session: + Pin.override(session, service="pin-custom-svc") + async with session.get(URL_200) as resp: + pass + +if sys.version_info >= (3, 7, 0): + asyncio.run(test()) +else: + asyncio.get_event_loop().run_until_complete(test()) + """ + out, err, status, pid = ddtrace_run_python_code_in_subprocess(code, env=os.environ.copy()) + assert status == 0, err + assert err == b"" + + +@pytest.mark.asyncio +@pytest.mark.skipif(sys.version_info < (3, 6, 0), reason="Python versions below 3.6 sort dictionaries differently") +async def test_trace_query_string(snapshot_context): + """ + When trace_query_string is enabled + The query string is included as a tag on the span + """ + with override_http_config("aiohttp_client", {"trace_query_string": True}): + with snapshot_context(): + async with aiohttp.ClientSession() as session: + async with session.get( + "%s/?k1=v1&k2=v2" % URL_200, + params={ + "k3": "v3", + "k4": "v4", + }, + ) as resp: + assert resp.status == 404 + + +@pytest.mark.asyncio +async def test_trace_parenting(snapshot_context): + pin = Pin.get_from(aiohttp) + tracer = pin.tracer + with snapshot_context(): + with tracer.trace("parent"): + async with aiohttp.ClientSession() as session: + async with session.get(URL_200) as resp: + assert resp.status == 200 + + +@pytest.mark.asyncio +async def test_trace_multiple(snapshot_context): + with snapshot_context(): + async with aiohttp.ClientSession() as session: + async with session.get(URL_200) as resp: + assert resp.status == 200 + async with session.get(URL_200) as resp: + assert resp.status == 200 + async with session.get(URL_200) as resp: + assert resp.status == 200 diff --git a/tests/contrib/config.py b/tests/contrib/config.py index 0abc5ea41bf..5d660c095bb 100644 --- a/tests/contrib/config.py +++ b/tests/contrib/config.py @@ -80,3 +80,8 @@ "password": os.getenv("TEST_RABBITMQ_PASSWORD", "guest"), "port": int(os.getenv("TEST_RABBITMQ_PORT", 5672)), } + +HTTPBIN_CONFIG = { + "host": "localhost", + "port": 8001, +} diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request.json new file mode 100644 index 00000000000..ad756672de0 --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request.json @@ -0,0 +1,36 @@ +[[ + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "GET", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200", + "runtime-id": "b984b1b0f414444b914808157cba1e4d" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 32687 + }, + "duration": 12671000, + "start": 1646414759574649000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "duration": 7026000, + "start": 1646414759575827000 + }]] diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request_post.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request_post.json new file mode 100644 index 00000000000..56a1a796372 --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_200_request_post.json @@ -0,0 +1,36 @@ +[[ + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "POST", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200", + "runtime-id": "d52ced09ce864933baf63a295ce898d8" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 28240 + }, + "duration": 6568000, + "start": 1646794689782412000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "duration": 2740000, + "start": 1646794689782860000 + }]] diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_500_request.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_500_request.json new file mode 100644 index 00000000000..fd77511f48d --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_500_request.json @@ -0,0 +1,37 @@ +[[ + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "type": "http", + "error": 1, + "meta": { + "http.method": "GET", + "http.status_code": "500", + "http.status_msg": "INTERNAL SERVER ERROR", + "http.url": "http://localhost:8001/status/500", + "runtime-id": "b984b1b0f414444b914808157cba1e4d" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 32687 + }, + "duration": 6225000, + "start": 1646414759679627000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "duration": 2061000, + "start": 1646414759680240000 + }]] diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_global_service_name_env.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_global_service_name_env.json new file mode 100644 index 00000000000..001550ae0ee --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_global_service_name_env.json @@ -0,0 +1,36 @@ +[[ + { + "name": "aiohttp.request", + "service": "global-service-name", + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "GET", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200", + "runtime-id": "992426ee48034b75b0dc066b040d8810" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 48841 + }, + "duration": 8008000, + "start": 1646721315459365000 + }, + { + "name": "TCPConnector.connect", + "service": "global-service-name", + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "duration": 4452000, + "start": 1646721315459826000 + }]] diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_service_name_pin.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_service_name_pin.json new file mode 100644 index 00000000000..177e6aceadc --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_configure_service_name_pin.json @@ -0,0 +1,36 @@ +[[ + { + "name": "aiohttp.request", + "service": "pin-custom-svc", + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "GET", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200", + "runtime-id": "b13cb8dce9b247bcb2b3dfb5c2bdddbf" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 49985 + }, + "duration": 22335000, + "start": 1646721987368402000 + }, + { + "name": "TCPConnector.connect", + "service": "pin-custom-svc", + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "duration": 18051000, + "start": 1646721987369091000 + }]] diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_multiple.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_multiple.json new file mode 100644 index 00000000000..b165e1571a5 --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_multiple.json @@ -0,0 +1,108 @@ +[[ + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "GET", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200", + "runtime-id": "2d042941bd8e4cd18a0bcb6ea7c9b80f" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 27506 + }, + "duration": 29211000, + "start": 1646794505597988000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "duration": 26278000, + "start": 1646794505598411000 + }], +[ + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 1, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "GET", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200", + "runtime-id": "2d042941bd8e4cd18a0bcb6ea7c9b80f" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 27506 + }, + "duration": 3596000, + "start": 1646794505627424000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 1, + "span_id": 2, + "parent_id": 1, + "duration": 70000, + "start": 1646794505627940000 + }], +[ + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 2, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "GET", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200", + "runtime-id": "2d042941bd8e4cd18a0bcb6ea7c9b80f" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 27506 + }, + "duration": 3312000, + "start": 1646794505631290000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 2, + "span_id": 2, + "parent_id": 1, + "duration": 136000, + "start": 1646794505631851000 + }]] diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_parenting.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_parenting.json new file mode 100644 index 00000000000..66cd2dea8f3 --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_parenting.json @@ -0,0 +1,48 @@ +[[ + { + "name": "parent", + "service": null, + "resource": "parent", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "meta": { + "runtime-id": "93de13222bfa491d896a7fd6f40622e1" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 27123 + }, + "duration": 6315000, + "start": 1646794413225857000 + }, + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "type": "http", + "meta": { + "http.method": "GET", + "http.status_code": "200", + "http.status_msg": "OK", + "http.url": "http://localhost:8001/status/200" + }, + "duration": 5716000, + "start": 1646794413226273000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 3, + "parent_id": 2, + "duration": 2464000, + "start": 1646794413226798000 + }]] diff --git a/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_query_string.json b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_query_string.json new file mode 100644 index 00000000000..63f2961cebe --- /dev/null +++ b/tests/snapshots/tests.contrib.aiohttp.test_aiohttp_client.test_trace_query_string.json @@ -0,0 +1,37 @@ +[[ + { + "name": "aiohttp.request", + "service": null, + "resource": "aiohttp.request", + "trace_id": 0, + "span_id": 1, + "parent_id": 0, + "type": "http", + "meta": { + "http.method": "GET", + "http.query.string": "k1=v1&k2=v2&k3=v3&k4=v4", + "http.status_code": "404", + "http.status_msg": "NOT FOUND", + "http.url": "http://localhost:8001/status/200/?k1=v1&k2=v2&k3=v3&k4=v4", + "runtime-id": "61df78e7f89c4a8f90049e780be97e8f" + }, + "metrics": { + "_dd.agent_psr": 1.0, + "_dd.top_level": 1, + "_dd.tracer_kr": 1.0, + "_sampling_priority_v1": 1, + "system.pid": 83844 + }, + "duration": 5072000, + "start": 1646853117219334000 + }, + { + "name": "TCPConnector.connect", + "service": null, + "resource": "TCPConnector.connect", + "trace_id": 0, + "span_id": 2, + "parent_id": 1, + "duration": 1803000, + "start": 1646853117220225000 + }]]