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

add influx push endpoint to mimir #10153

Draft
wants to merge 36 commits into
base: main
Choose a base branch
from
Draft

Conversation

alexgreenbank
Copy link

WIP - early draft - do not bother looking at yet

Early commit(s) are just importing the original code from #1971 which will not compile within latest codebase.

--

What this PR does

Which issue(s) this PR fixes or relates to

Fixes #

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.

@CLAassistant
Copy link

CLAassistant commented Dec 6, 2024

CLA assistant check
All committers have signed the CLA.

Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
@alexgreenbank alexgreenbank requested a review from colega December 16, 2024 15:17
pkg/api/api.go Outdated
Comment on lines 272 to 273
// TODO(alexg): hidden behind a featureflag or experimental config option?
a.RegisterRoute(InfluxPushEndpoint, distributor.InfluxHandler(
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think a feature flag for this is needed. We can just state in the docs (about-versioning.md) that the endpoint is experimental.

Copy link
Author

Choose a reason for hiding this comment

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

OK, done.

Comment on lines 38 to 41
level.Debug(spanLogger).Log(
"msg", "decodeAndConvert complete",
"bytesRead", bytesRead,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Opinionated style nit: I don't think we need 4 lines for this debug log.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed in next push.

"bytesRead", bytesRead,
)
if err != nil {
level.Error(logger).Log("err", err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this logger have all the required context? Can you also add some context here about what was going on when this happened? I'm scared of finding this log:

ts=2024-12-17 err="unexpected EOF"

Also, nit, .Error() call is not needed, just pass err.

Copy link
Author

Choose a reason for hiding this comment

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

Agreed, fixed in next push.

"github.com/grafana/dskit/grpcutil"
"github.com/grafana/dskit/httpgrpc"
"github.com/grafana/dskit/middleware"
io2 "github.com/influxdata/influxdb/v2/kit/io"
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
io2 "github.com/influxdata/influxdb/v2/kit/io"
influxio "github.com/influxdata/influxdb/v2/kit/io"

Copy link
Author

Choose a reason for hiding this comment

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

Agreed, fixed in next push.

"github.com/grafana/mimir/pkg/util/spanlogger"
)

func parser(ctx context.Context, r *http.Request, maxSize int, _ *util.RequestBuffers, req *mimirpb.PreallocWriteRequest, logger log.Logger) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

This function lives in pkg/distributor, I would say it's a little bit pretentious to take the name parser for this :D

How about influxRequestParser?

Copy link
Author

Choose a reason for hiding this comment

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

Agreed, fixed in next push.

Comment on lines 93 to 94
// TODO(alexg): Do we even need httpgrpc here?
// Check for httpgrpc error, default to client error if parsing failed
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see any httpgrpc errors being returned by parser

Copy link
Author

@alexgreenbank alexgreenbank Dec 17, 2024

Choose a reason for hiding this comment

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

Oops, should have got rid of that one. Will resolve once I work out best way to wrap existing error in the StatusBadRequest.

Copy link
Author

Choose a reason for hiding this comment

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

Ah, httpgprc is used to smuggle both the http status code and the error message out of the supplier() function. I've removed the misleading comment.

(charInt >= 48 && charInt <= 57) || // 0-9
charInt == 95) { // _

*in = (*in)[:charIndex] + "_" + (*in)[charIndex+1:]
Copy link
Contributor

Choose a reason for hiding this comment

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

This allocates a new string (hopefully just one, compiler should be clever) for each one of the invalid characters. How about you modify the bytes slice before transforming it to a string?

Copy link
Author

Choose a reason for hiding this comment

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

Agreed. Done in latest commit.

// analog of invalidChars = regexp.MustCompile("[^a-zA-Z0-9_]")
func replaceInvalidChars(in *string) {
for charIndex, char := range *in {
charInt := int(char)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you need it to be an int?

Copy link
Author

Choose a reason for hiding this comment

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

It doesn't, removed unnecessary cast.

func replaceInvalidChars(in *string) {
for charIndex, char := range *in {
charInt := int(char)
if !((charInt >= 97 && charInt <= 122) || // a-z
Copy link
Contributor

Choose a reason for hiding this comment

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

If you use 'a' instead of 97 (is it correct?) you won't need the comment and the code will be less prone to have bugs.

Copy link
Author

Choose a reason for hiding this comment

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

Moved to literal chars instead of ASCII codes.

}
}
// prefix with _ if first char is 0-9
if int((*in)[0]) >= 48 && int((*in)[0]) <= 57 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should check first that *in isn't empty, otherwise it would panic.

Copy link
Author

Choose a reason for hiding this comment

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

The values come from the influx library which won't allow an empty string to be created, but I've added an extra check just in case. Also added some extra tests to ensure the assumption about the influx library holds.

Comment on lines 121 to 128
key := string(tag.Key)
if key == "__name__" || key == internalLabel {
continue
}
replaceInvalidChars(&key)
lbls = append(lbls, mimirpb.LabelAdapter{
Name: key,
Value: string(tag.Value),
Copy link
Contributor

Choose a reason for hiding this comment

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

We can do yoloString here instead of string(), as the push code is crafted to avoid keeping references to the strings from LabelAdapter

Copy link
Author

Choose a reason for hiding this comment

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

Interesting! Fixed as per suggestion. I take it no other strings are guaranteed not to be referenced and so it can't be used anywhere else?

@alexgreenbank
Copy link
Author

alexgreenbank commented Dec 19, 2024

OK, comments left to deal with

  • end2end test for happy path
  • TryUnwrap
  • work on byteslice rather than chars
  • yoloString

Signed-off-by: alexgreenbank <[email protected]>
…trings from LabelAdapter

Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
Signed-off-by: alexgreenbank <[email protected]>
@alexgreenbank alexgreenbank self-assigned this Dec 19, 2024
Signed-off-by: alexgreenbank <[email protected]>
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