|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 | 14 |
|
| 15 | +from os import environ |
15 | 16 | from sys import modules
|
16 | 17 | from unittest.mock import Mock, patch
|
17 | 18 |
|
|
25 | 26 | from opentelemetry.test.test_base import TestBase
|
26 | 27 | from opentelemetry.test.wsgitestutil import WsgiTestBase
|
27 | 28 | from opentelemetry.trace import SpanKind, StatusCode
|
28 |
| -from opentelemetry.util.http import get_excluded_urls, get_traced_request_attrs |
| 29 | +from opentelemetry.util.http import ( |
| 30 | + ENV_HTTP_TRACE_RESPONSE_HEADER, |
| 31 | + get_excluded_urls, |
| 32 | + get_trace_response_headers, |
| 33 | + get_traced_request_attrs, |
| 34 | +) |
29 | 35 |
|
30 | 36 | # pylint: disable=import-error
|
31 | 37 | from .views import (
|
|
36 | 42 | route_span_name,
|
37 | 43 | traced,
|
38 | 44 | traced_template,
|
| 45 | + with_response_header, |
39 | 46 | )
|
40 | 47 |
|
41 | 48 | DJANGO_2_2 = VERSION >= (2, 2)
|
|
47 | 54 | url(r"^excluded_arg/", excluded),
|
48 | 55 | url(r"^excluded_noarg/", excluded_noarg),
|
49 | 56 | url(r"^excluded_noarg2/", excluded_noarg2),
|
| 57 | + url(r"^response_header/", with_response_header), |
50 | 58 | url(r"^span_name/([0-9]{4})/$", route_span_name),
|
51 | 59 | ]
|
52 | 60 | _django_instrumentor = DjangoInstrumentor()
|
@@ -268,3 +276,76 @@ def test_traced_request_attrs(self):
|
268 | 276 | self.assertEqual(span.attributes["path_info"], "/span_name/1234/")
|
269 | 277 | self.assertEqual(span.attributes["content_type"], "test/ct")
|
270 | 278 | self.assertNotIn("non_existing_variable", span.attributes)
|
| 279 | + |
| 280 | + def test_trace_response_header(self): |
| 281 | + original_env_var = environ.pop(ENV_HTTP_TRACE_RESPONSE_HEADER, None) |
| 282 | + response = Client().get("/span_name/1234/") |
| 283 | + self.assertNotIn("Server-Timing", response._headers) |
| 284 | + self.memory_exporter.clear() |
| 285 | + |
| 286 | + for header in ["Server-Timing", "traceresponse"]: |
| 287 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = header |
| 288 | + |
| 289 | + response = Client().get("/span_name/1234/") |
| 290 | + span = self.memory_exporter.get_finished_spans()[0] |
| 291 | + headers = get_trace_response_headers(span) |
| 292 | + self.assertEqual(len(headers), 2) |
| 293 | + |
| 294 | + access_control_header = headers[0] |
| 295 | + response_header = headers[1] |
| 296 | + |
| 297 | + self.assertIn(header.lower(), response._headers) |
| 298 | + self.assertEqual( |
| 299 | + response._headers["access-control-expose-headers"][0], |
| 300 | + access_control_header[0], |
| 301 | + ) |
| 302 | + self.assertEqual( |
| 303 | + response._headers["access-control-expose-headers"][1], |
| 304 | + access_control_header[1], |
| 305 | + ) |
| 306 | + self.assertEqual( |
| 307 | + response._headers[header.lower()][0], response_header[0] |
| 308 | + ) |
| 309 | + self.assertEqual( |
| 310 | + response._headers[header.lower()][1], response_header[1] |
| 311 | + ) |
| 312 | + |
| 313 | + self.memory_exporter.clear() |
| 314 | + del environ[ENV_HTTP_TRACE_RESPONSE_HEADER] |
| 315 | + |
| 316 | + if original_env_var: |
| 317 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = original_env_var |
| 318 | + |
| 319 | + def test_trace_response_header_pre_existing_header(self): |
| 320 | + original_env_var = environ.pop(ENV_HTTP_TRACE_RESPONSE_HEADER, None) |
| 321 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = "Server-Timing" |
| 322 | + response = Client().get("/response_header/") |
| 323 | + |
| 324 | + span = self.memory_exporter.get_finished_spans()[0] |
| 325 | + headers = get_trace_response_headers(span) |
| 326 | + self.assertEqual(len(headers), 2) |
| 327 | + access_control_header = headers[0] |
| 328 | + response_header = headers[1] |
| 329 | + |
| 330 | + self.assertIn("server-timing", response._headers) |
| 331 | + self.assertEqual( |
| 332 | + response._headers["access-control-expose-headers"][0], |
| 333 | + access_control_header[0], |
| 334 | + ) |
| 335 | + self.assertEqual( |
| 336 | + response._headers["access-control-expose-headers"][1], |
| 337 | + "X-Test-Header, Server-Timing", |
| 338 | + ) |
| 339 | + self.assertEqual( |
| 340 | + response._headers["server-timing"][0], response_header[0] |
| 341 | + ) |
| 342 | + self.assertEqual( |
| 343 | + response._headers["server-timing"][1], |
| 344 | + "abc; val=1, " + response_header[1], |
| 345 | + ) |
| 346 | + |
| 347 | + self.memory_exporter.clear() |
| 348 | + del environ[ENV_HTTP_TRACE_RESPONSE_HEADER] |
| 349 | + |
| 350 | + if original_env_var: |
| 351 | + environ[ENV_HTTP_TRACE_RESPONSE_HEADER] = original_env_var |
0 commit comments