-
Notifications
You must be signed in to change notification settings - Fork 624
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
Provide excluded_urls argument to Flask instrumentation #604
Merged
Merged
Changes from 5 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
bcbd21f
Provide excluded_urls argument to Flask instrumentation
mattoberle ab3d177
Update CHANGELOG with better description
mattoberle 417a046
Merge branch 'main' into flask-excluded_urls
lzchen 0e62052
Update CHANGELOG.md
mattoberle b3aa6bd
Merge branch 'main' into flask-excluded_urls
lzchen 5996b7e
Pass excluded_urls to Flask auto-instrumentation
mattoberle a236b46
Merge branch 'main' into flask-excluded_urls
lzchen 04f9525
Merge branch 'main' into flask-excluded_urls
lzchen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -63,7 +63,7 @@ def hello(): | |||||
from opentelemetry.propagate import extract | ||||||
from opentelemetry.semconv.trace import SpanAttributes | ||||||
from opentelemetry.util._time import _time_ns | ||||||
from opentelemetry.util.http import get_excluded_urls | ||||||
from opentelemetry.util.http import get_excluded_urls, parse_excluded_urls | ||||||
|
||||||
_logger = getLogger(__name__) | ||||||
|
||||||
|
@@ -73,7 +73,7 @@ def hello(): | |||||
_ENVIRON_TOKEN = "opentelemetry-flask.token" | ||||||
|
||||||
|
||||||
_excluded_urls = get_excluded_urls("FLASK") | ||||||
_excluded_urls_from_env = get_excluded_urls("FLASK") | ||||||
|
||||||
|
||||||
def get_default_span_name(): | ||||||
|
@@ -85,7 +85,7 @@ def get_default_span_name(): | |||||
return span_name | ||||||
|
||||||
|
||||||
def _rewrapped_app(wsgi_app, response_hook=None): | ||||||
def _rewrapped_app(wsgi_app, response_hook=None, excluded_urls=None): | ||||||
def _wrapped_app(wrapped_app_environ, start_response): | ||||||
# We want to measure the time for route matching, etc. | ||||||
# In theory, we could start the span here and use | ||||||
|
@@ -94,7 +94,9 @@ def _wrapped_app(wrapped_app_environ, start_response): | |||||
wrapped_app_environ[_ENVIRON_STARTTIME_KEY] = _time_ns() | ||||||
|
||||||
def _start_response(status, response_headers, *args, **kwargs): | ||||||
if not _excluded_urls.url_disabled(flask.request.url): | ||||||
if excluded_urls is None or not excluded_urls.url_disabled( | ||||||
flask.request.url | ||||||
): | ||||||
span = flask.request.environ.get(_ENVIRON_SPAN_KEY) | ||||||
|
||||||
propagator = get_global_response_propagator() | ||||||
|
@@ -123,9 +125,11 @@ def _start_response(status, response_headers, *args, **kwargs): | |||||
return _wrapped_app | ||||||
|
||||||
|
||||||
def _wrapped_before_request(request_hook=None, tracer=None): | ||||||
def _wrapped_before_request( | ||||||
request_hook=None, tracer=None, excluded_urls=None | ||||||
): | ||||||
def _before_request(): | ||||||
if _excluded_urls.url_disabled(flask.request.url): | ||||||
if excluded_urls and excluded_urls.url_disabled(flask.request.url): | ||||||
return | ||||||
flask_request_environ = flask.request.environ | ||||||
span_name = get_default_span_name() | ||||||
|
@@ -163,29 +167,33 @@ def _before_request(): | |||||
return _before_request | ||||||
|
||||||
|
||||||
def _teardown_request(exc): | ||||||
# pylint: disable=E1101 | ||||||
if _excluded_urls.url_disabled(flask.request.url): | ||||||
return | ||||||
def _wrapped_teardown_request(excluded_urls=None): | ||||||
def _teardown_request(exc): | ||||||
# pylint: disable=E1101 | ||||||
if excluded_urls and excluded_urls.url_disabled(flask.request.url): | ||||||
return | ||||||
|
||||||
activation = flask.request.environ.get(_ENVIRON_ACTIVATION_KEY) | ||||||
if not activation: | ||||||
# This request didn't start a span, maybe because it was created in a | ||||||
# way that doesn't run `before_request`, like when it is created with | ||||||
# `app.test_request_context`. | ||||||
return | ||||||
activation = flask.request.environ.get(_ENVIRON_ACTIVATION_KEY) | ||||||
if not activation: | ||||||
# This request didn't start a span, maybe because it was created in | ||||||
# a way that doesn't run `before_request`, like when it is created | ||||||
# with `app.test_request_context`. | ||||||
return | ||||||
|
||||||
if exc is None: | ||||||
activation.__exit__(None, None, None) | ||||||
else: | ||||||
activation.__exit__( | ||||||
type(exc), exc, getattr(exc, "__traceback__", None) | ||||||
) | ||||||
context.detach(flask.request.environ.get(_ENVIRON_TOKEN)) | ||||||
if exc is None: | ||||||
activation.__exit__(None, None, None) | ||||||
else: | ||||||
activation.__exit__( | ||||||
type(exc), exc, getattr(exc, "__traceback__", None) | ||||||
) | ||||||
context.detach(flask.request.environ.get(_ENVIRON_TOKEN)) | ||||||
|
||||||
return _teardown_request | ||||||
|
||||||
|
||||||
class _InstrumentedFlask(flask.Flask): | ||||||
|
||||||
_excluded_urls = None | ||||||
_tracer_provider = None | ||||||
_request_hook = None | ||||||
_response_hook = None | ||||||
|
@@ -209,6 +217,10 @@ def __init__(self, *args, **kwargs): | |||||
) | ||||||
self._before_request = _before_request | ||||||
self.before_request(_before_request) | ||||||
|
||||||
_teardown_request = _wrapped_teardown_request( | ||||||
excluded_urls=_InstrumentedFlask._excluded_urls, | ||||||
) | ||||||
self.teardown_request(_teardown_request) | ||||||
|
||||||
|
||||||
|
@@ -232,27 +244,49 @@ def _instrument(self, **kwargs): | |||||
_InstrumentedFlask._response_hook = response_hook | ||||||
tracer_provider = kwargs.get("tracer_provider") | ||||||
_InstrumentedFlask._tracer_provider = tracer_provider | ||||||
excluded_urls = kwargs.get("excluded_urls") | ||||||
_InstrumentedFlask._excluded_urls = ( | ||||||
_excluded_urls_from_env | ||||||
if excluded_urls is None | ||||||
else parse_excluded_urls(excluded_urls) | ||||||
) | ||||||
flask.Flask = _InstrumentedFlask | ||||||
|
||||||
def _uninstrument(self, **kwargs): | ||||||
flask.Flask = self._original_flask | ||||||
|
||||||
@staticmethod | ||||||
def instrument_app( | ||||||
app, request_hook=None, response_hook=None, tracer_provider=None | ||||||
app, | ||||||
request_hook=None, | ||||||
response_hook=None, | ||||||
tracer_provider=None, | ||||||
excluded_urls=None, | ||||||
): | ||||||
if not hasattr(app, "_is_instrumented_by_opentelemetry"): | ||||||
app._is_instrumented_by_opentelemetry = False | ||||||
|
||||||
if not app._is_instrumented_by_opentelemetry: | ||||||
excluded_urls = ( | ||||||
parse_excluded_urls(excluded_urls) | ||||||
if excluded_urls is not None | ||||||
else _excluded_urls_from_env | ||||||
) | ||||||
app._original_wsgi_app = app.wsgi_app | ||||||
app.wsgi_app = _rewrapped_app(app.wsgi_app, response_hook) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
tracer = trace.get_tracer(__name__, __version__, tracer_provider) | ||||||
|
||||||
_before_request = _wrapped_before_request(request_hook, tracer) | ||||||
_before_request = _wrapped_before_request( | ||||||
request_hook, tracer, excluded_urls=excluded_urls, | ||||||
) | ||||||
app._before_request = _before_request | ||||||
app.before_request(_before_request) | ||||||
|
||||||
_teardown_request = _wrapped_teardown_request( | ||||||
excluded_urls=excluded_urls, | ||||||
) | ||||||
app._teardown_request = _teardown_request | ||||||
app.teardown_request(_teardown_request) | ||||||
app._is_instrumented_by_opentelemetry = True | ||||||
else: | ||||||
|
@@ -267,7 +301,7 @@ def uninstrument_app(app): | |||||
|
||||||
# FIXME add support for other Flask blueprints that are not None | ||||||
app.before_request_funcs[None].remove(app._before_request) | ||||||
app.teardown_request_funcs[None].remove(_teardown_request) | ||||||
app.teardown_request_funcs[None].remove(app._teardown_request) | ||||||
del app._original_wsgi_app | ||||||
app._is_instrumented_by_opentelemetry = False | ||||||
else: | ||||||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does
_before_request
and_rewrapped_app
need theexcluded_urls
passed in as well?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch.
I need to extend
test_automatic.py
to cover this case and then I'll push up the change.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub didn't update the comment since the change is a few lines up, but this should be taken care of now on line 220 in this commit:
5996b7e