Skip to content

Commit 3f9a8f0

Browse files
authored
Fix #768: log validation exceptions (HTTP 422) (#780)
1 parent c37708d commit 3f9a8f0

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

jbi/app.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
from typing import Any, Awaitable, Callable
99

1010
import sentry_sdk
11-
from fastapi import FastAPI, Request, Response
11+
from fastapi import FastAPI, Request, Response, status
12+
from fastapi.encoders import jsonable_encoder
13+
from fastapi.exceptions import RequestValidationError
14+
from fastapi.responses import JSONResponse
1215
from fastapi.staticfiles import StaticFiles
1316

1417
from jbi.environment import get_settings, get_version
@@ -20,6 +23,8 @@
2023
settings = get_settings()
2124
version_info = get_version()
2225

26+
logger = logging.getLogger(__name__)
27+
2328

2429
def traces_sampler(sampling_context: dict[str, Any]) -> float:
2530
"""Function to dynamically set Sentry sampling rates"""
@@ -75,7 +80,29 @@ async def request_summary(
7580
return response
7681
except Exception as exc:
7782
log_fields = format_request_summary_fields(
78-
request, request_time, status_code=500
83+
request, request_time, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
7984
)
8085
summary_logger.info(exc, extra=log_fields)
8186
raise
87+
88+
89+
@app.exception_handler(RequestValidationError)
90+
async def validation_exception_handler(
91+
request: Request, exc: RequestValidationError
92+
) -> Response:
93+
"""
94+
Override the default exception handler for validation
95+
errors in order to log some information about malformed
96+
requests.
97+
"""
98+
logger.error(
99+
"invalid incoming request: %s",
100+
exc,
101+
extra={
102+
"errors": exc.errors(),
103+
},
104+
)
105+
return JSONResponse(
106+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
107+
content={"detail": jsonable_encoder(exc.errors())},
108+
)

tests/unit/test_app.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,21 @@ def test_request_summary_is_logged(caplog):
2828
assert summary.querystring == "{}"
2929

3030

31+
def test_422_errors_are_logged(webhook_create_example, caplog):
32+
webhook_create_example.bug = None
33+
34+
with TestClient(app) as anon_client:
35+
with caplog.at_level(logging.INFO):
36+
anon_client.post("/bugzilla_webhook", data=webhook_create_example.json())
37+
38+
logged = [r for r in caplog.records if r.name == "jbi.app"][0]
39+
assert logged.errors[0]["loc"] == ("body", "bug")
40+
assert (
41+
logged.errors[0]["msg"]
42+
== "Input should be a valid dictionary or object to extract fields from"
43+
)
44+
45+
3146
def test_request_summary_defaults_user_agent_to_empty_string(caplog):
3247
with caplog.at_level(logging.INFO):
3348
with TestClient(app) as anon_client:

0 commit comments

Comments
 (0)