| 
23 | 23 | from django.http import HttpRequest, HttpResponse  | 
24 | 24 | from django.test.client import Client  | 
25 | 25 | from django.test.utils import setup_test_environment, teardown_test_environment  | 
 | 26 | +from django.core.handlers.wsgi import WSGIRequest  | 
26 | 27 | 
 
  | 
27 | 28 | from opentelemetry import trace  | 
28 | 29 | from opentelemetry.instrumentation._semconv import (  | 
@@ -1019,6 +1020,84 @@ def tearDownClass(cls):  | 
1019 | 1020 |         super().tearDownClass()  | 
1020 | 1021 |         conf.settings = conf.LazySettings()  | 
1021 | 1022 | 
 
  | 
 | 1023 | +    @staticmethod  | 
 | 1024 | +    def _format_request_objects_in_headers(attributes):  | 
 | 1025 | +        for key, value_list in list(attributes.items()):  | 
 | 1026 | +            new_values = []  | 
 | 1027 | +            for value in value_list:  | 
 | 1028 | +                if hasattr(value, '__class__'):  | 
 | 1029 | +                    if value.__class__.__name__ in ('HttpRequest', 'WSGIRequest'):  | 
 | 1030 | +                        try:  | 
 | 1031 | +                            method = getattr(value, 'method', 'UNKNOWN')  | 
 | 1032 | +                            path = getattr(value, 'path', 'UNKNOWN')  | 
 | 1033 | +                            new_values.append(f"HttpRequest({method} {path})")  | 
 | 1034 | +                        except (AttributeError, ValueError, TypeError):  | 
 | 1035 | +                            new_values.append("HttpRequest(...)")  | 
 | 1036 | +                    else:  | 
 | 1037 | +                        new_values.append(value)  | 
 | 1038 | +                else:  | 
 | 1039 | +                    new_values.append(value)  | 
 | 1040 | +            attributes[key] = new_values  | 
 | 1041 | +        return attributes  | 
 | 1042 | + | 
 | 1043 | +    def test_wsgi_request_in_header_is_properly_formatted(self):  | 
 | 1044 | +        mock_wsgi_request = Mock(spec=WSGIRequest)  | 
 | 1045 | +        mock_wsgi_request.method = "GET"  | 
 | 1046 | +        mock_wsgi_request.path = "/test/path"  | 
 | 1047 | +        mock_wsgi_request.__class__.__name__ = "WSGIRequest"  | 
 | 1048 | + | 
 | 1049 | +        input_attributes = {"http.request.header.test_wsgirequest_header": [mock_wsgi_request]}  | 
 | 1050 | +        expected_attributes = {"http.request.header.test_wsgirequest_header": ["HttpRequest(GET /test/path)"]}  | 
 | 1051 | + | 
 | 1052 | +        formatted_attributes = TestMiddlewareWsgiWithCustomHeaders._format_request_objects_in_headers(input_attributes)  | 
 | 1053 | + | 
 | 1054 | +        self.assertEqual(formatted_attributes, expected_attributes)  | 
 | 1055 | + | 
 | 1056 | +    def test_wsgi_request_handles_extraction_error(self):  | 
 | 1057 | +        mock_wsgi_request = Mock(spec=WSGIRequest)  | 
 | 1058 | +        mock_wsgi_request.__class__.__name__ = "WSGIRequest"  | 
 | 1059 | + | 
 | 1060 | +        type(mock_wsgi_request).method = property(lambda self: (_ for _ in ()).throw(ValueError("Test error")))  | 
 | 1061 | + | 
 | 1062 | +        input_attributes = {"http.request.header.test_wsgirequest_header": [mock_wsgi_request]}  | 
 | 1063 | +        expected_attributes = {"http.request.header.test_wsgirequest_header": ["HttpRequest(...)"]}  | 
 | 1064 | + | 
 | 1065 | +        formatted_attributes = TestMiddlewareWsgiWithCustomHeaders._format_request_objects_in_headers(input_attributes)  | 
 | 1066 | + | 
 | 1067 | +        self.assertEqual(formatted_attributes, expected_attributes)  | 
 | 1068 | + | 
 | 1069 | +    def test_handles_http_request_as_well(self):  | 
 | 1070 | +        mock_http_request = Mock(spec=HttpRequest)  | 
 | 1071 | +        mock_http_request.method = "POST"  | 
 | 1072 | +        mock_http_request.path = "/api/data"  | 
 | 1073 | +        mock_http_request.__class__.__name__ = "HttpRequest"  | 
 | 1074 | + | 
 | 1075 | +        input_attributes = {"http.request.header.test_httprequest_header": [mock_http_request]}  | 
 | 1076 | +        expected_attributes = {"http.request.header.test_httprequest_header": ["HttpRequest(POST /api/data)"]}  | 
 | 1077 | + | 
 | 1078 | +        formatted_attributes = TestMiddlewareWsgiWithCustomHeaders._format_request_objects_in_headers(input_attributes)  | 
 | 1079 | + | 
 | 1080 | +        self.assertEqual(formatted_attributes, expected_attributes)  | 
 | 1081 | + | 
 | 1082 | +    def test_regular_header_values_are_preserved(self):  | 
 | 1083 | +        mock_wsgi_request = Mock(spec=WSGIRequest)  | 
 | 1084 | +        mock_wsgi_request.method = "GET"  | 
 | 1085 | +        mock_wsgi_request.path = "/test/path"  | 
 | 1086 | +        mock_wsgi_request.__class__.__name__ = "WSGIRequest"  | 
 | 1087 | + | 
 | 1088 | +        input_attributes = {  | 
 | 1089 | +            "http.request.header.test_wsgirequest_header": [mock_wsgi_request],  | 
 | 1090 | +            "http.request.header.test_regular_header": ["regular-value"]  | 
 | 1091 | +        }  | 
 | 1092 | +        expected_attributes = {  | 
 | 1093 | +            "http.request.header.test_wsgirequest_header": ["HttpRequest(GET /test/path)"],  | 
 | 1094 | +            "http.request.header.test_regular_header": ["regular-value"]  | 
 | 1095 | +        }  | 
 | 1096 | + | 
 | 1097 | +        formatted_attributes = TestMiddlewareWsgiWithCustomHeaders._format_request_objects_in_headers(input_attributes)  | 
 | 1098 | + | 
 | 1099 | +        self.assertEqual(formatted_attributes, expected_attributes)  | 
 | 1100 | + | 
1022 | 1101 |     def test_http_custom_request_headers_in_span_attributes(self):  | 
1023 | 1102 |         expected = {  | 
1024 | 1103 |             "http.request.header.custom_test_header_1": (  | 
 | 
0 commit comments