-
Notifications
You must be signed in to change notification settings - Fork 21
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
(fastapi) Log request ID when set in headers #100
Conversation
src/dockerflow/fastapi/middleware.py
Outdated
try: | ||
# Log the request ID if it's set by the reverse proxy | ||
# or by a library like `asgi-correlation-id`. | ||
fields["rid"] = info["request_headers"]["x-request-id"] | ||
except KeyError: | ||
pass |
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.
Should we use setdefault
, then build fields after that?
info["request_headers"].setdefault("x-request-id", uuid4())
fields = {
...,
"rid": info["request_headers"]["x-request-id"]
}
Almost, but it seems like I like the idea of Option 1, whether we actually use Options 2 feels brittle. Option 3 looks pretty good too. |
There's already something in the other integrations: python-dockerflow/src/dockerflow/sanic/app.py Line 133 in c939637
python-dockerflow/src/dockerflow/flask/app.py Line 191 in c939637
but does not read it from a header that would be set by the reverse proxy (which is the ideal since it would be tracked along the whole stack)
I also have a preference for Option 1, because in practice we will use this package in our services. And in the end, Option 3 consists in maintaining (and documenting) an abstraction that does not seem to bring much value |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #100 +/- ##
==========================================
+ Coverage 97.97% 98.02% +0.05%
==========================================
Files 22 22
Lines 692 710 +18
Branches 92 96 +4
==========================================
+ Hits 678 696 +18
Misses 8 8
Partials 6 6 ☔ View full report in Codecov by Sentry. |
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.
LGTM.
I don't know how valuable these tests would be (maybe only to validate our documentation) but I'm thinking:
-
Is it okay for users to add
MozlogRequestSummaryLogger
withoutCorrelationIdMiddleware
? If that happens, should we still try to get theX-Request-Id
header for therid
field, or omit it? Whatever we decide, having a test that covers this possibility would be good. -
Can we set up a test that demonstrates the
rid
being passed down into the call stack? Something like:
(diff)
diff --git a/tests/fastapi/test_fastapi.py b/tests/fastapi/test_fastapi.py
index 7770441..e553b2d 100644
--- a/tests/fastapi/test_fastapi.py
+++ b/tests/fastapi/test_fastapi.py
@@ -15,12 +15,21 @@ from dockerflow.fastapi.middleware import (
MozlogRequestSummaryLogger,
)
+def pong():
+ logger = logging.getLogger("some_logger")
+ logger.info("returning pong")
+ return "pong"
def create_app():
app = FastAPI()
app.include_router(dockerflow_router)
app.add_middleware(MozlogRequestSummaryLogger)
app.add_middleware(CorrelationIdMiddleware, validator=None)
+
+ @app.get("/ping")
+ def ping():
+ return pong()
+
return app
@@ -160,3 +169,8 @@ def test_heartbeat_custom_name(client):
response = client.get("/__heartbeat__")
assert response.json()["checks"]["my_check_name"]
+
+def test_rid_passed_down(client, caplog):
+ client.get("/ping", headers={"X-Request-ID": "tracked-value"})
+ assert caplog.records[0].rid == "tracked-value"
+ assert caplog.records[1].rid == "tracked-value"
we might also have to wire up some logging config like we do with JBI (filter, adding the filter to the log config), but it would be good to have a full example documented
I realized that tools like
asgi-correlation-id
for FastAPI add this header.https://github.com/snok/asgi-correlation-id/blob/7665c31af175de194a8b1f051b71d25ea18c5187/asgi_correlation_id/middleware.py#L83-L86
However I don't really like it to be hard-coded, and would welcome any suggestion.
Option 0
This PR, hard-coded. But in the end, the header name
X-Request-ID
is almost like a defacto standard, and very unlikely to be customized.Option 1
Include
asgi-correlation-id
by default as part of fastapi extras dependencies, and mention middleware in docs or introduce adockerflow.setup(app)
function that does all the cablingOption 2
Introspect
app.user_middleware
list, and look forAsgiCorrelationMiddleware
to read itsheader_name
attributehttps://github.com/encode/starlette/blob/a4cd0b5506ac2fd3fa0ce1e967f019b94df87b97/starlette/applications.py#L142C14-L142C29
Option 3
Read header name from a constant in
app.state
dict...(and let consumer app be responsible of setting it / aligning it with
AsgiCorrelationMiddleware
header_name
param, etc.)Option 4
?