def test_wsgi_metrics(self): app = otel_wsgi.OpenTelemetryMiddleware(error_wsgi_unhandled) self.assertRaises(ValueError, app, self.environ, self.start_response) self.assertRaises(ValueError, app, self.environ, self.start_response) self.assertRaises(ValueError, app, self.environ, self.start_response) metrics_list = self.memory_metrics_reader.get_metrics_data() number_data_point_seen = False histogram_data_point_seen = False self.assertTrue(len(metrics_list.resource_metrics) != 0) for resource_metric in metrics_list.resource_metrics: self.assertTrue(len(resource_metric.scope_metrics) != 0) for scope_metric in resource_metric.scope_metrics: self.assertTrue(len(scope_metric.metrics) != 0) for metric in scope_metric.metrics: self.assertIn(metric.name, _expected_metric_names) data_points = list(metric.data.data_points) self.assertEqual(len(data_points), 1) for point in data_points: if isinstance(point, HistogramDataPoint): self.assertEqual(point.count, 3) histogram_data_point_seen = True if isinstance(point, NumberDataPoint): number_data_point_seen = True for attr in point.attributes: self.assertIn( attr, _recommended_attrs[metric.name] ) self.assertTrue(number_data_point_seen and histogram_data_point_seen)
def test_mark_span_internal_in_presence_of_span_from_other_framework(self): tracer_provider, exporter = TestBase.create_tracer_provider() tracer = tracer_provider.get_tracer(__name__) with tracer.start_as_current_span( "test", kind=trace_api.SpanKind.SERVER ) as parent_span: app = otel_wsgi.OpenTelemetryMiddleware( simple_wsgi, tracer_provider=tracer_provider ) response = app(self.environ, self.start_response) while True: try: value = next(response) self.assertEqual(value, b"*") except StopIteration: break span_list = exporter.get_finished_spans() self.assertEqual(trace_api.SpanKind.INTERNAL, span_list[0].kind) self.assertEqual(trace_api.SpanKind.SERVER, parent_span.kind) # internal span should be child of the parent span we have provided self.assertEqual( parent_span.context.span_id, span_list[0].parent.span_id )
def test_wsgi_internal_error(self): app = otel_wsgi.OpenTelemetryMiddleware(error_wsgi_unhandled) self.assertRaises(ValueError, app, self.environ, self.start_response) span_list = self.memory_exporter.get_finished_spans() self.assertEqual(len(span_list), 1) self.assertEqual( span_list[0].status.canonical_code, StatusCanonicalCode.INTERNAL, )
def test_basic_wsgi_call(self): resource = Resource.create({"service-key": "service-value"}) result = TestBase.create_tracer_provider(resource=resource) tracer_provider, exporter = result app = otel_wsgi.OpenTelemetryMiddleware( simple_wsgi, tracer_provider=tracer_provider) response = app(self.environ, self.start_response) self.validate_response(response, exporter)
def test_wsgi_iterable(self): original_response = Response() iter_wsgi = create_iter_wsgi(original_response) app = otel_wsgi.OpenTelemetryMiddleware(iter_wsgi) response = app(self.environ, self.start_response) # Verify that start_response has been called self.assertTrue(self.status) self.validate_response(response) # Verify that close has been called exactly once self.assertEqual(1, original_response.close_calls)
def test_wsgi_generator(self): original_response = Response() gen_wsgi = create_gen_wsgi(original_response) app = otel_wsgi.OpenTelemetryMiddleware(gen_wsgi) response = app(self.environ, self.start_response) # Verify that start_response has not been called self.assertIsNone(self.status) self.validate_response(response) # Verify that close has been called exactly once self.assertEqual(original_response.close_calls, 1)
def test_override_span_name(self): """Test that span_names can be overwritten by our callback function.""" span_name = "Dymaxion" def get_predefined_span_name(scope): # pylint: disable=unused-argument return span_name app = otel_wsgi.OpenTelemetryMiddleware( simple_wsgi, name_callback=get_predefined_span_name) response = app(self.environ, self.start_response) self.validate_response(response, span_name=span_name)
def test_wsgi_not_recording(self): mock_tracer = mock.Mock() mock_span = mock.Mock() mock_span.is_recording.return_value = False mock_tracer.start_span.return_value = mock_span with mock.patch("opentelemetry.trace.get_tracer") as tracer: tracer.return_value = mock_tracer app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi) # pylint: disable=W0612 response = app(self.environ, self.start_response) # noqa: F841 self.assertFalse(mock_span.is_recording()) self.assertTrue(mock_span.is_recording.called) self.assertFalse(mock_span.set_attribute.called) self.assertFalse(mock_span.set_status.called)
def test_custom_request_headers_non_recording_span(self): try: tracer_provider = trace_api.NoOpTracerProvider() self.environ.update( { "HTTP_CUSTOM_TEST_HEADER_1": "Test Value 2", "HTTP_CUSTOM_TEST_HEADER_2": "TestValue2,TestValue3", } ) app = otel_wsgi.OpenTelemetryMiddleware( simple_wsgi, tracer_provider=tracer_provider ) response = app(self.environ, self.start_response) self.iterate_response(response) except Exception as exc: # pylint: disable=W0703 self.fail(f"Exception raised with NonRecordingSpan {exc}")
def test_custom_response_headers_not_added_in_internal_span(self): with self.tracer.start_as_current_span( "test", kind=trace_api.SpanKind.INTERNAL ): app = otel_wsgi.OpenTelemetryMiddleware( wsgi_with_custom_response_headers ) response = app(self.environ, self.start_response) self.iterate_response(response) span = self.memory_exporter.get_finished_spans()[0] not_expected = { "http.response.header.my_custom_header": ( "my-custom-value-1,my-custom-header-2", ), } for key, _ in not_expected.items(): self.assertNotIn(key, span.attributes)
def test_custom_response_headers_added_in_server_span(self): app = otel_wsgi.OpenTelemetryMiddleware( wsgi_with_custom_response_headers ) response = app(self.environ, self.start_response) self.iterate_response(response) span = self.memory_exporter.get_finished_spans()[0] expected = { "http.response.header.content_type": ( "text/plain; charset=utf-8", ), "http.response.header.content_length": ("100",), "http.response.header.my_custom_header": ( "my-custom-value-1,my-custom-header-2", ), } self.assertSpanHasAttributes(span, expected)
def test_custom_request_headers_added_in_server_span(self): self.environ.update( { "HTTP_CUSTOM_TEST_HEADER_1": "Test Value 1", "HTTP_CUSTOM_TEST_HEADER_2": "TestValue2,TestValue3", } ) app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi) response = app(self.environ, self.start_response) self.iterate_response(response) span = self.memory_exporter.get_finished_spans()[0] expected = { "http.request.header.custom_test_header_1": ("Test Value 1",), "http.request.header.custom_test_header_2": ( "TestValue2,TestValue3", ), } self.assertSpanHasAttributes(span, expected)
def test_custom_request_headers_not_added_in_internal_span(self): self.environ.update( { "HTTP_CUSTOM_TEST_HEADER_1": "Test Value 1", } ) with self.tracer.start_as_current_span( "test", kind=trace_api.SpanKind.SERVER ): app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi) response = app(self.environ, self.start_response) self.iterate_response(response) span = self.memory_exporter.get_finished_spans()[0] not_expected = { "http.request.header.custom_test_header_1": ("Test Value 1",), } for key, _ in not_expected.items(): self.assertNotIn(key, span.attributes)
def test_hooks(self): hook_headers = ( "hook_attr", "hello otel", ) def request_hook(span, environ): span.update_name("name from hook") def response_hook(span, environ, status_code, response_headers): span.set_attribute("hook_attr", "hello world") response_headers.append(hook_headers) app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi, request_hook, response_hook) response = app(self.environ, self.start_response) self.validate_response( response, span_name="name from hook", span_attributes={"hook_attr": "hello world"}, response_headers=(hook_headers, ), )
def test_basic_wsgi_call(self): app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi) response = app(self.environ, self.start_response) self.validate_response(response)
def test_default_span_name_missing_request_method(self): """Test that default span_names with missing request method.""" self.environ.pop("REQUEST_METHOD") app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi) response = app(self.environ, self.start_response) self.validate_response(response, span_name="HTTP", http_method=None)
def test_wsgi_exc_info(self): app = otel_wsgi.OpenTelemetryMiddleware(error_wsgi) response = app(self.environ, self.start_response) self.validate_response(response, error=ValueError)