|
11 | 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 | 12 | # See the License for the specific language governing permissions and
|
13 | 13 | # limitations under the License.
|
14 |
| -# pylint: disable=too-many-lines |
15 |
| - |
16 | 14 | import unittest
|
17 | 15 | from timeit import default_timer
|
18 | 16 | from unittest.mock import patch
|
19 | 17 |
|
20 | 18 | import fastapi
|
21 | 19 | from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
|
22 |
| -from fastapi.responses import JSONResponse |
23 | 20 | from fastapi.testclient import TestClient
|
24 | 21 |
|
25 | 22 | import opentelemetry.instrumentation.fastapi as otel_fastapi
|
|
31 | 28 | )
|
32 | 29 | from opentelemetry.sdk.resources import Resource
|
33 | 30 | from opentelemetry.semconv.trace import SpanAttributes
|
34 |
| -from opentelemetry.test.globals_test import reset_trace_globals |
35 | 31 | from opentelemetry.test.test_base import TestBase
|
36 | 32 | from opentelemetry.util.http import (
|
37 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS, |
38 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST, |
39 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE, |
40 | 33 | _active_requests_count_attrs,
|
41 | 34 | _duration_attrs,
|
42 | 35 | get_excluded_urls,
|
@@ -701,345 +694,3 @@ def test_mark_span_internal_in_presence_of_span_from_other_framework(self):
|
701 | 694 | self.assertEqual(
|
702 | 695 | parent_span.context.span_id, span_list[3].context.span_id
|
703 | 696 | )
|
704 |
| - |
705 |
| - |
706 |
| -@patch.dict( |
707 |
| - "os.environ", |
708 |
| - { |
709 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*", |
710 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*", |
711 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*", |
712 |
| - }, |
713 |
| -) |
714 |
| -class TestHTTPAppWithCustomHeaders(TestBase): |
715 |
| - def setUp(self): |
716 |
| - super().setUp() |
717 |
| - self.app = self._create_app() |
718 |
| - otel_fastapi.FastAPIInstrumentor().instrument_app(self.app) |
719 |
| - self.client = TestClient(self.app) |
720 |
| - |
721 |
| - def tearDown(self) -> None: |
722 |
| - super().tearDown() |
723 |
| - with self.disable_logging(): |
724 |
| - otel_fastapi.FastAPIInstrumentor().uninstrument_app(self.app) |
725 |
| - |
726 |
| - @staticmethod |
727 |
| - def _create_app(): |
728 |
| - app = fastapi.FastAPI() |
729 |
| - |
730 |
| - @app.get("/foobar") |
731 |
| - async def _(): |
732 |
| - headers = { |
733 |
| - "custom-test-header-1": "test-header-value-1", |
734 |
| - "custom-test-header-2": "test-header-value-2", |
735 |
| - "my-custom-regex-header-1": "my-custom-regex-value-1,my-custom-regex-value-2", |
736 |
| - "My-Custom-Regex-Header-2": "my-custom-regex-value-3,my-custom-regex-value-4", |
737 |
| - "My-Secret-Header": "My Secret Value", |
738 |
| - } |
739 |
| - content = {"message": "hello world"} |
740 |
| - return JSONResponse(content=content, headers=headers) |
741 |
| - |
742 |
| - return app |
743 |
| - |
744 |
| - def test_http_custom_request_headers_in_span_attributes(self): |
745 |
| - expected = { |
746 |
| - "http.request.header.custom_test_header_1": ( |
747 |
| - "test-header-value-1", |
748 |
| - ), |
749 |
| - "http.request.header.custom_test_header_2": ( |
750 |
| - "test-header-value-2", |
751 |
| - ), |
752 |
| - "http.request.header.regex_test_header_1": ("Regex Test Value 1",), |
753 |
| - "http.request.header.regex_test_header_2": ( |
754 |
| - "RegexTestValue2,RegexTestValue3", |
755 |
| - ), |
756 |
| - "http.request.header.my_secret_header": ("[REDACTED]",), |
757 |
| - } |
758 |
| - resp = self.client.get( |
759 |
| - "/foobar", |
760 |
| - headers={ |
761 |
| - "custom-test-header-1": "test-header-value-1", |
762 |
| - "custom-test-header-2": "test-header-value-2", |
763 |
| - "Regex-Test-Header-1": "Regex Test Value 1", |
764 |
| - "regex-test-header-2": "RegexTestValue2,RegexTestValue3", |
765 |
| - "My-Secret-Header": "My Secret Value", |
766 |
| - }, |
767 |
| - ) |
768 |
| - self.assertEqual(200, resp.status_code) |
769 |
| - span_list = self.memory_exporter.get_finished_spans() |
770 |
| - self.assertEqual(len(span_list), 3) |
771 |
| - |
772 |
| - server_span = [ |
773 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
774 |
| - ][0] |
775 |
| - |
776 |
| - self.assertSpanHasAttributes(server_span, expected) |
777 |
| - |
778 |
| - def test_http_custom_request_headers_not_in_span_attributes(self): |
779 |
| - not_expected = { |
780 |
| - "http.request.header.custom_test_header_3": ( |
781 |
| - "test-header-value-3", |
782 |
| - ), |
783 |
| - } |
784 |
| - resp = self.client.get( |
785 |
| - "/foobar", |
786 |
| - headers={ |
787 |
| - "custom-test-header-1": "test-header-value-1", |
788 |
| - "custom-test-header-2": "test-header-value-2", |
789 |
| - "Regex-Test-Header-1": "Regex Test Value 1", |
790 |
| - "regex-test-header-2": "RegexTestValue2,RegexTestValue3", |
791 |
| - "My-Secret-Header": "My Secret Value", |
792 |
| - }, |
793 |
| - ) |
794 |
| - self.assertEqual(200, resp.status_code) |
795 |
| - span_list = self.memory_exporter.get_finished_spans() |
796 |
| - self.assertEqual(len(span_list), 3) |
797 |
| - |
798 |
| - server_span = [ |
799 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
800 |
| - ][0] |
801 |
| - |
802 |
| - for key, _ in not_expected.items(): |
803 |
| - self.assertNotIn(key, server_span.attributes) |
804 |
| - |
805 |
| - def test_http_custom_response_headers_in_span_attributes(self): |
806 |
| - expected = { |
807 |
| - "http.response.header.custom_test_header_1": ( |
808 |
| - "test-header-value-1", |
809 |
| - ), |
810 |
| - "http.response.header.custom_test_header_2": ( |
811 |
| - "test-header-value-2", |
812 |
| - ), |
813 |
| - "http.response.header.my_custom_regex_header_1": ( |
814 |
| - "my-custom-regex-value-1,my-custom-regex-value-2", |
815 |
| - ), |
816 |
| - "http.response.header.my_custom_regex_header_2": ( |
817 |
| - "my-custom-regex-value-3,my-custom-regex-value-4", |
818 |
| - ), |
819 |
| - "http.response.header.my_secret_header": ("[REDACTED]",), |
820 |
| - } |
821 |
| - resp = self.client.get("/foobar") |
822 |
| - self.assertEqual(200, resp.status_code) |
823 |
| - span_list = self.memory_exporter.get_finished_spans() |
824 |
| - self.assertEqual(len(span_list), 3) |
825 |
| - |
826 |
| - server_span = [ |
827 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
828 |
| - ][0] |
829 |
| - self.assertSpanHasAttributes(server_span, expected) |
830 |
| - |
831 |
| - def test_http_custom_response_headers_not_in_span_attributes(self): |
832 |
| - not_expected = { |
833 |
| - "http.response.header.custom_test_header_3": ( |
834 |
| - "test-header-value-3", |
835 |
| - ), |
836 |
| - } |
837 |
| - resp = self.client.get("/foobar") |
838 |
| - self.assertEqual(200, resp.status_code) |
839 |
| - span_list = self.memory_exporter.get_finished_spans() |
840 |
| - self.assertEqual(len(span_list), 3) |
841 |
| - |
842 |
| - server_span = [ |
843 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
844 |
| - ][0] |
845 |
| - |
846 |
| - for key, _ in not_expected.items(): |
847 |
| - self.assertNotIn(key, server_span.attributes) |
848 |
| - |
849 |
| - |
850 |
| -@patch.dict( |
851 |
| - "os.environ", |
852 |
| - { |
853 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*", |
854 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*", |
855 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,my-custom-regex-header-.*,invalid-regex-header-.*,.*my-secret.*", |
856 |
| - }, |
857 |
| -) |
858 |
| -class TestWebSocketAppWithCustomHeaders(TestBase): |
859 |
| - def setUp(self): |
860 |
| - super().setUp() |
861 |
| - self.app = self._create_app() |
862 |
| - otel_fastapi.FastAPIInstrumentor().instrument_app(self.app) |
863 |
| - self.client = TestClient(self.app) |
864 |
| - |
865 |
| - def tearDown(self) -> None: |
866 |
| - super().tearDown() |
867 |
| - with self.disable_logging(): |
868 |
| - otel_fastapi.FastAPIInstrumentor().uninstrument_app(self.app) |
869 |
| - |
870 |
| - @staticmethod |
871 |
| - def _create_app(): |
872 |
| - app = fastapi.FastAPI() |
873 |
| - |
874 |
| - @app.websocket("/foobar_web") |
875 |
| - async def _(websocket: fastapi.WebSocket): |
876 |
| - message = await websocket.receive() |
877 |
| - if message.get("type") == "websocket.connect": |
878 |
| - await websocket.send( |
879 |
| - { |
880 |
| - "type": "websocket.accept", |
881 |
| - "headers": [ |
882 |
| - (b"custom-test-header-1", b"test-header-value-1"), |
883 |
| - (b"custom-test-header-2", b"test-header-value-2"), |
884 |
| - (b"Regex-Test-Header-1", b"Regex Test Value 1"), |
885 |
| - ( |
886 |
| - b"regex-test-header-2", |
887 |
| - b"RegexTestValue2,RegexTestValue3", |
888 |
| - ), |
889 |
| - (b"My-Secret-Header", b"My Secret Value"), |
890 |
| - ], |
891 |
| - } |
892 |
| - ) |
893 |
| - await websocket.send_json({"message": "hello world"}) |
894 |
| - await websocket.close() |
895 |
| - if message.get("type") == "websocket.disconnect": |
896 |
| - pass |
897 |
| - |
898 |
| - return app |
899 |
| - |
900 |
| - def test_web_socket_custom_request_headers_in_span_attributes(self): |
901 |
| - expected = { |
902 |
| - "http.request.header.custom_test_header_1": ( |
903 |
| - "test-header-value-1", |
904 |
| - ), |
905 |
| - "http.request.header.custom_test_header_2": ( |
906 |
| - "test-header-value-2", |
907 |
| - ), |
908 |
| - } |
909 |
| - |
910 |
| - with self.client.websocket_connect( |
911 |
| - "/foobar_web", |
912 |
| - headers={ |
913 |
| - "custom-test-header-1": "test-header-value-1", |
914 |
| - "custom-test-header-2": "test-header-value-2", |
915 |
| - }, |
916 |
| - ) as websocket: |
917 |
| - data = websocket.receive_json() |
918 |
| - self.assertEqual(data, {"message": "hello world"}) |
919 |
| - |
920 |
| - span_list = self.memory_exporter.get_finished_spans() |
921 |
| - self.assertEqual(len(span_list), 5) |
922 |
| - |
923 |
| - server_span = [ |
924 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
925 |
| - ][0] |
926 |
| - |
927 |
| - self.assertSpanHasAttributes(server_span, expected) |
928 |
| - |
929 |
| - @patch.dict( |
930 |
| - "os.environ", |
931 |
| - { |
932 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS: ".*my-secret.*", |
933 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3,Regex-Test-Header-.*,Regex-Invalid-Test-Header-.*,.*my-secret.*", |
934 |
| - }, |
935 |
| - ) |
936 |
| - def test_web_socket_custom_request_headers_not_in_span_attributes(self): |
937 |
| - not_expected = { |
938 |
| - "http.request.header.custom_test_header_3": ( |
939 |
| - "test-header-value-3", |
940 |
| - ), |
941 |
| - } |
942 |
| - |
943 |
| - with self.client.websocket_connect( |
944 |
| - "/foobar_web", |
945 |
| - headers={ |
946 |
| - "custom-test-header-1": "test-header-value-1", |
947 |
| - "custom-test-header-2": "test-header-value-2", |
948 |
| - }, |
949 |
| - ) as websocket: |
950 |
| - data = websocket.receive_json() |
951 |
| - self.assertEqual(data, {"message": "hello world"}) |
952 |
| - |
953 |
| - span_list = self.memory_exporter.get_finished_spans() |
954 |
| - self.assertEqual(len(span_list), 5) |
955 |
| - |
956 |
| - server_span = [ |
957 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
958 |
| - ][0] |
959 |
| - |
960 |
| - for key, _ in not_expected.items(): |
961 |
| - self.assertNotIn(key, server_span.attributes) |
962 |
| - |
963 |
| - def test_web_socket_custom_response_headers_in_span_attributes(self): |
964 |
| - expected = { |
965 |
| - "http.response.header.custom_test_header_1": ( |
966 |
| - "test-header-value-1", |
967 |
| - ), |
968 |
| - "http.response.header.custom_test_header_2": ( |
969 |
| - "test-header-value-2", |
970 |
| - ), |
971 |
| - } |
972 |
| - |
973 |
| - with self.client.websocket_connect("/foobar_web") as websocket: |
974 |
| - data = websocket.receive_json() |
975 |
| - self.assertEqual(data, {"message": "hello world"}) |
976 |
| - |
977 |
| - span_list = self.memory_exporter.get_finished_spans() |
978 |
| - self.assertEqual(len(span_list), 5) |
979 |
| - |
980 |
| - server_span = [ |
981 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
982 |
| - ][0] |
983 |
| - |
984 |
| - self.assertSpanHasAttributes(server_span, expected) |
985 |
| - |
986 |
| - def test_web_socket_custom_response_headers_not_in_span_attributes(self): |
987 |
| - not_expected = { |
988 |
| - "http.response.header.custom_test_header_3": ( |
989 |
| - "test-header-value-3", |
990 |
| - ), |
991 |
| - } |
992 |
| - |
993 |
| - with self.client.websocket_connect("/foobar_web") as websocket: |
994 |
| - data = websocket.receive_json() |
995 |
| - self.assertEqual(data, {"message": "hello world"}) |
996 |
| - |
997 |
| - span_list = self.memory_exporter.get_finished_spans() |
998 |
| - self.assertEqual(len(span_list), 5) |
999 |
| - |
1000 |
| - server_span = [ |
1001 |
| - span for span in span_list if span.kind == trace.SpanKind.SERVER |
1002 |
| - ][0] |
1003 |
| - |
1004 |
| - for key, _ in not_expected.items(): |
1005 |
| - self.assertNotIn(key, server_span.attributes) |
1006 |
| - |
1007 |
| - |
1008 |
| -@patch.dict( |
1009 |
| - "os.environ", |
1010 |
| - { |
1011 |
| - OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST: "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3", |
1012 |
| - }, |
1013 |
| -) |
1014 |
| -class TestNonRecordingSpanWithCustomHeaders(TestBase): |
1015 |
| - def setUp(self): |
1016 |
| - super().setUp() |
1017 |
| - self.app = fastapi.FastAPI() |
1018 |
| - |
1019 |
| - @self.app.get("/foobar") |
1020 |
| - async def _(): |
1021 |
| - return {"message": "hello world"} |
1022 |
| - |
1023 |
| - reset_trace_globals() |
1024 |
| - tracer_provider = trace.NoOpTracerProvider() |
1025 |
| - trace.set_tracer_provider(tracer_provider=tracer_provider) |
1026 |
| - |
1027 |
| - self._instrumentor = otel_fastapi.FastAPIInstrumentor() |
1028 |
| - self._instrumentor.instrument_app(self.app) |
1029 |
| - self.client = TestClient(self.app) |
1030 |
| - |
1031 |
| - def tearDown(self) -> None: |
1032 |
| - super().tearDown() |
1033 |
| - with self.disable_logging(): |
1034 |
| - self._instrumentor.uninstrument_app(self.app) |
1035 |
| - |
1036 |
| - def test_custom_header_not_present_in_non_recording_span(self): |
1037 |
| - resp = self.client.get( |
1038 |
| - "/foobar", |
1039 |
| - headers={ |
1040 |
| - "custom-test-header-1": "test-header-value-1", |
1041 |
| - }, |
1042 |
| - ) |
1043 |
| - self.assertEqual(200, resp.status_code) |
1044 |
| - span_list = self.memory_exporter.get_finished_spans() |
1045 |
| - self.assertEqual(len(span_list), 0) |
0 commit comments