fix(logs): the browser's copy of a polled read is quiet too

The server now logs polled reads at DEBUG, and the browser's copy of each
request line promises the server's level: at INFO the unread-count polls
filled My log within minutes and, at Detailed, the shipped log. The server
marks a line it logged at DEBUG with X-Log-Quiet, so the polled-route list
stays in one place.
This commit is contained in:
2026-09-19 05:03:31 +02:00
parent 6bbf532b70
commit 6cb8231a9f
5 changed files with 40 additions and 10 deletions
+4
View File
@@ -738,6 +738,10 @@ async def log_requests(request, call_next):
extra={**event("http.request", **attrs), **_request_owner(request, level)},
)
response.headers["X-Request-Id"] = rid
# The browser logs its own copy of this line (frontend lib/http.ts) and must pick the same level:
# it learns "this one is quiet" here instead of keeping a second copy of the polled-route list.
if level == logging.DEBUG:
response.headers["X-Log-Quiet"] = "1"
# The template, so the browser's copy of this line groups the same way (frontend lib/http.ts).
# Only a MATCHED route's: a template never carries a path parameter's value (a share token stays
# `{token}`), while the raw-path fallback of an unmatched request could — the browser then
+5 -2
View File
@@ -337,10 +337,13 @@ def test_a_polled_read_is_debug_a_write_to_the_same_route_is_not(sink):
http = logging.getLogger("siftlode.http")
http.setLevel(logs.TRACE)
client = _client()
client.get("/api/messages/unread_count")
r = client.get("/api/messages/unread_count")
assert sink.objects()[-1]["level"] == "DEBUG"
client.post("/api/messages/unread_count")
# ...and says so, for the browser's copy of the line (frontend lib/http.ts).
assert r.headers["X-Log-Quiet"] == "1"
r = client.post("/api/messages/unread_count")
assert sink.objects()[-1]["level"] == "INFO"
assert "X-Log-Quiet" not in r.headers
client.get("/api/videos/abc")
assert sink.objects()[-1]["level"] == "INFO"