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

Bugfix: quote label name in matchers when needed #14068

Merged

Conversation

colega
Copy link
Contributor

@colega colega commented May 8, 2024

Yet another issue I discovered fuzzying.

{"0"="0"} is now a valid parseable vector selector, but parser.VectorSelector.String() of that is {0="0"}, which is not.

This fixes the Matcher.String() method to quote the name when needed.

Obviously, when needed came at a cost, so I also optimized Match.String() getting rid of the expensive fmt.Sprintf() and making the net cost of the method cheaper in most cases.

(Updated benchmarks)

goos: darwin
goarch: arm64
pkg: github.com/prometheus/prometheus/model/labels
                                                              │   main_mem    │             buffer_mem              │
                                                              │    sec/op     │   sec/op     vs base                │
Matcher_String/short_name_equal-12                              123.30n ± 10%   41.86n ± 0%  -66.05% (p=0.000 n=10)
Matcher_String/short_quoted_name_not_equal-12                   131.10n ± 14%   54.25n ± 0%  -58.62% (p=0.000 n=10)
Matcher_String/short_quoted_name_with_quotes_not_equal-12       125.10n ± 12%   60.01n ± 1%  -52.03% (p=0.000 n=10)
Matcher_String/short_name_value_with_quotes_equal-12            134.30n ± 16%   47.78n ± 1%  -64.42% (p=0.000 n=10)
Matcher_String/short_name_and_long_value_regexp-12               301.6n ± 14%   213.7n ± 1%  -29.16% (p=0.000 n=10)
Matcher_String/short_name_and_long_value_with_quotes_equal-12    323.0n ± 17%   226.9n ± 1%  -29.74% (p=0.000 n=10)
Matcher_String/long_name_regexp-12                              134.65n ± 10%   82.34n ± 1%  -38.85% (p=0.000 n=10)
Matcher_String/long_quoted_name_regexp-12                        132.0n ± 14%   232.4n ± 0%  +76.06% (p=0.000 n=10)
Matcher_String/long_name_and_long_value_regexp-12                316.3n ± 13%   263.4n ± 3%  -16.71% (p=0.000 n=10)
Matcher_String/long_quoted_name_and_long_value_regexp-12         309.5n ± 12%   412.7n ± 3%  +33.35% (p=0.000 n=10)
Matcher_String/mixed-12                                          212.9n ± 11%   172.5n ± 1%  -19.00% (p=0.000 n=10)
geomean                                                          187.0n         124.7n       -33.33%

                                                              │  main_mem  │             buffer_mem             │
                                                              │    B/op    │    B/op     vs base                │
Matcher_String/short_name_equal-12                              48.00 ± 0%   16.00 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_quoted_name_not_equal-12                   48.00 ± 0%   16.00 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_quoted_name_with_quotes_not_equal-12       48.00 ± 0%   16.00 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_name_value_with_quotes_equal-12            48.00 ± 0%   16.00 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_name_and_long_value_regexp-12              96.00 ± 0%   64.00 ± 0%  -33.33% (p=0.000 n=10)
Matcher_String/short_name_and_long_value_with_quotes_equal-12   96.00 ± 0%   64.00 ± 0%  -33.33% (p=0.000 n=10)
Matcher_String/long_name_regexp-12                              96.00 ± 0%   64.00 ± 0%  -33.33% (p=0.000 n=10)
Matcher_String/long_quoted_name_regexp-12                       96.00 ± 0%   64.00 ± 0%  -33.33% (p=0.000 n=10)
Matcher_String/long_name_and_long_value_regexp-12               144.0 ± 0%   112.0 ± 0%  -22.22% (p=0.000 n=10)
Matcher_String/long_quoted_name_and_long_value_regexp-12        144.0 ± 0%   112.0 ± 0%  -22.22% (p=0.000 n=10)
Matcher_String/mixed-12                                         86.00 ± 0%   54.00 ± 0%  -37.21% (p=0.000 n=10)
geomean                                                         79.52        42.14       -47.00%

                                                              │  main_mem  │             buffer_mem             │
                                                              │ allocs/op  │ allocs/op   vs base                │
Matcher_String/short_name_equal-12                              3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_quoted_name_not_equal-12                   3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_quoted_name_with_quotes_not_equal-12       3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_name_value_with_quotes_equal-12            3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_name_and_long_value_regexp-12              3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/short_name_and_long_value_with_quotes_equal-12   3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/long_name_regexp-12                              3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/long_quoted_name_regexp-12                       3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/long_name_and_long_value_regexp-12               3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/long_quoted_name_and_long_value_regexp-12        3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
Matcher_String/mixed-12                                         3.000 ± 0%   1.000 ± 0%  -66.67% (p=0.000 n=10)
geomean                                                         3.000        1.000       -66.67%

colega added 2 commits May 8, 2024 16:58
When the label name of a matcher contains non-standard characters, like
a dot, or starts with a digit, it should be quoted.

If it's not quoted, then `VectorSelector.String()` isn't a valid PromQL.

Signed-off-by: Oleg Zaytsev <mail@olegzaytsev.com>
Signed-off-by: Oleg Zaytsev <mail@olegzaytsev.com>
@colega colega requested a review from roidelapluie as a code owner May 8, 2024 15:12
Copy link
Member

@beorn7 beorn7 left a comment

Choose a reason for hiding this comment

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

Very nice, thank you very much.

As said in the comment, you could totally require Go1.22 for this. Let me know if you want to modify this PR or leave it as is. (That's why I'm not merging it right now.)

Comment on lines 82 to 83
const quote = 1
const matcher = 2
Copy link
Member

Choose a reason for hiding this comment

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

Maybe call these lenQuote and lenMatcher or something? I first thought this might be keys to different types of characters.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a valid point, I'll do it in a follow up PR. Right now I removed pre-growing at all, as I don't have a benchmark for it and there's now a 1KB preallocated stack for building the matcher which covers all the benchmarks.

Let's merge this as is, and I can add a 4KB long matcher to the benchmarks in a follow up PR, and see the impact of growing.

return fmt.Sprintf("%s%s%q", m.Name, m.Type, m.Value)
const quote = 1
const matcher = 2
// As we're not on go1.22 yet and we don't have the new fancy AvailableBuffer method on strings.Builder,
Copy link
Member

Choose a reason for hiding this comment

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

Given that v2.52 is already separated from the main branch, and Go is already at 1.22.3, I don't see a problem with requiring Go1.22 from now on. So If it helps with this PR, feel free to bump the requirement.

Copy link
Member

Choose a reason for hiding this comment

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

In fact, the RC for v2.52 is already built with Go1.22.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out, it's the bytes.Buffer, not strings.Builder that has the AvailBuffer method. I copied the implementation from Labels.String() that uses it, with the preallocated array on stack. No need to bump the go version after all.

Also removed the growing until there's a benchmark for that.

Signed-off-by: Oleg Zaytsev <mail@olegzaytsev.com>
@colega colega force-pushed the quote-label-name-in-matchers-when-needed branch from b0318da to b7b4355 Compare May 9, 2024 08:01
@colega
Copy link
Contributor Author

colega commented May 9, 2024

@beorn7 this is ready to take another look. Thank you.

Edit: I also updated the benchmarks in the description of the PR.

@beorn7 beorn7 merged commit e6be424 into prometheus:main May 14, 2024
25 checks passed
krajorama added a commit to grafana/mimir that referenced this pull request May 15, 2024
krajorama added a commit to grafana/mimir that referenced this pull request May 15, 2024
grafanabot pushed a commit to grafana/mimir that referenced this pull request May 15, 2024
* Update mimir-prometheus to e5b85c151ba8

grafana/mimir-prometheus@e5b85c1

prometheus/prometheus#14103
prometheus/prometheus#14096
prometheus/prometheus#14068
prometheus/prometheus#13669

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
(cherry picked from commit 307567a)
krajorama added a commit to grafana/mimir that referenced this pull request May 15, 2024
* Update mimir-prometheus to e5b85c151ba8

grafana/mimir-prometheus@e5b85c1

prometheus/prometheus#14103
prometheus/prometheus#14096
prometheus/prometheus#14068
prometheus/prometheus#13669

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
(cherry picked from commit 307567a)

Co-authored-by: George Krajcsovits <krajorama@users.noreply.github.com>
krajorama added a commit to grafana/mimir that referenced this pull request May 15, 2024
Reverting prometheus/prometheus#14068
because it is causing unforseen complications with LBAC in GEM.

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
krajorama added a commit to grafana/mimir that referenced this pull request May 15, 2024
Reverting prometheus/prometheus#14068
because it is causing unforseen complications with LBAC in GEM.

Signed-off-by: György Krajcsovits <gyorgy.krajcsovits@grafana.com>
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.

None yet

2 participants