From d01efe5c5023110447de1741107e53b009b5886e Mon Sep 17 00:00:00 2001 From: Sanket Mehta Date: Sat, 8 Jan 2022 03:54:09 +0530 Subject: [PATCH] Develop/condition server span django (#832) * Code changes and pytests for https://github.com/open-telemetry/opentelemetry-python-contrib/issues/448 * removing unnecessary imports * removing unnecessary imports * adding wsgi.py file to get the wsgi application object * Revert "Updating personal fork from public repo" * Revert "Updating personal fork from public repo" * Revert "Updating personal fork from public repo" * Revert "Updating personal fork from public repo" * Changing the unit test case by removing WSGI instrumentation and make it from generalised * removing unnecessary import statements * Revert "Updating personal fork from public repo" * resolving failed builds for lint and generate * removing commented code * removing blank line * removed unused variable resp from test_middleware.py and modified the CHANGELOG.md with PR entry * modified the CHANGELOG.md to removed unnecessary entry * modified the CHANGELOG.md to add proper PR entry Co-authored-by: Diego Hurtado --- CHANGELOG.md | 3 +++ .../instrumentation/django/middleware.py | 24 ++++++++++++++----- .../tests/test_middleware.py | 19 +++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcf9a79be7..0dfa240b90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- `opentelemetry-instrumentation-django` Django: Conditionally create SERVER spans + ([#832](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/832)) + - `opentelemetry-instrumentation-flask` Flask: Conditionally create SERVER spans ([#828](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/828)) diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py index 9cdc7e682c..47df930bf2 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware.py @@ -32,7 +32,13 @@ from opentelemetry.instrumentation.wsgi import wsgi_getter from opentelemetry.propagate import extract from opentelemetry.semconv.trace import SpanAttributes -from opentelemetry.trace import Span, SpanKind, use_span +from opentelemetry.trace import ( + INVALID_SPAN, + Span, + SpanKind, + get_current_span, + use_span, +) from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs try: @@ -183,11 +189,16 @@ def process_request(self, request): carrier_getter = wsgi_getter collect_request_attributes = wsgi_collect_request_attributes - token = attach(extract(carrier, getter=carrier_getter)) - + token = context = None + span_kind = SpanKind.INTERNAL + if get_current_span() is INVALID_SPAN: + context = extract(carrier, getter=carrier_getter) + token = attach(context) + span_kind = SpanKind.SERVER span = self._tracer.start_span( self._get_span_name(request), - kind=SpanKind.SERVER, + context, + kind=span_kind, start_time=request_meta.get( "opentelemetry-instrumentor-django.starttime_key" ), @@ -220,7 +231,8 @@ def process_request(self, request): request.META[self._environ_activation_key] = activation request.META[self._environ_span_key] = span - request.META[self._environ_token] = token + if token: + request.META[self._environ_token] = token if _DjangoMiddleware._otel_request_hook: _DjangoMiddleware._otel_request_hook( # pylint: disable=not-callable @@ -295,7 +307,7 @@ def process_response(self, request, response): else: activation.__exit__(None, None, None) - if self._environ_token in request.META.keys(): + if request.META.get(self._environ_token, None) is not None: detach(request.META.get(self._environ_token)) request.META.pop(self._environ_token) diff --git a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py index f5d31d920b..32bd1d03fa 100644 --- a/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py @@ -22,6 +22,7 @@ from django.test.client import Client from django.test.utils import setup_test_environment, teardown_test_environment +from opentelemetry import trace from opentelemetry.instrumentation.django import ( DjangoInstrumentor, _DjangoMiddleware, @@ -409,6 +410,7 @@ def setUp(self): result = self.create_tracer_provider(resource=resource) tracer_provider, exporter = result self.exporter = exporter + self.tracer_provider = tracer_provider _django_instrumentor.instrument(tracer_provider=tracer_provider) def tearDown(self): @@ -432,3 +434,20 @@ def test_tracer_provider_traced(self): self.assertEqual( span.resource.attributes["resource-key"], "resource-value" ) + + def test_django_with_wsgi_instrumented(self): + tracer = self.tracer_provider.get_tracer(__name__) + with tracer.start_as_current_span( + "test", kind=SpanKind.SERVER + ) as parent_span: + Client().get("/span_name/1234/") + span_list = self.exporter.get_finished_spans() + print(span_list) + self.assertEqual( + span_list[0].attributes[SpanAttributes.HTTP_STATUS_CODE], 200 + ) + self.assertEqual(trace.SpanKind.INTERNAL, span_list[0].kind) + self.assertEqual( + parent_span.get_span_context().span_id, + span_list[0].parent.span_id, + )