Skip to content

Commit 66c0e27

Browse files
Add docker test_django_functional
1 parent cef7092 commit 66c0e27

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from sys import modules
16+
17+
from django import VERSION, conf
18+
from django.http import HttpResponse
19+
from django.test.client import Client
20+
from django.test.utils import setup_test_environment, teardown_test_environment
21+
22+
from opentelemetry import metrics as metrics_api
23+
from opentelemetry.instrumentation.django import DjangoInstrumentor
24+
from opentelemetry.sdk.metrics import AlwaysOnExemplarFilter
25+
from opentelemetry.test.globals_test import (
26+
reset_metrics_globals,
27+
)
28+
from opentelemetry.test.test_base import TestBase
29+
from opentelemetry.trace import (
30+
INVALID_SPAN_ID,
31+
INVALID_TRACE_ID,
32+
)
33+
34+
DJANGO_2_0 = VERSION >= (2, 0)
35+
36+
if DJANGO_2_0:
37+
from django.urls import re_path
38+
else:
39+
from django.conf.urls import url as re_path
40+
41+
42+
def view_test_route(request): # pylint: disable=unused-argument
43+
return HttpResponse("Test response")
44+
45+
46+
urlpatterns = [
47+
re_path(r"^test/", view_test_route),
48+
]
49+
50+
51+
class TestFunctionalDjango(TestBase):
52+
def setUp(self):
53+
super().setUp()
54+
self.memory_exporter.clear()
55+
# This is done because set_meter_provider cannot override the
56+
# current meter provider.
57+
reset_metrics_globals()
58+
(
59+
self.meter_provider,
60+
self.memory_metrics_reader,
61+
) = self.create_meter_provider(
62+
exemplar_filter=AlwaysOnExemplarFilter(),
63+
)
64+
metrics_api.set_meter_provider(self.meter_provider)
65+
66+
conf.settings.configure(
67+
ROOT_URLCONF=modules[__name__],
68+
DATABASES={
69+
"default": {},
70+
},
71+
)
72+
73+
setup_test_environment()
74+
self._client = Client()
75+
76+
DjangoInstrumentor().instrument(
77+
meter_provider=self.meter_provider,
78+
)
79+
80+
def tearDown(self):
81+
DjangoInstrumentor().uninstrument()
82+
teardown_test_environment()
83+
conf.settings = conf.LazySettings()
84+
super().tearDown()
85+
86+
def test_duration_metrics_exemplars(self):
87+
"""Should generate exemplars with trace and span IDs for Django HTTP requests."""
88+
self._client.get("/test/")
89+
self._client.get("/test/")
90+
self._client.get("/test/")
91+
92+
metrics_data = self.memory_metrics_reader.get_metrics_data()
93+
self.assertIsNotNone(metrics_data)
94+
self.assertTrue(len(metrics_data.resource_metrics) > 0)
95+
96+
duration_metric = None
97+
metric_names = []
98+
for resource_metric in metrics_data.resource_metrics:
99+
for scope_metric in resource_metric.scope_metrics:
100+
for metric in scope_metric.metrics:
101+
metric_names.append(metric.name)
102+
if metric.name in [
103+
"http.server.request.duration",
104+
"http.server.duration",
105+
]:
106+
duration_metric = metric
107+
break
108+
if duration_metric:
109+
break
110+
if duration_metric:
111+
break
112+
113+
self.assertIsNotNone(duration_metric)
114+
data_points = list(duration_metric.data.data_points)
115+
self.assertTrue(len(data_points) > 0)
116+
117+
exemplar_count = 0
118+
for data_point in data_points:
119+
if hasattr(data_point, "exemplars") and data_point.exemplars:
120+
for exemplar in data_point.exemplars:
121+
exemplar_count += 1
122+
# Exemplar has required fields and valid span context
123+
self.assertIsNotNone(exemplar.value)
124+
self.assertIsNotNone(exemplar.time_unix_nano)
125+
self.assertIsNotNone(exemplar.span_id)
126+
self.assertNotEqual(exemplar.span_id, INVALID_SPAN_ID)
127+
self.assertIsNotNone(exemplar.trace_id)
128+
self.assertNotEqual(exemplar.trace_id, INVALID_TRACE_ID)
129+
130+
# Trace and span ID of exemplar are part of finished spans
131+
finished_spans = self.memory_exporter.get_finished_spans()
132+
finished_span_ids = [
133+
span.context.span_id for span in finished_spans
134+
]
135+
finished_trace_ids = [
136+
span.context.trace_id for span in finished_spans
137+
]
138+
self.assertIn(exemplar.span_id, finished_span_ids)
139+
self.assertIn(exemplar.trace_id, finished_trace_ids)
140+
141+
# At least one exemplar was generated
142+
self.assertGreater(exemplar_count, 0)

tests/opentelemetry-docker-tests/tests/test-requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ click-repl==0.3.0
1717
cryptography==44.0.1
1818
Deprecated==1.2.14
1919
distro==1.9.0
20+
Django==4.2.17
2021
dnspython==2.6.1
2122
docker==5.0.3
2223
docker-compose==1.29.2

tox.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,7 @@ deps =
10081008
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-kafka-python
10091009
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-confluent-kafka
10101010
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-dbapi
1011+
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-django
10111012
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-mysql
10121013
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-mysqlclient
10131014
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-psycopg
@@ -1019,6 +1020,7 @@ deps =
10191020
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-aiopg
10201021
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-redis
10211022
-e {toxinidir}/instrumentation/opentelemetry-instrumentation-remoulade
1023+
-e {toxinidir}/util/opentelemetry-util-http
10221024
opentelemetry-exporter-opencensus@{env:CORE_REPO}\#egg=opentelemetry-exporter-opencensus&subdirectory=exporter/opentelemetry-exporter-opencensus
10231025

10241026
changedir =

0 commit comments

Comments
 (0)