From b32be746e4a2d5ff2cd2bb8ebe5731197d395800 Mon Sep 17 00:00:00 2001 From: Sanket Mehta Date: Tue, 25 Jan 2022 21:01:13 +0530 Subject: [PATCH] Develop/conditional server span pyramid (#869) * code change to resolve the bug https://github.com/open-telemetry/opentelemetry-python-contrib/issues/449 * modifying the changelog file to add entry for PR #869 * removing redundent get statement * Conditionally create server spans for falcon (#867) * Making span as internal for falcon in presence of a span in current context * Updating changelog * Fixing lint and generate build failures * Resolving comments: Converting snippet to re-usable function * Fixing build failures * Resolving comments: Creating wrapper for start span to make internal/server span * Rerun docker tests * Resolving comments: Refactoring * Fix Django 1.9 issue preventing use of MIDDLEWARE_CLASSES (#870) * Update CHANGELOG.md * Fix Django 1.9 issue preventing use of MIDDLEWARE_CLASSES Co-authored-by: Srikanth Chekuri * changing the import trace statement to resolve issue with unit test cases Co-authored-by: Ashutosh Goel <39601429+ashu658@users.noreply.github.com> Co-authored-by: Dan Co-authored-by: Srikanth Chekuri Co-authored-by: Owais Lone --- CHANGELOG.md | 2 ++ .../instrumentation/pyramid/callbacks.py | 19 +++++++---- .../tests/test_automatic.py | 32 +++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3beab54b6..450c13f20b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.8.0-0.27b0...HEAD) +- `opentelemetry-instrumentation-pyramid` Pyramid: Conditionally create SERVER spans + ([#869](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/869)) ### Added diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py index f8be4ca720..788c930e0d 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/src/opentelemetry/instrumentation/pyramid/callbacks.py @@ -82,9 +82,8 @@ def _before_traversal(event): start_time = request_environ.get(_ENVIRON_STARTTIME_KEY) - token = context.attach( - extract(request_environ, getter=otel_wsgi.wsgi_getter) - ) + token = ctx = None + span_kind = trace.SpanKind.INTERNAL tracer = trace.get_tracer(__name__, __version__) if request.matched_route: @@ -92,9 +91,14 @@ def _before_traversal(event): else: span_name = otel_wsgi.get_default_span_name(request_environ) + if trace.get_current_span() is trace.INVALID_SPAN: + ctx = extract(request_environ, getter=otel_wsgi.wsgi_getter) + token = context.attach(ctx) + span_kind = trace.SpanKind.SERVER span = tracer.start_span( span_name, - kind=trace.SpanKind.SERVER, + ctx, + kind=span_kind, start_time=start_time, ) @@ -111,7 +115,8 @@ def _before_traversal(event): activation.__enter__() # pylint: disable=E1101 request_environ[_ENVIRON_ACTIVATION_KEY] = activation request_environ[_ENVIRON_SPAN_KEY] = span - request_environ[_ENVIRON_TOKEN] = token + if token: + request_environ[_ENVIRON_TOKEN] = token def trace_tween_factory(handler, registry): @@ -180,7 +185,9 @@ def trace_tween(request): else: activation.__exit__(None, None, None) - context.detach(request.environ.get(_ENVIRON_TOKEN)) + env_token = request.environ.get(_ENVIRON_TOKEN, None) + if env_token is not None: + context.detach(env_token) return response diff --git a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py index b065e26064..37b2be4c76 100644 --- a/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py +++ b/instrumentation/opentelemetry-instrumentation-pyramid/tests/test_automatic.py @@ -17,6 +17,7 @@ from opentelemetry.instrumentation.pyramid import PyramidInstrumentor from opentelemetry.test.test_base import TestBase from opentelemetry.test.wsgitestutil import WsgiTestBase +from opentelemetry.trace import SpanKind # pylint: disable=import-error from .pyramid_base_test import InstrumentationTest @@ -77,3 +78,34 @@ def test_tween_list(self): self.assertEqual([b"Hello: 123"], list(resp.response)) span_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(span_list), 1) + + +class TestWrappedWithOtherFramework( + InstrumentationTest, TestBase, WsgiTestBase +): + def setUp(self): + super().setUp() + PyramidInstrumentor().instrument() + self.config = Configurator() + self._common_initialization(self.config) + + def tearDown(self) -> None: + super().tearDown() + with self.disable_logging(): + PyramidInstrumentor().uninstrument() + + def test_with_existing_span(self): + tracer_provider, _ = self.create_tracer_provider() + tracer = tracer_provider.get_tracer(__name__) + + with tracer.start_as_current_span( + "test", kind=SpanKind.SERVER + ) as parent_span: + resp = self.client.get("/hello/123") + self.assertEqual(200, resp.status_code) + span_list = self.memory_exporter.get_finished_spans() + self.assertEqual(SpanKind.INTERNAL, span_list[0].kind) + self.assertEqual( + parent_span.get_span_context().span_id, + span_list[0].parent.span_id, + )