From 345aeda1b2c445e5a4795c0700147c25378f1bca Mon Sep 17 00:00:00 2001 From: Varsha GS Date: Tue, 17 Sep 2024 19:48:22 +0530 Subject: [PATCH] pyramid: enable auto-instrumentation Signed-off-by: Varsha GS --- src/instana/__init__.py | 1 + .../instrumentation/pyramid/__init__.py | 0 .../{pyramid/tweens.py => pyramid_inst.py} | 34 ++++++++++++++++++- .../{ => pyramid}/pyramid_app/__init__.py | 2 +- tests/apps/{ => pyramid}/pyramid_app/app.py | 6 ++-- tests/apps/pyramid/pyramid_utils/tweens.py | 16 +++++++++ tests/frameworks/test_pyramid.py | 2 +- 7 files changed, 56 insertions(+), 5 deletions(-) delete mode 100644 src/instana/instrumentation/pyramid/__init__.py rename src/instana/instrumentation/{pyramid/tweens.py => pyramid_inst.py} (77%) rename tests/apps/{ => pyramid}/pyramid_app/__init__.py (78%) rename tests/apps/{ => pyramid}/pyramid_app/app.py (91%) create mode 100644 tests/apps/pyramid/pyramid_utils/tweens.py diff --git a/src/instana/__init__.py b/src/instana/__init__.py index 7ecf67a18..c2457e8f8 100644 --- a/src/instana/__init__.py +++ b/src/instana/__init__.py @@ -199,6 +199,7 @@ def boot_agent(): # client, # noqa: F401 # server, # noqa: F401 # ) + from instana.instrumentation import pyramid_inst # Hooks # from instana.hooks import hook_uwsgi # noqa: F401 diff --git a/src/instana/instrumentation/pyramid/__init__.py b/src/instana/instrumentation/pyramid/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/instana/instrumentation/pyramid/tweens.py b/src/instana/instrumentation/pyramid_inst.py similarity index 77% rename from src/instana/instrumentation/pyramid/tweens.py rename to src/instana/instrumentation/pyramid_inst.py index aed34e63d..bc001a8de 100644 --- a/src/instana/instrumentation/pyramid/tweens.py +++ b/src/instana/instrumentation/pyramid_inst.py @@ -3,7 +3,11 @@ from pyramid.httpexceptions import HTTPException +from pyramid.path import caller_package +from pyramid.settings import aslist +from pyramid.tweens import EXCVIEW from typing import TYPE_CHECKING, Dict, Any, Callable +import wrapt from opentelemetry.semconv.trace import SpanAttributes from opentelemetry.trace import SpanKind @@ -104,6 +108,34 @@ def __call__(self, request: "Request") -> "Response": return response +INSTANA_TWEEN = __name__ + ".InstanaTweenFactory" + + +# implicit tween ordering def includeme(config: "Configurator") -> None: logger.debug("Instrumenting pyramid") - config.add_tween(__name__ + ".InstanaTweenFactory") + config.add_tween(INSTANA_TWEEN) + + +# explicit tween ordering +@wrapt.patch_function_wrapper("pyramid.config", "Configurator.__init__") +def init_with_instana(wrapped, instance, args, kwargs): + settings = kwargs.get("settings", {}) + tweens = aslist(settings.get("pyramid.tweens", [])) + + if tweens and INSTANA_TWEEN not in settings: + # pyramid.tweens.EXCVIEW is the name of built-in exception view provided by + # pyramid. We need our tween to be before it, otherwise unhandled + # exceptions will be caught before they reach our tween. + if EXCVIEW in tweens: + tweens = [INSTANA_TWEEN] + tweens + else: + tweens = [INSTANA_TWEEN] + tweens + [EXCVIEW] + settings["pyramid.tweens"] = "\n".join(tweens) + kwargs["settings"] = settings + + if not kwargs.get("package", None): + kwargs["package"] = caller_package() + + wrapped(*args, **kwargs) + instance.include(__name__) diff --git a/tests/apps/pyramid_app/__init__.py b/tests/apps/pyramid/pyramid_app/__init__.py similarity index 78% rename from tests/apps/pyramid_app/__init__.py rename to tests/apps/pyramid/pyramid_app/__init__.py index c42e24b46..bae667907 100644 --- a/tests/apps/pyramid_app/__init__.py +++ b/tests/apps/pyramid/pyramid_app/__init__.py @@ -2,7 +2,7 @@ # (c) Copyright Instana Inc. 2020 import os -from tests.apps.pyramid_app.app import pyramid_server as server +from tests.apps.pyramid.pyramid_app.app import pyramid_server as server from tests.apps.utils import launch_background_thread app_thread = None diff --git a/tests/apps/pyramid_app/app.py b/tests/apps/pyramid/pyramid_app/app.py similarity index 91% rename from tests/apps/pyramid_app/app.py rename to tests/apps/pyramid/pyramid_app/app.py index 89c00b163..867b2e7cb 100644 --- a/tests/apps/pyramid_app/app.py +++ b/tests/apps/pyramid/pyramid_app/app.py @@ -40,8 +40,10 @@ def hello_user(request): app = None -with Configurator() as config: - config.include("instana.instrumentation.pyramid.tweens") +settings = { + "pyramid.tweens": "tests.apps.pyramid.pyramid_utils.tweens.timing_tween_factory", +} +with Configurator(settings=settings) as config: config.add_route("hello", "/") config.add_view(hello_world, route_name="hello") config.add_route("fail", "/500") diff --git a/tests/apps/pyramid/pyramid_utils/tweens.py b/tests/apps/pyramid/pyramid_utils/tweens.py new file mode 100644 index 000000000..0183df4bb --- /dev/null +++ b/tests/apps/pyramid/pyramid_utils/tweens.py @@ -0,0 +1,16 @@ +# (c) Copyright IBM Corp. 2024 + +import time + + +def timing_tween_factory(handler, registry): + def timing_tween(request): + start = time.time() + try: + response = handler(request) + finally: + end = time.time() + print(f"The request took {end - start} seconds") + return response + + return timing_tween diff --git a/tests/frameworks/test_pyramid.py b/tests/frameworks/test_pyramid.py index d2378d3a8..dcd414740 100644 --- a/tests/frameworks/test_pyramid.py +++ b/tests/frameworks/test_pyramid.py @@ -5,7 +5,7 @@ import urllib3 from typing import Generator -import tests.apps.pyramid_app +import tests.apps.pyramid.pyramid_app from tests.helpers import testenv from instana.singletons import tracer, agent from instana.span.span import get_current_span