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

Generalise some of Mimir's query sharding code to be more reusable #9363

Merged
merged 4 commits into from
Sep 30, 2024

Conversation

zenador
Copy link
Contributor

@zenador zenador commented Sep 22, 2024

What this PR does

Generalise some of Mimir's query sharding code to be more reusable for other kinds of sharded queries.

Which issue(s) this PR fixes or relates to

Follow up to #8755

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.

No docs as these are minor, non-user-facing changes.

@zenador zenador requested a review from a team as a code owner September 22, 2024 17:52
@zenador zenador marked this pull request as draft September 22, 2024 18:01
@charleskorn charleskorn self-requested a review September 24, 2024 03:01
@zenador zenador marked this pull request as ready for review September 30, 2024 04:05
@@ -755,6 +817,90 @@ func (c prometheusCodec) DecodeResponse(ctx context.Context, r *http.Response, _
return resp, nil
}

func (c prometheusCodec) DecodeLabelsQueryResponse(ctx context.Context, r *http.Response, lr LabelsQueryRequest, logger log.Logger) (Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be split in half, one half for labels and another for series responses?

Or is there a reason to keep them in one method like this?

(same applies for EncodeLabelsQueryResponse)

Copy link
Contributor Author

@zenador zenador Sep 30, 2024

Choose a reason for hiding this comment

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

I kept it as one because the LabelsQueryRequest is used for label names, label values and series because their request formats are all fairly similar and this function outputs a Response which works for all three hence the signatures are the same, and I don't want to clutter this with more functions that do almost the same thing, and only differentiate between the labels and series in the formatter interface (they have different signatures since the response formats are different).

Copy link
Contributor

Choose a reason for hiding this comment

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

fwiw I tend to agree with Charles. It's less surprising if we have the separation in all places. Now DecodeLabelsResponse and DecodeLabelsQueryResponse work for different sets of requests.

pkg/frontend/querymiddleware/querysharding.go Outdated Show resolved Hide resolved
pkg/frontend/querymiddleware/roundtrip.go Outdated Show resolved Hide resolved
@zenador zenador enabled auto-merge (squash) September 30, 2024 09:20
@zenador zenador merged commit 97f0319 into main Sep 30, 2024
29 checks passed
@zenador zenador deleted the zenador/prep-ccqf-middleware branch September 30, 2024 23:56
Copy link
Contributor

@dimitarvdimitrov dimitarvdimitrov left a comment

Choose a reason for hiding this comment

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

i was catching up with the code written so far for this project and left a few comments. Do what you will with them 😄

Comment on lines +267 to +268
name: "successful series response",
request: &PrometheusSeriesQueryRequest{},
Copy link
Contributor

Choose a reason for hiding this comment

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

should this also test for label names?

@@ -755,6 +817,90 @@ func (c prometheusCodec) DecodeResponse(ctx context.Context, r *http.Response, _
return resp, nil
}

func (c prometheusCodec) DecodeLabelsQueryResponse(ctx context.Context, r *http.Response, lr LabelsQueryRequest, logger log.Logger) (Response, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

fwiw I tend to agree with Charles. It's less surprising if we have the separation in all places. Now DecodeLabelsResponse and DecodeLabelsQueryResponse work for different sets of requests.

isSeriesResponse: false,
},
{
name: "successful series response",
Copy link
Contributor

Choose a reason for hiding this comment

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

same as above - test with label names too?

Path string
Start int64
End int64
// labelMatcherSets is a repeated field here in order to enable the representation
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: labelMatcherSets->LabelMatcherSets to make it a godoc

Comment on lines +486 to +574
func (r *PrometheusSeriesQueryRequest) GetStartOrDefault() int64 {
if r.GetStart() == 0 {
return v1.MinTime.UnixMilli()
}
return r.GetStart()
}

func (r *PrometheusSeriesQueryRequest) GetEndOrDefault() int64 {
if r.GetEnd() == 0 {
return v1.MaxTime.UnixMilli()
}
return r.GetEnd()
}

func (r *PrometheusLabelNamesQueryRequest) GetHeaders() []*PrometheusHeader {
return r.Headers
}

func (r *PrometheusLabelValuesQueryRequest) GetHeaders() []*PrometheusHeader {
return r.Headers
}

func (r *PrometheusSeriesQueryRequest) GetHeaders() []*PrometheusHeader {
return r.Headers
}

// WithLabelName clones the current `PrometheusLabelNamesQueryRequest` with a new label name param.
func (r *PrometheusLabelNamesQueryRequest) WithLabelName(string) (LabelsQueryRequest, error) {
panic("PrometheusLabelNamesQueryRequest.WithLabelName is not implemented")
}

// WithLabelName clones the current `PrometheusLabelValuesQueryRequest` with a new label name param.
func (r *PrometheusLabelValuesQueryRequest) WithLabelName(name string) (LabelsQueryRequest, error) {
newRequest := *r
newRequest.Path = labelValuesPathSuffix.ReplaceAllString(r.Path, `/api/v1/label/`+name+`/values`)
newRequest.LabelName = name
return &newRequest, nil
}

// WithLabelName clones the current `PrometheusSeriesQueryRequest` with a new label name param.
func (r *PrometheusSeriesQueryRequest) WithLabelName(string) (LabelsQueryRequest, error) {
panic("PrometheusSeriesQueryRequest.WithLabelName is not implemented")
}

// WithLabelMatcherSets clones the current `PrometheusLabelNamesQueryRequest` with new label matcher sets.
func (r *PrometheusLabelNamesQueryRequest) WithLabelMatcherSets(labelMatcherSets []string) (LabelsQueryRequest, error) {
newRequest := *r
newRequest.LabelMatcherSets = make([]string, len(labelMatcherSets))
copy(newRequest.LabelMatcherSets, labelMatcherSets)
return &newRequest, nil
}

// WithLabelMatcherSets clones the current `PrometheusLabelValuesQueryRequest` with new label matcher sets.
func (r *PrometheusLabelValuesQueryRequest) WithLabelMatcherSets(labelMatcherSets []string) (LabelsQueryRequest, error) {
newRequest := *r
newRequest.LabelMatcherSets = make([]string, len(labelMatcherSets))
copy(newRequest.LabelMatcherSets, labelMatcherSets)
return &newRequest, nil
}

// WithLabelMatcherSets clones the current `PrometheusSeriesQueryRequest` with new label matcher sets.
func (r *PrometheusSeriesQueryRequest) WithLabelMatcherSets(labelMatcherSets []string) (LabelsQueryRequest, error) {
newRequest := *r
newRequest.LabelMatcherSets = make([]string, len(labelMatcherSets))
copy(newRequest.LabelMatcherSets, labelMatcherSets)
return &newRequest, nil
}

// WithHeaders clones the current `PrometheusLabelNamesQueryRequest` with new headers.
func (r *PrometheusLabelNamesQueryRequest) WithHeaders(headers []*PrometheusHeader) (LabelsQueryRequest, error) {
newRequest := *r
newRequest.Headers = cloneHeaders(headers)
return &newRequest, nil
}

// WithHeaders clones the current `PrometheusLabelValuesQueryRequest` with new headers.
func (r *PrometheusLabelValuesQueryRequest) WithHeaders(headers []*PrometheusHeader) (LabelsQueryRequest, error) {
newRequest := *r
newRequest.Headers = cloneHeaders(headers)
return &newRequest, nil
}

// WithHeaders clones the current `PrometheusSeriesQueryRequest` with new headers.
func (r *PrometheusSeriesQueryRequest) WithHeaders(headers []*PrometheusHeader) (LabelsQueryRequest, error) {
newRequest := *r
newRequest.Headers = cloneHeaders(headers)
return &newRequest, nil
}

Copy link
Contributor

Choose a reason for hiding this comment

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

nit on ordering: we usually put the methods of a struct below the struct not with methods of the same name of other structs. I see you did this for some of the methods, but not these ones here

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.

3 participants