Skip to content

Commit e49806e

Browse files
authored
Configurable Middleware Position for Django Instrumentation (#2912)
1 parent 39bd7fa commit e49806e

File tree

4 files changed

+107
-2
lines changed

4 files changed

+107
-2
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
417417
([#1879](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1879))
418418
- Add optional distro and configurator selection for auto-instrumentation
419419
([#1823](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1823))
420+
- `opentelemetry-instrumentation-django` - Add option to add Opentelemetry middleware at specific position in middleware chain
421+
([#2912]https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2912)
420422

421423
### Added
422424

instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/__init__.py

+34-2
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,30 @@ def _get_django_middleware_setting() -> str:
285285
return "MIDDLEWARE"
286286

287287

288+
def _get_django_otel_middleware_position(
289+
middleware_length, default_middleware_position=0
290+
):
291+
otel_position = environ.get("OTEL_PYTHON_DJANGO_MIDDLEWARE_POSITION")
292+
try:
293+
middleware_position = int(otel_position)
294+
except (ValueError, TypeError):
295+
_logger.debug(
296+
"Invalid OTEL_PYTHON_DJANGO_MIDDLEWARE_POSITION value: (%s). Using default position: %d.",
297+
otel_position,
298+
default_middleware_position,
299+
)
300+
middleware_position = default_middleware_position
301+
302+
if middleware_position < 0 or middleware_position > middleware_length:
303+
_logger.debug(
304+
"Middleware position %d is out of range (0-%d). Using 0 as the position",
305+
middleware_position,
306+
middleware_length,
307+
)
308+
middleware_position = 0
309+
return middleware_position
310+
311+
288312
class DjangoInstrumentor(BaseInstrumentor):
289313
"""An instrumentor for Django
290314
@@ -388,10 +412,18 @@ def _instrument(self, **kwargs):
388412

389413
is_sql_commentor_enabled = kwargs.pop("is_sql_commentor_enabled", None)
390414

415+
middleware_position = _get_django_otel_middleware_position(
416+
len(settings_middleware), kwargs.pop("middleware_position", 0)
417+
)
418+
391419
if is_sql_commentor_enabled:
392-
settings_middleware.insert(0, self._sql_commenter_middleware)
420+
settings_middleware.insert(
421+
middleware_position, self._sql_commenter_middleware
422+
)
393423

394-
settings_middleware.insert(0, self._opentelemetry_middleware)
424+
settings_middleware.insert(
425+
middleware_position, self._opentelemetry_middleware
426+
)
395427

396428
setattr(settings, _middleware_setting, settings_middleware)
397429

instrumentation/opentelemetry-instrumentation-django/tests/test_middleware.py

+40
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,46 @@ def tearDownClass(cls):
157157
super().tearDownClass()
158158
conf.settings = conf.LazySettings()
159159

160+
def test_middleware_added_at_position(self):
161+
_django_instrumentor.uninstrument()
162+
if DJANGO_2_0:
163+
middleware = conf.settings.MIDDLEWARE
164+
else:
165+
middleware = conf.settings.MIDDLEWARE_CLASSES
166+
# adding two dummy middlewares
167+
temprory_middelware = "django.utils.deprecation.MiddlewareMixin"
168+
middleware.append(temprory_middelware)
169+
middleware.append(temprory_middelware)
170+
171+
middleware_position = 1
172+
_django_instrumentor.instrument(
173+
middleware_position=middleware_position
174+
)
175+
self.assertEqual(
176+
middleware[middleware_position],
177+
"opentelemetry.instrumentation.django.middleware.otel_middleware._DjangoMiddleware",
178+
)
179+
180+
def test_middleware_added_at_position_if_wrong_position(self):
181+
_django_instrumentor.uninstrument()
182+
if DJANGO_2_0:
183+
middleware = conf.settings.MIDDLEWARE
184+
else:
185+
middleware = conf.settings.MIDDLEWARE_CLASSES
186+
# adding middleware
187+
temprory_middelware = "django.utils.deprecation.MiddlewareMixin"
188+
middleware.append(temprory_middelware)
189+
middleware_position = (
190+
756 # wrong position out of bound of middleware length
191+
)
192+
_django_instrumentor.instrument(
193+
middleware_position=middleware_position
194+
)
195+
self.assertEqual(
196+
middleware[0],
197+
"opentelemetry.instrumentation.django.middleware.otel_middleware._DjangoMiddleware",
198+
)
199+
160200
def test_templated_route_get(self):
161201
Client().get("/route/2020/template/")
162202

instrumentation/opentelemetry-instrumentation-django/tests/test_sqlcommenter.py

+31
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,37 @@ def test_middleware_added(self, sqlcommenter_middleware):
7272
in middleware
7373
)
7474

75+
@patch(
76+
"opentelemetry.instrumentation.django.middleware.sqlcommenter_middleware.SqlCommenter"
77+
)
78+
def test_middleware_added_at_position(self, sqlcommenter_middleware):
79+
_django_instrumentor.uninstrument()
80+
if DJANGO_2_0:
81+
middleware = conf.settings.MIDDLEWARE
82+
else:
83+
middleware = conf.settings.MIDDLEWARE_CLASSES
84+
85+
# adding two dummy middlewares
86+
temprory_middelware = "django.utils.deprecation.MiddlewareMixin"
87+
middleware.append(temprory_middelware)
88+
middleware.append(temprory_middelware)
89+
90+
middleware_position = 1
91+
_django_instrumentor.instrument(
92+
is_sql_commentor_enabled=True,
93+
middleware_position=middleware_position,
94+
)
95+
instance = sqlcommenter_middleware.return_value
96+
instance.get_response = HttpResponse()
97+
self.assertEqual(
98+
middleware[middleware_position],
99+
"opentelemetry.instrumentation.django.middleware.otel_middleware._DjangoMiddleware",
100+
)
101+
self.assertEqual(
102+
middleware[middleware_position + 1],
103+
"opentelemetry.instrumentation.django.middleware.sqlcommenter_middleware.SqlCommenter",
104+
)
105+
75106
@patch(
76107
"opentelemetry.instrumentation.django.middleware.sqlcommenter_middleware._get_opentelemetry_values"
77108
)

0 commit comments

Comments
 (0)