Prepare asgi tests to support newer asgiref version (#2778)

This commit is contained in:
Riccardo Magliocchetti
2024-08-26 18:38:07 +02:00
committed by GitHub
parent bc4d2c5b75
commit 19f8e775ce
2 changed files with 195 additions and 163 deletions

View File

@ -1,7 +1,21 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import opentelemetry.instrumentation.asgi as otel_asgi
from opentelemetry.test.asgitestutil import AsgiTestBase
from opentelemetry.test.asgitestutil import AsyncAsgiTestBase
from opentelemetry.test.test_base import TestBase
from opentelemetry.trace import SpanKind
from opentelemetry.util.http import (
@ -90,7 +104,7 @@ async def websocket_app_with_custom_headers(scope, receive, send):
break
class TestCustomHeaders(AsgiTestBase, TestBase):
class TestCustomHeaders(AsyncAsgiTestBase):
constructor_params = {}
__test__ = False
@ -108,7 +122,7 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
**self.constructor_params,
)
def test_http_custom_request_headers_in_span_attributes(self):
async def test_http_custom_request_headers_in_span_attributes(self):
self.scope["headers"].extend(
[
(b"custom-test-header-1", b"test-header-value-1"),
@ -119,8 +133,8 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
]
)
self.seed_app(self.app)
self.send_default_request()
self.get_all_output()
await self.send_default_request()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
expected = {
"http.request.header.custom_test_header_1": (
@ -139,7 +153,7 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
if span.kind == SpanKind.SERVER:
self.assertSpanHasAttributes(span, expected)
def test_http_repeat_request_headers_in_span_attributes(self):
async def test_http_repeat_request_headers_in_span_attributes(self):
self.scope["headers"].extend(
[
(b"custom-test-header-1", b"test-header-value-1"),
@ -147,8 +161,8 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
]
)
self.seed_app(self.app)
self.send_default_request()
self.get_all_output()
await self.send_default_request()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
expected = {
"http.request.header.custom_test_header_1": (
@ -159,15 +173,15 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
span = next(span for span in span_list if span.kind == SpanKind.SERVER)
self.assertSpanHasAttributes(span, expected)
def test_http_custom_request_headers_not_in_span_attributes(self):
async def test_http_custom_request_headers_not_in_span_attributes(self):
self.scope["headers"].extend(
[
(b"custom-test-header-1", b"test-header-value-1"),
]
)
self.seed_app(self.app)
self.send_default_request()
self.get_all_output()
await self.send_default_request()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
expected = {
"http.request.header.custom_test_header_1": (
@ -185,15 +199,15 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
for key, _ in not_expected.items():
self.assertNotIn(key, span.attributes)
def test_http_custom_response_headers_in_span_attributes(self):
async def test_http_custom_response_headers_in_span_attributes(self):
self.app = otel_asgi.OpenTelemetryMiddleware(
http_app_with_custom_headers,
tracer_provider=self.tracer_provider,
**self.constructor_params,
)
self.seed_app(self.app)
self.send_default_request()
self.get_all_output()
await self.send_default_request()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
expected = {
"http.response.header.custom_test_header_1": (
@ -214,15 +228,15 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
if span.kind == SpanKind.SERVER:
self.assertSpanHasAttributes(span, expected)
def test_http_repeat_response_headers_in_span_attributes(self):
async def test_http_repeat_response_headers_in_span_attributes(self):
self.app = otel_asgi.OpenTelemetryMiddleware(
http_app_with_repeat_headers,
tracer_provider=self.tracer_provider,
**self.constructor_params,
)
self.seed_app(self.app)
self.send_default_request()
self.get_all_output()
await self.send_default_request()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
expected = {
"http.response.header.custom_test_header_1": (
@ -233,15 +247,15 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
span = next(span for span in span_list if span.kind == SpanKind.SERVER)
self.assertSpanHasAttributes(span, expected)
def test_http_custom_response_headers_not_in_span_attributes(self):
async def test_http_custom_response_headers_not_in_span_attributes(self):
self.app = otel_asgi.OpenTelemetryMiddleware(
http_app_with_custom_headers,
tracer_provider=self.tracer_provider,
**self.constructor_params,
)
self.seed_app(self.app)
self.send_default_request()
self.get_all_output()
await self.send_default_request()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
not_expected = {
"http.response.header.custom_test_header_3": (
@ -253,7 +267,7 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
for key, _ in not_expected.items():
self.assertNotIn(key, span.attributes)
def test_websocket_custom_request_headers_in_span_attributes(self):
async def test_websocket_custom_request_headers_in_span_attributes(self):
self.scope = {
"type": "websocket",
"http_version": "1.1",
@ -271,11 +285,11 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
"server": ("127.0.0.1", 80),
}
self.seed_app(self.app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
expected = {
"http.request.header.custom_test_header_1": (
@ -294,7 +308,9 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
if span.kind == SpanKind.SERVER:
self.assertSpanHasAttributes(span, expected)
def test_websocket_custom_request_headers_not_in_span_attributes(self):
async def test_websocket_custom_request_headers_not_in_span_attributes(
self,
):
self.scope = {
"type": "websocket",
"http_version": "1.1",
@ -309,11 +325,11 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
"server": ("127.0.0.1", 80),
}
self.seed_app(self.app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
not_expected = {
"http.request.header.custom_test_header_3": (
@ -325,7 +341,7 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
for key, _ in not_expected.items():
self.assertNotIn(key, span.attributes)
def test_websocket_custom_response_headers_in_span_attributes(self):
async def test_websocket_custom_response_headers_in_span_attributes(self):
self.scope = {
"type": "websocket",
"http_version": "1.1",
@ -342,10 +358,10 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
**self.constructor_params,
)
self.seed_app(self.app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
expected = {
"http.response.header.custom_test_header_1": (
@ -366,7 +382,9 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
if span.kind == SpanKind.SERVER:
self.assertSpanHasAttributes(span, expected)
def test_websocket_custom_response_headers_not_in_span_attributes(self):
async def test_websocket_custom_response_headers_not_in_span_attributes(
self,
):
self.scope = {
"type": "websocket",
"http_version": "1.1",
@ -383,10 +401,10 @@ class TestCustomHeaders(AsgiTestBase, TestBase):
**self.constructor_params,
)
self.seed_app(self.app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
await self.get_all_output()
span_list = self.exporter.get_finished_spans()
not_expected = {
"http.response.header.custom_test_header_3": (

View File

@ -14,7 +14,6 @@
# pylint: disable=too-many-lines
import asyncio
import sys
import time
import unittest
@ -64,7 +63,7 @@ from opentelemetry.semconv.attributes.user_agent_attributes import (
)
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry.test.asgitestutil import (
AsgiTestBase,
AsyncAsgiTestBase,
setup_testing_defaults,
)
from opentelemetry.test.test_base import TestBase
@ -275,7 +274,7 @@ async def error_asgi(scope, receive, send):
# pylint: disable=too-many-public-methods
class TestAsgiApplication(AsgiTestBase):
class TestAsgiApplication(AsyncAsgiTestBase):
def setUp(self):
super().setUp()
@ -477,31 +476,31 @@ class TestAsgiApplication(AsgiTestBase):
"opentelemetry.instrumentation.asgi",
)
def test_basic_asgi_call(self):
async def test_basic_asgi_call(self):
"""Test that spans are emitted as expected."""
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs)
def test_basic_asgi_call_new_semconv(self):
async def test_basic_asgi_call_new_semconv(self):
"""Test that spans are emitted as expected."""
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs, old_sem_conv=False, new_sem_conv=True)
def test_basic_asgi_call_both_semconv(self):
async def test_basic_asgi_call_both_semconv(self):
"""Test that spans are emitted as expected."""
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs, old_sem_conv=True, new_sem_conv=True)
def test_asgi_not_recording(self):
async def test_asgi_not_recording(self):
mock_tracer = mock.Mock()
mock_span = mock.Mock()
mock_span.is_recording.return_value = False
@ -514,21 +513,21 @@ class TestAsgiApplication(AsgiTestBase):
tracer.return_value = mock_tracer
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
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_asgi_exc_info(self):
async def test_asgi_exc_info(self):
"""Test that exception information is emitted as expected."""
app = otel_asgi.OpenTelemetryMiddleware(error_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs, error=ValueError)
def test_long_response(self):
async def test_long_response(self):
"""Test that the server span is ended on the final response body message.
If the server span is ended early then this test will fail due
@ -536,8 +535,8 @@ class TestAsgiApplication(AsgiTestBase):
"""
app = otel_asgi.OpenTelemetryMiddleware(long_response_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
def add_more_body_spans(expected: list):
more_body_span = {
@ -551,12 +550,12 @@ class TestAsgiApplication(AsgiTestBase):
self.validate_outputs(outputs, modifiers=[add_more_body_spans])
def test_background_execution(self):
async def test_background_execution(self):
"""Test that the server span is ended BEFORE the background task is finished."""
app = otel_asgi.OpenTelemetryMiddleware(background_execution_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs)
span_list = self.memory_exporter.get_finished_spans()
server_span = span_list[-1]
@ -567,15 +566,15 @@ class TestAsgiApplication(AsgiTestBase):
_SIMULATED_BACKGROUND_TASK_EXECUTION_TIME_S * 10**9,
)
def test_trailers(self):
async def test_trailers(self):
"""Test that trailers are emitted as expected and that the server span is ended
BEFORE the background task is finished."""
app = otel_asgi.OpenTelemetryMiddleware(
background_execution_trailers_asgi
)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
def add_body_and_trailer_span(expected: list):
body_span = {
@ -602,7 +601,7 @@ class TestAsgiApplication(AsgiTestBase):
_SIMULATED_BACKGROUND_TASK_EXECUTION_TIME_S * 10**9,
)
def test_override_span_name(self):
async def test_override_span_name(self):
"""Test that default span_names can be overwritten by our callback function."""
span_name = "Dymaxion"
@ -623,11 +622,11 @@ class TestAsgiApplication(AsgiTestBase):
simple_asgi, default_span_details=get_predefined_span_details
)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs, modifiers=[update_expected_span_name])
def test_custom_tracer_provider_otel_asgi(self):
async def test_custom_tracer_provider_otel_asgi(self):
resource = resources.Resource.create({"service-test-key": "value"})
result = TestBase.create_tracer_provider(resource=resource)
tracer_provider, exporter = result
@ -636,28 +635,28 @@ class TestAsgiApplication(AsgiTestBase):
simple_asgi, tracer_provider=tracer_provider
)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
span_list = exporter.get_finished_spans()
for span in span_list:
self.assertEqual(
span.resource.attributes["service-test-key"], "value"
)
def test_no_op_tracer_provider_otel_asgi(self):
async def test_no_op_tracer_provider_otel_asgi(self):
app = otel_asgi.OpenTelemetryMiddleware(
simple_asgi, tracer_provider=trace_api.NoOpTracerProvider()
)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
response_start, response_body, *_ = self.get_all_output()
response_start, response_body, *_ = await self.get_all_output()
self.assertEqual(response_body["body"], b"*")
self.assertEqual(response_start["status"], 200)
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 0)
def test_behavior_with_scope_server_as_none(self):
async def test_behavior_with_scope_server_as_none(self):
"""Test that middleware is ok when server is none in scope."""
def update_expected_server(expected):
@ -673,11 +672,11 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["server"] = None
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs, modifiers=[update_expected_server])
def test_behavior_with_scope_server_as_none_new_semconv(self):
async def test_behavior_with_scope_server_as_none_new_semconv(self):
"""Test that middleware is ok when server is none in scope."""
def update_expected_server(expected):
@ -692,8 +691,8 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["server"] = None
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(
outputs,
modifiers=[update_expected_server],
@ -701,7 +700,7 @@ class TestAsgiApplication(AsgiTestBase):
new_sem_conv=True,
)
def test_behavior_with_scope_server_as_none_both_semconv(self):
async def test_behavior_with_scope_server_as_none_both_semconv(self):
"""Test that middleware is ok when server is none in scope."""
def update_expected_server(expected):
@ -719,8 +718,8 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["server"] = None
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(
outputs,
modifiers=[update_expected_server],
@ -728,7 +727,7 @@ class TestAsgiApplication(AsgiTestBase):
new_sem_conv=True,
)
def test_host_header(self):
async def test_host_header(self):
"""Test that host header is converted to http.server_name."""
hostname = b"server_name_1"
@ -741,11 +740,11 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["headers"].append([b"host", hostname])
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs, modifiers=[update_expected_server])
def test_host_header_both_semconv(self):
async def test_host_header_both_semconv(self):
"""Test that host header is converted to http.server_name."""
hostname = b"server_name_1"
@ -758,8 +757,8 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["headers"].append([b"host", hostname])
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(
outputs,
modifiers=[update_expected_server],
@ -767,7 +766,7 @@ class TestAsgiApplication(AsgiTestBase):
new_sem_conv=True,
)
def test_user_agent(self):
async def test_user_agent(self):
"""Test that host header is converted to http.server_name."""
user_agent = b"test-agent"
@ -780,11 +779,11 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["headers"].append([b"user-agent", user_agent])
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(outputs, modifiers=[update_expected_user_agent])
def test_user_agent_new_semconv(self):
async def test_user_agent_new_semconv(self):
"""Test that host header is converted to http.server_name."""
user_agent = b"test-agent"
@ -797,8 +796,8 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["headers"].append([b"user-agent", user_agent])
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(
outputs,
modifiers=[update_expected_user_agent],
@ -806,7 +805,7 @@ class TestAsgiApplication(AsgiTestBase):
new_sem_conv=True,
)
def test_user_agent_both_semconv(self):
async def test_user_agent_both_semconv(self):
"""Test that host header is converted to http.server_name."""
user_agent = b"test-agent"
@ -822,8 +821,8 @@ class TestAsgiApplication(AsgiTestBase):
self.scope["headers"].append([b"user-agent", user_agent])
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(
outputs,
modifiers=[update_expected_user_agent],
@ -831,7 +830,7 @@ class TestAsgiApplication(AsgiTestBase):
new_sem_conv=True,
)
def test_traceresponse_header(self):
async def test_traceresponse_header(self):
"""Test a traceresponse header is sent when a global propagator is set."""
orig = get_global_response_propagator()
@ -839,12 +838,12 @@ class TestAsgiApplication(AsgiTestBase):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
response_start, response_body, *_ = await self.get_all_output()
span = self.memory_exporter.get_finished_spans()[-1]
self.assertEqual(trace_api.SpanKind.SERVER, span.kind)
response_start, response_body, *_ = self.get_all_output()
self.assertEqual(response_body["body"], b"*")
self.assertEqual(response_start["status"], 200)
@ -864,7 +863,7 @@ class TestAsgiApplication(AsgiTestBase):
set_global_response_propagator(orig)
def test_websocket(self):
async def test_websocket(self):
self.scope = {
"method": "GET",
"type": "websocket",
@ -878,10 +877,10 @@ class TestAsgiApplication(AsgiTestBase):
}
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
await self.get_all_output()
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 6)
expected = [
@ -938,7 +937,7 @@ class TestAsgiApplication(AsgiTestBase):
self.assertEqual(span.kind, expected["kind"])
self.assertDictEqual(dict(span.attributes), expected["attributes"])
def test_websocket_new_semconv(self):
async def test_websocket_new_semconv(self):
self.scope = {
"method": "GET",
"type": "websocket",
@ -952,10 +951,10 @@ class TestAsgiApplication(AsgiTestBase):
}
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
await self.get_all_output()
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 6)
expected = [
@ -1010,7 +1009,7 @@ class TestAsgiApplication(AsgiTestBase):
self.assertEqual(span.kind, expected["kind"])
self.assertDictEqual(dict(span.attributes), expected["attributes"])
def test_websocket_both_semconv(self):
async def test_websocket_both_semconv(self):
self.scope = {
"method": "GET",
"type": "websocket",
@ -1024,10 +1023,10 @@ class TestAsgiApplication(AsgiTestBase):
}
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
await self.get_all_output()
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 6)
expected = [
@ -1094,7 +1093,7 @@ class TestAsgiApplication(AsgiTestBase):
self.assertEqual(span.kind, expected["kind"])
self.assertDictEqual(dict(span.attributes), expected["attributes"])
def test_websocket_traceresponse_header(self):
async def test_websocket_traceresponse_header(self):
"""Test a traceresponse header is set for websocket messages"""
orig = get_global_response_propagator()
@ -1112,10 +1111,10 @@ class TestAsgiApplication(AsgiTestBase):
}
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
_, socket_send, *_ = self.get_all_output()
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
_, socket_send, *_ = await self.get_all_output()
span = self.memory_exporter.get_finished_spans()[-1]
self.assertEqual(trace_api.SpanKind.SERVER, span.kind)
@ -1134,15 +1133,15 @@ class TestAsgiApplication(AsgiTestBase):
set_global_response_propagator(orig)
def test_lifespan(self):
async def test_lifespan(self):
self.scope["type"] = "lifespan"
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 0)
def test_hooks(self):
async def test_hooks(self):
def server_request_hook(span, scope):
span.update_name("name from server hook")
@ -1169,20 +1168,23 @@ class TestAsgiApplication(AsgiTestBase):
client_response_hook=client_response_hook,
)
self.seed_app(app)
self.send_default_request()
outputs = self.get_all_output()
await self.send_default_request()
outputs = await self.get_all_output()
self.validate_outputs(
outputs, modifiers=[update_expected_hook_results]
)
def test_asgi_metrics(self):
async def test_asgi_metrics(self):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
metrics_list = self.memory_metrics_reader.get_metrics_data()
number_data_point_seen = False
histogram_data_point_seen = False
@ -1211,14 +1213,17 @@ class TestAsgiApplication(AsgiTestBase):
)
self.assertTrue(number_data_point_seen and histogram_data_point_seen)
def test_asgi_metrics_new_semconv(self):
async def test_asgi_metrics_new_semconv(self):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
metrics_list = self.memory_metrics_reader.get_metrics_data()
number_data_point_seen = False
histogram_data_point_seen = False
@ -1247,14 +1252,17 @@ class TestAsgiApplication(AsgiTestBase):
)
self.assertTrue(number_data_point_seen and histogram_data_point_seen)
def test_asgi_metrics_both_semconv(self):
async def test_asgi_metrics_both_semconv(self):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
metrics_list = self.memory_metrics_reader.get_metrics_data()
number_data_point_seen = False
histogram_data_point_seen = False
@ -1283,12 +1291,13 @@ class TestAsgiApplication(AsgiTestBase):
)
self.assertTrue(number_data_point_seen and histogram_data_point_seen)
def test_basic_metric_success(self):
async def test_basic_metric_success(self):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
start = default_timer()
self.send_default_request()
await self.send_default_request()
duration = max(round((default_timer() - start) * 1000), 0)
await self.get_all_output()
expected_duration_attributes = {
"http.method": "GET",
"http.host": "127.0.0.1",
@ -1330,7 +1339,7 @@ class TestAsgiApplication(AsgiTestBase):
)
self.assertEqual(point.value, 0)
def test_basic_metric_success_nonrecording_span(self):
async def test_basic_metric_success_nonrecording_span(self):
mock_tracer = mock.Mock()
mock_span = mock.Mock()
mock_span.is_recording.return_value = False
@ -1344,8 +1353,9 @@ class TestAsgiApplication(AsgiTestBase):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
start = default_timer()
self.send_default_request()
await self.send_default_request()
duration = max(round((default_timer() - start) * 1000), 0)
await self.get_all_output()
expected_duration_attributes = {
"http.method": "GET",
"http.host": "127.0.0.1",
@ -1374,7 +1384,7 @@ class TestAsgiApplication(AsgiTestBase):
self.assertEqual(point.count, 1)
if metric.name == "http.server.duration":
self.assertAlmostEqual(
duration, point.sum, delta=5
duration, point.sum, delta=15
)
elif (
metric.name == "http.server.response.size"
@ -1389,12 +1399,13 @@ class TestAsgiApplication(AsgiTestBase):
)
self.assertEqual(point.value, 0)
def test_basic_metric_success_new_semconv(self):
async def test_basic_metric_success_new_semconv(self):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
start = default_timer()
self.send_default_request()
await self.send_default_request()
duration_s = max(default_timer() - start, 0)
await self.get_all_output()
expected_duration_attributes = {
"http.request.method": "GET",
"url.scheme": "http",
@ -1436,13 +1447,14 @@ class TestAsgiApplication(AsgiTestBase):
)
self.assertEqual(point.value, 0)
def test_basic_metric_success_both_semconv(self):
async def test_basic_metric_success_both_semconv(self):
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
start = default_timer()
self.send_default_request()
await self.send_default_request()
duration = max(round((default_timer() - start) * 1000), 0)
duration_s = max(default_timer() - start, 0)
await self.get_all_output()
expected_duration_attributes_old = {
"http.method": "GET",
"http.host": "127.0.0.1",
@ -1524,7 +1536,7 @@ class TestAsgiApplication(AsgiTestBase):
)
self.assertEqual(point.value, 0)
def test_metric_target_attribute(self):
async def test_metric_target_attribute(self):
expected_target = "/api/user/{id}"
class TestRoute:
@ -1540,7 +1552,8 @@ class TestAsgiApplication(AsgiTestBase):
app = otel_asgi.OpenTelemetryMiddleware(target_asgi)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
metrics_list = self.memory_metrics_reader.get_metrics_data()
assertions = 0
for resource_metric in metrics_list.resource_metrics:
@ -1557,7 +1570,7 @@ class TestAsgiApplication(AsgiTestBase):
assertions += 1
self.assertEqual(assertions, 3)
def test_no_metric_for_websockets(self):
async def test_no_metric_for_websockets(self):
self.scope = {
"type": "websocket",
"http_version": "1.1",
@ -1570,10 +1583,10 @@ class TestAsgiApplication(AsgiTestBase):
}
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
self.seed_app(app)
self.send_input({"type": "websocket.connect"})
self.send_input({"type": "websocket.receive", "text": "ping"})
self.send_input({"type": "websocket.disconnect"})
self.get_all_output()
await self.send_input({"type": "websocket.connect"})
await self.send_input({"type": "websocket.receive", "text": "ping"})
await self.send_input({"type": "websocket.disconnect"})
await self.get_all_output()
self.assertIsNone(self.memory_metrics_reader.get_metrics_data())
@ -1790,8 +1803,10 @@ class TestAsgiAttributes(unittest.TestCase):
)
class TestWrappedApplication(AsgiTestBase):
def test_mark_span_internal_in_presence_of_span_from_other_framework(self):
class TestWrappedApplication(AsyncAsgiTestBase):
async 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__)
app = otel_asgi.OpenTelemetryMiddleware(
@ -1806,7 +1821,8 @@ class TestWrappedApplication(AsgiTestBase):
await app(scope, receive, send)
self.seed_app(wrapped_app)
self.send_default_request()
await self.send_default_request()
await self.get_all_output()
span_list = exporter.get_finished_spans()
self.assertEqual(SpanKind.INTERNAL, span_list[0].kind)
@ -1823,11 +1839,11 @@ class TestWrappedApplication(AsgiTestBase):
)
class TestAsgiApplicationRaisingError(AsgiTestBase):
class TestAsgiApplicationRaisingError(AsyncAsgiTestBase):
def tearDown(self):
pass
def test_asgi_issue_1883(self):
async def test_asgi_value_error_exception(self):
"""
Test that exception UnboundLocalError local variable 'start' referenced before assignment is not raised
See https://github.com/open-telemetry/opentelemetry-python-contrib/issues/1883
@ -1838,11 +1854,9 @@ class TestAsgiApplicationRaisingError(AsgiTestBase):
app = otel_asgi.OpenTelemetryMiddleware(bad_app)
self.seed_app(app)
self.send_default_request()
await self.send_default_request()
try:
asyncio.get_event_loop().run_until_complete(
self.communicator.stop()
)
await self.communicator.wait()
except ValueError as exc_info:
self.assertEqual(exc_info.args[0], "whatever")
except Exception as exc_info: # pylint: disable=W0703