Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Span names for flask requests only show the HTTP method if they didn't match a route #2155

Open
alexmojaki opened this issue Feb 7, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@alexmojaki
Copy link
Contributor

Steps to reproduce

  1. Instrument a Flask app with FlaskInstrumentor
  2. Visit a URL that matches a route and returns 200
  3. Visit a different URL that doesn't match a route and returns 404
  4. Check the span names for the two requests

Example code:

from flask import Flask
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor

tracer_provider = TracerProvider()
processor = SimpleSpanProcessor(ConsoleSpanExporter(formatter=lambda span: f'!!! Span: {span.name}\n'))
tracer_provider.add_span_processor(processor)

app = Flask(__name__)
FlaskInstrumentor().instrument_app(app, tracer_provider=tracer_provider)


@app.route('/item/<int:item_id>')
def get_item(item_id):
    return f'item {item_id}'


app.run()

Then open in your browser:

Note that the second request has the right general pattern but fails to match a route purely because foobar can't be converted to an integer.

What is the expected behavior?

!!! Span: GET /item/<int:item_id>
!!! Span: GET /item/foobar

What is the actual behavior?

The first GET is missing:

!!! Span: /item/<int:item_id>
!!! Span: GET /item/foobar

Additional context

The reason for this is clearly visible in the code. Requests with a matching Flask route don't have the HTTP method included:

def get_default_span_name():
try:
span_name = flask.request.url_rule.rule
except AttributeError:
span_name = otel_wsgi.get_default_span_name(flask.request.environ)
return span_name

But if they don't match, they fallback to the WSGI span name which includes the method:

def get_default_span_name(environ):
"""
Default span name is the HTTP method and URL path, or just the method.
https://github.com/open-telemetry/opentelemetry-specification/pull/3165
https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#name
Args:
environ: The WSGI environ object.
Returns:
The span name.
"""
method = sanitize_method(environ.get("REQUEST_METHOD", "").strip())
path = environ.get("PATH_INFO", "").strip()
if method and path:
return f"{method} {path}"
return method

BTW, this PR comment requested removing name_callback which would have allowed customising the span name myself to work around this issue, but I don't see the reasoning behind this.

@alexmojaki alexmojaki added the bug Something isn't working label Feb 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant