-
Notifications
You must be signed in to change notification settings - Fork 832
feat: simplify query related modules #3320
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
feat: simplify query related modules #3320
Conversation
a0602fe
to
ba42f0d
Compare
bdc90fd
to
349e68d
Compare
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.
@jtlisi I tried my best to follow this refactoring but I found it a bit hard. The new design looks good to me, but I find difficult to understand if we're introducing any regression. I left few questions.
pkg/api/handlers.go
Outdated
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.
Am I missing anything, or promRouter
and legacyPromRouter
don't have middlewares
attached?
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.
The purpose for these routers is that they are compatible with the upstream Prometheus API struct route registration function. But we end up needing two of them because we register the routes on two separate path prefixes. Since we consolidate them both under another router that we instantiate in this function, it's easier to register the middleware with that router instead of individually with both of these routers.
We could wrap these two routers individually with the middleware as we did previously. However, that seems a bit redundant.
pkg/cortex/modules.go
Outdated
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.
// If queries processed using the external HTTP Server, we need wrap the internalHandler with | |
// If queries are processed using the external HTTP Server, we need wrap the internalHandler with |
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.
Also, what's internalHandler
?
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.
In this case the internalHandler is the router that's returned by NewQuerierHandler
. I say internalHandler in the sense that it is not the main router that is registered with the weaveworks common HTTP server to handle external requests. Any request forwarded to the internalHandler must either go through the external HTTP server router first or be passed to it from the frontend worker.
Maybe a clearer term would be internalQuerierRouter
?
pkg/api/api.go
Outdated
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.
Who register these now?
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.
These routes are registered with the two routers when we call api.Register on them. We end up having to register two routers because the upstream prometheus route library and registration function requires us to register separately for each path prefix.
Previously we explicitly registered every route in the Prometheus API to query handler. However, now we only explicitly register the metadata
and read
routes because they aren't handled by the upstream API struct. For the rest we register the prefix and since the promHandler
and legacyPromHandler
are themselves routers, the requests should be forwarded correctly.
Also I should note that the only way to hit these routes is by a request being routed to the internalQuerierHandler
which can only happen if it hit's the routes registered in RegisterQueryAPI
, so no new routes should have been exposed and no existing routes should have been removed. This PR just simplified the router that already was only acting as a middleman to the upstream Prometheus routers we already registered with the API struct.
1820ab9
to
af7651a
Compare
ea6118f
to
45851b2
Compare
@pracucci I added a diagram that I hope makes things a bit clearer. Let me know if you find it helpful or not. Otherwise I can remove it since it adds a good amount of LOC. |
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.
Makes sense to me why we want this, although it looks bit scary. 🤞
func (t *Cortex) initQueryFrontend() (serv services.Service, err error) { | ||
// initQueryFrontendTripperware instantiates the tripperware used by the query frontend | ||
// to optimize Prometheus query requests. | ||
func (t *Cortex) initQueryFrontendTripperware() (serv services.Service, err error) { |
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.
Nice!
pkg/api/handlers.go
Outdated
// A prefix is fine because external routes will be registered explicitly | ||
router.PathPrefix(cfg.LegacyHTTPPrefix + "/api/v1/").Handler(legacyPromRouter) | ||
|
||
// Since we have a new router and the request will not go trough the default server |
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.
Does this comment still apply?
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.
I think it would make sense to reword it or remove it but keep the tracing instrumentation since it can be useful to have a span for this particular router
|
||
// initQuerier registers an internal HTTP router with a Prometheus API backed by the | ||
// Cortex Queryable. Then it does one of the following: | ||
// 1. Query-Frontend Enabled: If Cortex has an All or QueryFrontend target, the internal |
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.
To make sure comment is formatted properly, please put empty lines between paragraphs (or list items), and don't use extra space at the beginning of the lines (except for diagram below) -- such lines are formatted as code according to Go doc conventions.
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.
I will update this to match the conventions
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.
Thanks. It helps tools to format it properly. (eg. GoLand :))
// If queries are processed using the external HTTP Server, we need wrap the internal querier with | ||
// HTTP router with middleware to parse the tenant ID from the HTTP header and inject it into the | ||
// request context. | ||
internalQuerierRouter = middleware.AuthenticateUser.Wrap(internalQuerierRouter) |
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.
We didn't do this before, did we? Why is it needed now?
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.
Actually, we did do this before because we previously used the registerRouteWithRouter
function built into the API struct which applies this middleware. Now we just register the routes directly with with the router using the Path|PathPrefix
function.
Signed-off-by: Jacob Lisi <[email protected]>
Signed-off-by: Jacob Lisi <[email protected]>
Signed-off-by: Jacob Lisi <[email protected]>
Signed-off-by: Jacob Lisi <[email protected]>
Signed-off-by: Jacob Lisi <[email protected]>
f9fc990
to
a13a0c4
Compare
Signed-off-by: Jacob Lisi <[email protected]>
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, thanks!
What this PR does:
querier
module into two modules:querier
andqueryable
.queryrange
tripperware from thequery-frontend
The goal of this PR is to simplify the setup of the querier and make it clearer how requests are routed to the querier when running with or without the query-frontend enabled simultaneously and to decouple the initialization of the default queryable and the initialization of the request processing/handling code.
I did my best in this PR to comment/clarify how the routing for the querier is instantiated when running standalone or as a part of single-binary.
Checklist
CHANGELOG.md
updated - the order of entries should be[CHANGE]
,[FEATURE]
,[ENHANCEMENT]
,[BUGFIX]