Skip to content
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

Early Request Validation in Query Frontend #10093

Merged
merged 7 commits into from
Dec 6, 2024

Conversation

francoposa
Copy link
Member

@francoposa francoposa commented Dec 2, 2024

What this PR does

This PR introduces early request validation for the majority of request types supported by the query-frontend.
This specifically does not introduce any new request parsing or validation logic, but it ensures that the validation that does exist is called in the first roundtripper, before any other work is done and that a standardized 400 Bad Request APIError is returned.

The tests are largely focused on making sure we get a status 400 API Error when we expect one - each request validator roundtripper relies on existing validation codecs which have their own extensive test suites.

Done so far are the ones that have clearly defined validation code already in Mimir:

  • instant query
  • range query
  • label names query
  • label values query
  • series query
  • label names cardinality
  • label values cardinality
  • active series cardinality

Still to be done, likely saved for a subsequent PR are:

  • metadata
  • query exemplars
  • active native histogram metrics cardinality requests

Which issue(s) this PR fixes or relates to

In previous incidents we have seen unexpected issues when parsing an invalid requests errors out in a part of the stack which is not set up to propagate the errors properly back up the stack and prevent breaking connections or crashing goroutines.

Checklist

  • Tests updated.
  • Documentation added.
  • CHANGELOG.md updated - the order of entries should be [CHANGE], [FEATURE], [ENHANCEMENT], [BUGFIX].
  • about-versioning.md updated with experimental features.

@@ -186,26 +186,6 @@ func TestTripperware_InstantQuery(t *testing.T) {
}, res)
})

t.Run("specific time param with form being already parsed", func(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these tests are for old code that was removed as it is more robustly handled in the prometheus codec and associated utils.

The tests continued to pass by chance that we weren't using this particular request parsing middleware twice.

We have moved away from trying to go back and fix the situation if the request body is consumed by our own middleware. Instead everything that reads a request body just needs to use ParseRequestFormWithoutConsumingBody introduced in #5524.

@francoposa francoposa marked this pull request as ready for review December 4, 2024 22:02
@francoposa francoposa requested a review from a team as a code owner December 4, 2024 22:02
queryrange = NewMetricsQueryRequestValidationRoundTripper(codec, queryrange)
instant = NewMetricsQueryRequestValidationRoundTripper(codec, instant)
labels = NewLabelsQueryRequestValidationRoundTripper(codec, labels)
series = NewLabelsQueryRequestValidationRoundTripper(codec, series)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Series Request validation is also supported by the codec for Label Names and Label Values Requests - a separate PR exists to update the naming for the codecs to express this

@francoposa francoposa force-pushed the francoposa/query-frontend-request-validation branch from 0e296ea to 6c336d2 Compare December 4, 2024 22:19
Copy link
Contributor

@56quarters 56quarters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are in a maze of handlers, middlewares, roundtrippers, and tripperwares, all alike.

This change LGTM and is a definite improvement.

However, it feels weird that we're parsing/decoding requests multiple times. There's some existing functionality that adds QueryDetails to the context of a request. WDYT about doing something similar, adding the parsed request from the validation roundtrippers to the context of each request so that every subsequent roundtripper doesn't need to repeat the parsing process in a follow-up PR? It's fine if the answer to that is "that'd just make things more complicated"

@francoposa
Copy link
Member Author

However, it feels weird that we're parsing/decoding requests multiple times. There's some existing functionality that adds QueryDetails to the context of a request. WDYT about doing something similar, adding the parsed request from the validation roundtrippers to the context of each request so that every subsequent roundtripper doesn't need to repeat the parsing process in a follow-up PR? It's fine if the answer to that is "that'd just make things more complicated"

@56quarters I will scratch that out and see how it looks - the multiple parse is definitely something we want to get away from and this context approach could be a good band-aid in the mean time.
Getting the parsing done early in the roundtripper stack like this PR does is one step towards getting away from multiple parse.

There's still a bit of work to get to a point where we can have roundtrippers that can take a MetricsQueryRequest or LabelsSeriesQueryRequest as an argument.
Right now the roundtrippers that handle several request types they do so by taking http.Request and switch on the request type by matching on URL patterns, meaning they would not support getting passed only a MetricsQueryRequest or LabelsSeriesQueryRequest directly in the signature.
We'd either need to apply a generics or split the signatures so there's different roundtripper paths for each parsed request type, which requires some level of accounting for which aspects of a request each roundtripper needs access to.

@francoposa francoposa merged commit 3251e86 into main Dec 6, 2024
29 checks passed
@francoposa francoposa deleted the francoposa/query-frontend-request-validation branch December 6, 2024 21:17
francoposa added a commit that referenced this pull request Dec 6, 2024
bjorns163 pushed a commit to bjorns163/mimir that referenced this pull request Dec 30, 2024
* WIP sketch out validation roundtripper with existing metrics and labels query codecs

* lint: license header

* separate series request roundtrippers

* introduce request validation roundtripper tests

* lint import order

* introduce & test cardinality query validation in frontend roundtripper; expand metrics query tests to cover instant queries

* CHANGELOG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants