Commit cf01d83
fix: scope activity tracking middleware to query routes only (#15129)
#### What this PR does
Scopes the activity tracking middleware to query routes only, preventing
it from rejecting write requests with HTTP 500 when clients send an
unexpected `Content-Type` header.
**Root cause**: PR #14777 moved activity tracking from the
query-frontend transport handler into `newRoute()`, which wraps *all*
registered HTTP routes. This was intended to cover query-frontend
routes, but as a side effect it also wraps the push endpoint
(`/api/v1/push`), distributor OTLP endpoint, alertmanager routes, etc.
When a client sends a push request with `Content-Type:
application/x-www-form-urlencoded` (instead of the expected
`application/x-protobuf`), the activity tracking middleware attempts to
parse the protobuf body as form data. Go 1.17+ rejects semicolons as
query separators (`url.ParseQuery`), and since random protobuf bytes
inevitably contain `0x3B` (`;`), parsing fails with `"invalid semicolon
separator in query"`. The middleware then returns HTTP 500 before the
request reaches the actual push handler.
**Impact observed**: ~3500 rps of 500 errors on a dedicated Mimir
cluster (`prod-us-east-1/mimir-dedicated-17`), with the distributor
rejecting all affected push requests. The SLI dropped to 0.178 (~82%
write failure rate), triggering a critical SLO burn rate alert.
**Fix**: Gate the activity tracking middleware on `maxBodySizeIfAny > 0`
in `newRoute()`. This condition matches exactly the routes that PR
#14777 intended to cover — all query API routes registered via
`RegisterQueryAPI`/`RegisterQueryFrontendHandler` pass a non-zero
`maxBodySizeIfAny`, while `RegisterRoute` (used for push, alertmanager,
etc.) passes `0`.
#### Which issue(s) this PR fixes or relates to
Follow-up fix to #14777
#### Checklist
- [x] Tests updated.
- [ ] Documentation added.
- [x] `CHANGELOG.md` updated - the order of entries should be
`[CHANGE]`, `[FEATURE]`, `[ENHANCEMENT]`, `[BUGFIX]`. If changelog entry
is not needed, please add the `changelog-not-needed` label to the PR.
- [ ]
[`about-versioning.md`](https://github.com/grafana/mimir/blob/main/docs/sources/mimir/configure/about-versioning.md)
updated with experimental features.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches HTTP middleware composition for all registered routes; while
the change is small and tested, it could affect which endpoints get
activity tracking and how some requests are handled.
>
> **Overview**
> Prevents the activity-tracking middleware from wrapping
non-query/write endpoints (eg. `/api/v1/push`) by only enabling it for
routes registered with a non-zero `maxBodySizeIfAny`.
>
> Adds a regression test ensuring a push request with an unexpected
`Content-Type: application/x-www-form-urlencoded` and protobuf-like body
reaches the inner handler (avoiding a Go form-parsing error/HTTP 500),
and documents the fix in `CHANGELOG.md`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
8df3481. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Signed-off-by: Yuri Nikolic <durica.nikolic@grafana.com>
Co-authored-by: Yuri Nikolic <durica.nikolic@grafana.com>
Co-authored-by: Andrew Hall <andrew.hall@grafana.com>1 parent aced80d commit cf01d83
3 files changed
Lines changed: 44 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
200 | 200 | | |
201 | 201 | | |
202 | 202 | | |
| 203 | + | |
203 | 204 | | |
204 | 205 | | |
205 | 206 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
195 | 195 | | |
196 | 196 | | |
197 | 197 | | |
198 | | - | |
| 198 | + | |
199 | 199 | | |
200 | 200 | | |
201 | 201 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
378 | 379 | | |
379 | 380 | | |
380 | 381 | | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
0 commit comments