Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ext/opentelemetry-ext-flask/tests/test_programmatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def test_404(self):
resp.close()
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
self.assertEqual(span_list[0].name, "/bye")
self.assertEqual(span_list[0].name, "HTTP POST")
self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
self.assertEqual(span_list[0].attributes, expected_attrs)

Expand Down
2 changes: 1 addition & 1 deletion ext/opentelemetry-ext-pyramid/tests/test_programmatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test_404(self):
resp.close()
span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
self.assertEqual(span_list[0].name, "/bye")
self.assertEqual(span_list[0].name, "HTTP POST")
self.assertEqual(span_list[0].kind, trace.SpanKind.SERVER)
self.assertEqual(span_list[0].attributes, expected_attrs)

Expand Down
29 changes: 17 additions & 12 deletions ext/opentelemetry-ext-wsgi/src/opentelemetry/ext/wsgi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ def collect_request_attributes(environ):

result = {
"component": "http",
"http.method": environ["REQUEST_METHOD"],
"http.server_name": environ["SERVER_NAME"],
"http.scheme": environ["wsgi.url_scheme"],
"host.port": int(environ["SERVER_PORT"]),
"http.method": environ.get("REQUEST_METHOD"),
"http.server_name": environ.get("SERVER_NAME"),
"http.scheme": environ.get("wsgi.url_scheme"),
"host.port": int(environ.get("SERVER_PORT")),
Comment thread
majorgreys marked this conversation as resolved.
Outdated
}

setifnotnone(result, "http.host", environ.get("HTTP_HOST"))
Expand Down Expand Up @@ -149,12 +149,13 @@ def add_response_attributes(


def get_default_span_name(environ):
"""Calculates a (generic) span name for an incoming HTTP request based on the PEP3333 conforming WSGI environ."""

# TODO: Update once
# https://github.com/open-telemetry/opentelemetry-specification/issues/270
# is resolved
return environ.get("PATH_INFO", "/")
"""Default implementation for name_callback, returns HTTP {METHOD_NAME}."""
request_method = environ.get("REQUEST_METHOD")
return "HTTP" + (
" " + request_method
if request_method is not None and request_method != ""
else ""
Comment thread
majorgreys marked this conversation as resolved.
Outdated
)


class OpenTelemetryMiddleware:
Expand All @@ -165,11 +166,15 @@ class OpenTelemetryMiddleware:

Args:
wsgi: The WSGI application callable to forward requests to.
name_callback: Callback which calculates a generic span name for an
incoming HTTP request based on the PEP3333 WSGI environ.
Optional: Defaults to get_default_span_name.
"""

def __init__(self, wsgi):
def __init__(self, wsgi, name_callback=get_default_span_name):
self.wsgi = wsgi
self.tracer = trace.get_tracer(__name__, __version__)
self.name_callback = name_callback

@staticmethod
def _create_start_response(span, start_response):
Expand All @@ -191,7 +196,7 @@ def __call__(self, environ, start_response):
token = context.attach(
propagators.extract(get_header_from_environ, environ)
)
span_name = get_default_span_name(environ)
span_name = self.name_callback(environ)

span = self.tracer.start_span(
span_name,
Expand Down
56 changes: 39 additions & 17 deletions ext/opentelemetry-ext-wsgi/tests/test_wsgi_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ def error_wsgi(environ, start_response):


class TestWsgiApplication(WsgiTestBase):
def validate_response(self, response, error=None):
def validate_response(
self, response, error=None, span_name="HTTP GET", http_method="GET"
):
while True:
try:
value = next(response)
Expand All @@ -95,23 +97,22 @@ def validate_response(self, response, error=None):

span_list = self.memory_exporter.get_finished_spans()
self.assertEqual(len(span_list), 1)
self.assertEqual(span_list[0].name, "/")
self.assertEqual(span_list[0].name, span_name)
self.assertEqual(span_list[0].kind, trace_api.SpanKind.SERVER)
self.assertEqual(
span_list[0].attributes,
{
"component": "http",
"http.method": "GET",
"http.server_name": "127.0.0.1",
"http.scheme": "http",
"host.port": 80,
"http.host": "127.0.0.1",
"http.flavor": "1.0",
"http.url": "http://127.0.0.1/",
"http.status_text": "OK",
"http.status_code": 200,
},
)
expected_attributes = {
"component": "http",
"http.server_name": "127.0.0.1",
"http.scheme": "http",
"host.port": 80,
"http.host": "127.0.0.1",
"http.flavor": "1.0",
"http.url": "http://127.0.0.1/",
"http.status_text": "OK",
"http.status_code": 200,
}
if http_method is not None:
expected_attributes["http.method"] = http_method
self.assertEqual(span_list[0].attributes, expected_attributes)

def test_basic_wsgi_call(self):
app = otel_wsgi.OpenTelemetryMiddleware(simple_wsgi)
Expand Down Expand Up @@ -147,6 +148,27 @@ def test_wsgi_exc_info(self):
response = app(self.environ, self.start_response)
self.validate_response(response, error=ValueError)

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
Comment on lines +155 to +157
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this could be replaced with a Mock:

In [4]: from unittest.mock import Mock

In [5]: the_mock = Mock(**{"return_value": "Dymaxion"})

In [6]: the_mock({"a": "b"})
Out[6]: 'Dymaxion'


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_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)


class TestWsgiAttributes(unittest.TestCase):
def setUp(self):
Expand Down