Skip to content

Commit

Permalink
Added ability to extract span attributes from django request objects.
Browse files Browse the repository at this point in the history
OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS env var can be set to a command
separated list of attributes names that will be extracted from Django's
request object and set as attributes on spans.
  • Loading branch information
owais committed Sep 24, 2020
1 parent 7636547 commit 9702292
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Changed span name extraction from request to comply semantic convention ([#992](https://github.com/open-telemetry/opentelemetry-python/pull/992))
- Added support for `OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS` ([#1154](https://github.com/open-telemetry/opentelemetry-python/pull/1154))

## Version 0.13b0

Expand Down
15 changes: 15 additions & 0 deletions instrumentation/opentelemetry-instrumentation-django/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ For example,

will exclude requests such as ``https://site/client/123/info`` and ``https://site/xyz/healthcheck``.

Request attributes
********************
To extract certain attributes from Django's request object and use them as span attributes, set the environment variable ``OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS`` to a comma
delimited list of request attribute names.

For example,

::

export OTEL_PYTHON_DJANGO_TRACED_REQUEST_ATTRS='path_info,content_type'

will extract path_info and content_type attributes from every traced request and add them as span attritbues.

Django Request object reference: https://docs.djangoproject.com/en/3.1/ref/request-response/#attributes

References
----------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ class _DjangoMiddleware(MiddlewareMixin):
else:
_excluded_urls = ExcludeList(_excluded_urls)

_traced_request_attrs = [
attr.strip()
for attr in (Configuration().DJANGO_TRACED_REQUEST_ATTRS or "").split(
","
)
]

@staticmethod
def _get_span_name(request):
try:
Expand Down Expand Up @@ -95,6 +102,11 @@ def process_request(self, request):
tracer = get_tracer(__name__, __version__)

attributes = collect_request_attributes(environ)
for attr in self._traced_request_attrs:
if hasattr(request, attr):
value = str(getattr(request, attr))
if value:
attributes[attr] = value

span = tracer.start_span(
self._get_span_name(request),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,30 @@ def test_span_name_404(self):

span = span_list[0]
self.assertEqual(span.name, "HTTP GET")

def test_traced_request_attrs(self):
with patch(
"opentelemetry.instrumentation.django.middleware._DjangoMiddleware._traced_request_attrs",
[],
):
Client().get("/span_name/1234/", CONTENT_TYPE="test/ct")
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)

span = span_list[0]
self.assertNotIn("path_info", span.attributes)
self.assertNotIn("content_type", span.attributes)
self.memory_exporter.clear()

with patch(
"opentelemetry.instrumentation.django.middleware._DjangoMiddleware._traced_request_attrs",
["path_info", "content_type", "non_existing_variable"],
):
Client().get("/span_name/1234/", CONTENT_TYPE="test/ct")
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)

span = span_list[0]
self.assertEqual(span.attributes["path_info"], "/span_name/1234/")
self.assertEqual(span.attributes["content_type"], "test/ct")
self.assertNotIn("non_existing_variable", span.attributes)

0 comments on commit 9702292

Please sign in to comment.