Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
The format is based on [Keep a Changelog](http://keepachangelog.com/).
## Unreleased

- fix: Flask, Quart and Connexion no longer generate a new correlation ID for each log record emitted outside an
active HTTP request; those records now get `-`, as documented. Connexion 3 error handlers and ASGI middleware,
which run outside the Flask request context, still use the request's correlation header; without one they get
`-`, because a generated ID is only stored inside the Flask request context. Fixes #125

- fix: `init_sanic()` no longer raises `KeyError: 'format'` when Sanic 24.x and later omit
formatter `format` keys; older Sanic logging configuration remains supported (PR #133).

Expand Down
19 changes: 18 additions & 1 deletion json_logging/framework/connexion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ def is_connexion_present():
_flask = flask
_connexion.g = g

try:
# Connexion 3+: the ASGI request scope, a werkzeug LocalProxy that is falsy outside a Connexion request
from connexion.context import scope as _connexion_scope
except ImportError:
# Connexion 2: connexion.request is flask.request, so the Flask request context is the only one
_connexion_scope = None


class ConnexionAppRequestInstrumentationConfigurator(BaseAppRequestInstrumentationConfigurator):
def config(self, app, request_response_dto_class, exclude_url_patterns=[]):
Expand Down Expand Up @@ -79,7 +86,17 @@ def support_global_request_object():

@staticmethod
def get_current_request():
return _current_request
# The request proxy exists even outside a request; only expose it while a request is active,
# so callers fall back to json_logging.EMPTY_VALUE instead of generating fabricated IDs.
if _flask.has_request_context():
return _current_request
# Connexion 3 runs error handlers and ASGI middleware outside the Flask request context. The request's
# correlation header can still be read there, but a generated ID could not be stored (connexion.g is
# flask.g), so expose the request only when it carries a correlation header.
if _connexion_scope is not None and _connexion_scope and any(
header in _current_request.headers for header in json_logging.CORRELATION_ID_HEADERS):
return _current_request
return None

def get_remote_user(self, request):
if request.authorization is not None:
Expand Down
4 changes: 3 additions & 1 deletion json_logging/framework/flask/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ def support_global_request_object():

@staticmethod
def get_current_request():
return _current_request
# The request proxy exists even outside a request; only expose it while a request is active,
# so callers fall back to json_logging.EMPTY_VALUE instead of generating fabricated IDs.
return _current_request if _flask.has_request_context() else None

def get_remote_user(self, request):
if request.authorization is not None:
Expand Down
4 changes: 3 additions & 1 deletion json_logging/framework/quart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ def support_global_request_object():

@staticmethod
def get_current_request():
return _current_request
# The request proxy exists even outside a request; only expose it while a request is active,
# so callers fall back to json_logging.EMPTY_VALUE instead of generating fabricated IDs.
return _current_request if _quart.has_request_context() else None

def get_remote_user(self, request):
if request.authorization is not None:
Expand Down
2 changes: 1 addition & 1 deletion test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
wheel
flask
connexion[swagger-ui]
connexion[flask,swagger-ui]
quart
sanic
fastapi
Expand Down
Loading
Loading