def test_response_attributes(self): OpenTelemetryMiddleware._add_response_attributes( # noqa pylint: disable=protected-access self.span, "404 Not Found") expected = ( mock.call("http.status_code", 404), mock.call("http.status_text", "Not Found"), ) self.assertEqual(self.span.set_attribute.call_count, len(expected)) self.span.set_attribute.assert_has_calls(expected, any_order=True)
def validate_url(self, expected_url): OpenTelemetryMiddleware._add_request_attributes( # noqa pylint: disable=protected-access self.span, self.environ) attrs = { args[0][0]: args[0][1] for args in self.span.set_attribute.call_args_list } self.assertIn("http.url", attrs) self.assertEqual(attrs["http.url"], expected_url) self.assertIn("http.host", attrs) self.assertEqual(attrs["http.host"], urlparse(expected_url).netloc)
def test_request_attributes(self): OpenTelemetryMiddleware._add_request_attributes( # noqa pylint: disable=protected-access self.span, self.environ) expected = ( mock.call("component", "http"), mock.call("http.method", "GET"), mock.call("http.host", "127.0.0.1"), mock.call("http.url", "http://127.0.0.1/"), ) self.assertEqual(self.span.set_attribute.call_count, len(expected)) self.span.set_attribute.assert_has_calls(expected, any_order=True)
def configure_opentelemetry(flask_app: flask.Flask): """Configure a flask application to use OpenTelemetry. This activates the specific components: * sets tracer to the SDK's Tracer * enables requests integration on the Tracer * uses a WSGI middleware to enable configuration TODO: * processors? * exporters? """ # Start by configuring all objects required to ensure # a complete end to end workflow. # the preferred implementation of these objects must be set, # as the opentelemetry-api defines the interface with a no-op # implementation. trace.set_preferred_tracer_implementation(lambda _: Tracer()) # Next, we need to configure how the values that are used by # traces and metrics are propagated (such as what specific headers # carry this value). # TBD: can remove once default TraceContext propagators are installed. propagators.set_global_httptextformat(B3Format()) # Integrations are the glue that binds the OpenTelemetry API # and the frameworks and libraries that are used together, automatically # creating Spans and propagating context as appropriate. opentelemetry.ext.http_requests.enable(trace.tracer()) flask_app.wsgi_app = OpenTelemetryMiddleware(flask_app.wsgi_app)
def test_wsgi_generator(self): original_response = Response() gen_wsgi = create_gen_wsgi(original_response) app = 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_wsgi_iterable(self): original_response = Response() iter_wsgi = create_iter_wsgi(original_response) app = 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(original_response.close_calls, 1)
from kitchen_service import KitchenService from kitchen_consumer import KitchenConsumer from donut import Donut from status import NEW_ORDER trace.set_preferred_tracer_implementation(lambda T: Tracer()) propagators.set_global_httptextformat(B3Format()) tracer = trace.tracer() enable(tracer) tracer.add_span_processor(SimpleExportSpanProcessor(ConsoleSpanExporter())) app = Flask(__name__) app.static_folder = 'static' app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app) kitchen_service = KitchenService() kitchen_consumer = KitchenConsumer() @app.route('/') def home(): return render_template('index.html') @app.route('/order', methods=['POST']) def order(): order_id = str(uuid4())
""" WSGI config for django_opentelemetry_example project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ """ import os from opentelemetry.ext.wsgi import OpenTelemetryMiddleware from django.core.wsgi import get_wsgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_opentelemetry_example.settings') from django_opentelemetry_example.tracer import setup_tracer setup_tracer('django-wsgi-service') application = get_wsgi_application() application = OpenTelemetryMiddleware(application)
def test_response_attributes_invalid_status_code(self): OpenTelemetryMiddleware._add_response_attributes( # noqa pylint: disable=protected-access self.span, "Invalid Status Code") self.assertEqual(self.span.set_attribute.call_count, 1) self.span.set_attribute.assert_called_with("http.status_text", "Status Code")
def test_wsgi_exc_info(self): app = OpenTelemetryMiddleware(error_wsgi) response = app(self.environ, self.start_response) self.validate_response(response, error=ValueError)
def test_basic_wsgi_call(self): app = OpenTelemetryMiddleware(simple_wsgi) response = app(self.environ, self.start_response) self.validate_response(response)
def get_telemetry_app(application): return OpenTelemetryMiddleware(application)