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

Distributor: /all_user_stats now show API and Rule Ingest Rate correctly #2457

Merged
merged 10 commits into from
Apr 16, 2020

Conversation

Wing924
Copy link
Contributor

@Wing924 Wing924 commented Apr 14, 2020

Signed-off-by: Wing924 weihe924stephen@gmail.com

What this PR does:

  • Distributor: /all_user_stats now show API and Rule Ingest Rate correctly.

Which issue(s) this PR fixes:
Fixes #2171

Checklist

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

…Rate correctly.

Signed-off-by: Wing924 <weihe924stephen@gmail.com>
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
pkg/ruler/compat.go Outdated Show resolved Hide resolved
_, err := util.ParseProtoReader(r.Context(), r.Body, int(r.ContentLength), cfg.MaxRecvMsgSize, &req, compressionType)
logger := util.WithContext(r.Context(), util.Logger)
if err != nil {
level.Error(logger).Log("err", err.Error())
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
req.Source = client.API
Copy link
Contributor

Choose a reason for hiding this comment

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

why did this move?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

_, err := util.ParseProtoReader(r.Context(), r.Body, int(r.ContentLength), cfg.MaxRecvMsgSize, &req, compressionType) overwrite that value.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that was deliberate: if the caller supplies a value then we use that, otherwise we fall back to API.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tested here and I'm sure util.ParseProtoReader will overwrite req.Source to 0.
Because client.API equals to 0, you may not notice it.

reproduce

diff --git a/pkg/ingester/client/cortex.proto b/pkg/ingester/client/cortex.proto
index 6a341b59..a9dfcfee 100644
--- a/pkg/ingester/client/cortex.proto
+++ b/pkg/ingester/client/cortex.proto
@@ -30,7 +30,8 @@ service Ingester {
 message WriteRequest {
   repeated TimeSeries timeseries = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "PreallocTimeseries"];
   enum SourceEnum {
-    API = 0;
+    UNKNOWN_SOURCE = 0;
+    API = 2;
     RULE = 1;
   }
   SourceEnum Source = 2;

and print req.Source before and afterutil.ParseProtoReader.

result:

  • before is API
  • after is UNKNOWN_SOURCE

Copy link
Contributor

Choose a reason for hiding this comment

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

Did you test it with and without the caller supplying a value in the protobuf?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just test it with real remote write from distributor.
I don't think remote write protobuf have Source field.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree on @Wing924 on this. The source is not part of the remote write protocol, so we need to inject it after the WriteRequest has been deseralized, otherwise the deserialization will overwrite it with the default value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added test to cover both prometheus remote write and cortex writerequest.

Signed-off-by: Wing924 <weihe924stephen@gmail.com>
@Wing924 Wing924 changed the title [BUGFIX] Distributor: /all_user_stats now show API and Rule Ingest Rate correctly. [BUGFIX] Distributor: /all_user_stats now show API and Rule Ingest Rate correctly; reuse []Timeseries in ruler to reduce memory allocation. Apr 14, 2020
@Wing924 Wing924 changed the title [BUGFIX] Distributor: /all_user_stats now show API and Rule Ingest Rate correctly; reuse []Timeseries in ruler to reduce memory allocation. Distributor: /all_user_stats now show API and Rule Ingest Rate correctly; reuse []Timeseries in ruler to reduce memory allocation. Apr 14, 2020
Copy link
Contributor

@gouthamve gouthamve left a comment

Choose a reason for hiding this comment

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

LGTM!

@Wing924 Wing924 requested a review from bboreham April 14, 2020 11:11
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
@Wing924 Wing924 changed the title Distributor: /all_user_stats now show API and Rule Ingest Rate correctly; reuse []Timeseries in ruler to reduce memory allocation. Distributor: /all_user_stats now show API and Rule Ingest Rate correctly Apr 14, 2020
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
Copy link
Contributor

@pracucci pracucci left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! LGTM

_, err := util.ParseProtoReader(r.Context(), r.Body, int(r.ContentLength), cfg.MaxRecvMsgSize, &req, compressionType)
logger := util.WithContext(r.Context(), util.Logger)
if err != nil {
level.Error(logger).Log("err", err.Error())
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
req.Source = client.API
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree on @Wing924 on this. The source is not part of the remote write protocol, so we need to inject it after the WriteRequest has been deseralized, otherwise the deserialization will overwrite it with the default value.

Signed-off-by: Wing924 <weihe924stephen@gmail.com>
@pull-request-size pull-request-size bot added size/L and removed size/S labels Apr 15, 2020
Wing924 added 4 commits April 15, 2020 18:55
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
Copy link
Contributor

@jtlisi jtlisi left a comment

Choose a reason for hiding this comment

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

LGTM

@gouthamve gouthamve merged commit 88400e1 into cortexproject:master Apr 16, 2020
@Wing924 Wing924 deleted the fix_user_stats branch April 16, 2020 08:44
Copy link
Contributor

@bboreham bboreham left a comment

Choose a reason for hiding this comment

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

This should not have been merged.

Comment on lines +27 to +29
if req.Source == 0 {
req.Source = client.API
}
Copy link
Contributor

Choose a reason for hiding this comment

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

As per our instructions, every commit must explain the changes made. This is an extraordinary change, so needs a very good explanation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll send another PR to add comment here.

Comment on lines +27 to +29
if req.Source == 0 {
req.Source = client.API
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Getting back to this change, @bboreham as right and I was wrong. The req.Source is not overridden by the unmarshalling if not included in the request, so we should have fixed the issue to the root: ensuring Source is always set within Cortex.

https://github.com/cortexproject/cortex/blob/master/pkg/ingester/client/cortex.pb.go#L5502-L5520

@Wing924 May you re-iterate on this?

Copy link
Contributor Author

@Wing924 Wing924 Apr 16, 2020

Choose a reason for hiding this comment

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

The req.Source is not overridden by the unmarshalling if not included in the request

It's not true.

Let's change the code like this:

+ req.Source = 2
		_, err := util.ParseProtoReader(r.Context(), r.Body, int(r.ContentLength), cfg.MaxRecvMsgSize, &req, compressionType)
		logger := util.WithContext(r.Context(), util.Logger)
		if err != nil {
			level.Error(logger).Log("err", err.Error())
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
- if req.Source == 0 {
- 	req.Source = client.API
- }

if Source is not included in the request, we expect req.Source is 2, right?
But actually it's 0.
You can check my test.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

How about you explain your change, where I have substituted one const value with its definition for clarity:

if req.Source == 0 {
	req.Source = 0
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I know client.API is equals to 0 so that you think these code is useless.
This code is explicitly set default value if req.Source is not set.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Physically, client.API equals to 0, but logically, they are different things.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, the Reset() is indeed the important line, thanks.
So the original code didn't do anything (it set to 0 which was then overridden to 0) and the new code doesn't do anything.

bboreham added a commit that referenced this pull request Apr 16, 2020
The meaning of the code as-was is that we initialise to `API` but
allow the unmarshal code to override.

Tests were added in #2457 to confirm this works as expected.

Signed-off-by: Bryan Boreham <bryan@weave.works>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[bug] /all_user_stats don't show correct Rule Ingest Rate
5 participants