Skip to content

MetricNamer: avoid adding duplicate suffixes when UTF8 is allowed#48

Merged
ArthurSens merged 3 commits intoprometheus:mainfrom
dashpole:dedup_suffixes
Jul 25, 2025
Merged

MetricNamer: avoid adding duplicate suffixes when UTF8 is allowed#48
ArthurSens merged 3 commits intoprometheus:mainfrom
dashpole:dedup_suffixes

Conversation

@dashpole
Copy link
Contributor

@dashpole dashpole commented Jul 23, 2025

Fixes #44

Benchstat:

goos: linux
goarch: amd64
pkg: github.com/prometheus/otlptranslator
cpu: Intel(R) Xeon(R) CPU @ 2.20GHz
                                                                                     │   old.txt   │              new.txt               │
                                                                                     │   sec/op    │   sec/op     vs base               │
NormalizeLabel/empty_label-2                                                           2.656n ± 1%   2.563n ± 0%   -3.48% (p=0.002 n=6)
NormalizeLabel/label_with_colons-2                                                     138.7n ± 1%   144.2n ± 4%   +4.00% (p=0.002 n=6)
NormalizeLabel/label_with_capital_letters-2                                            197.6n ± 1%   175.5n ± 1%  -11.14% (p=0.002 n=6)
NormalizeLabel/label_with_special_characters-2                                         181.7n ± 0%   188.6n ± 1%   +3.80% (p=0.002 n=6)
NormalizeLabel/label_with_foreign_characters-2                                         253.4n ± 6%   263.6n ± 2%        ~ (p=0.065 n=6)
NormalizeLabel/label_with_dots-2                                                       126.8n ± 5%   131.8n ± 0%        ~ (p=0.058 n=6)
NormalizeLabel/label_starting_with_digits-2                                            129.3n ± 2%   132.0n ± 1%   +2.05% (p=0.013 n=6)
NormalizeLabel/label_starting_with_underscores-2                                       307.9n ± 1%   307.6n ± 0%        ~ (p=0.970 n=6)
NormalizeLabel/label_starting_with_2_underscores-2                                     260.8n ± 1%   269.8n ± 1%   +3.47% (p=0.002 n=6)
Build/withSuffixes=true/utf8Allowed=true/Basic_metric_with_no_special_characters-2     124.0n ± 4%   125.5n ± 2%        ~ (p=0.084 n=6)
Build/withSuffixes=true/utf8Allowed=true/Counter_metric-2                              181.7n ± 3%   199.1n ± 1%   +9.58% (p=0.002 n=6)
Build/withSuffixes=true/utf8Allowed=true/Gauge_ratio_metric-2                          238.4n ± 1%   262.5n ± 1%  +10.11% (p=0.002 n=6)
Build/withSuffixes=true/utf8Allowed=true/Metric_with_per-unit_suffix_notation-2        358.1n ± 0%   377.5n ± 1%   +5.42% (p=0.002 n=6)
Build/withSuffixes=true/utf8Allowed=true/Metric_with_special_characters-2              129.2n ± 2%   129.9n ± 2%        ~ (p=0.119 n=6)
Build/withSuffixes=true/utf8Allowed=true/Metric_starting_with_digit-2                  120.9n ± 3%   122.2n ± 1%        ~ (p=0.331 n=6)
Build/withSuffixes=true/utf8Allowed=true/Metric_with_multiple_underscores-2            136.5n ± 2%   138.8n ± 3%        ~ (p=0.102 n=6)
Build/withSuffixes=true/utf8Allowed=true/Metric_with_complex_unit-2                    456.5n ± 2%   477.3n ± 1%   +4.57% (p=0.002 n=6)
Build/withSuffixes=true/utf8Allowed=false/Basic_metric_with_no_special_characters-2    556.7n ± 1%   552.0n ± 1%   -0.84% (p=0.026 n=6)
Build/withSuffixes=true/utf8Allowed=false/Counter_metric-2                             726.4n ± 1%   721.9n ± 2%        ~ (p=0.818 n=6)
Build/withSuffixes=true/utf8Allowed=false/Gauge_ratio_metric-2                         666.1n ± 1%   673.5n ± 3%        ~ (p=0.132 n=6)
Build/withSuffixes=true/utf8Allowed=false/Metric_with_per-unit_suffix_notation-2       964.0n ± 1%   972.1n ± 1%        ~ (p=0.394 n=6)
Build/withSuffixes=true/utf8Allowed=false/Metric_with_special_characters-2             692.5n ± 2%   696.0n ± 1%        ~ (p=0.240 n=6)
Build/withSuffixes=true/utf8Allowed=false/Metric_starting_with_digit-2                 492.4n ± 1%   495.4n ± 1%        ~ (p=0.485 n=6)
Build/withSuffixes=true/utf8Allowed=false/Metric_with_multiple_underscores-2           752.8n ± 1%   755.1n ± 2%        ~ (p=0.240 n=6)
Build/withSuffixes=true/utf8Allowed=false/Metric_with_complex_unit-2                   1.303µ ± 1%   1.318µ ± 1%   +1.07% (p=0.013 n=6)
Build/withSuffixes=false/utf8Allowed=true/Basic_metric_with_no_special_characters-2    64.39n ± 1%   66.38n ± 1%   +3.10% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=true/Counter_metric-2                             64.73n ± 1%   66.87n ± 2%   +3.32% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=true/Gauge_ratio_metric-2                         64.93n ± 1%   66.57n ± 2%   +2.53% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=true/Metric_with_per-unit_suffix_notation-2       61.87n ± 1%   64.05n ± 3%   +3.53% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=true/Metric_with_special_characters-2             69.91n ± 1%   71.78n ± 1%   +2.68% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=true/Metric_starting_with_digit-2                 62.32n ± 1%   63.79n ± 1%   +2.36% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=true/Metric_with_multiple_underscores-2           73.74n ± 1%   77.53n ± 3%   +5.14% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=true/Metric_with_complex_unit-2                   64.44n ± 1%   66.50n ± 1%   +3.19% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=false/Basic_metric_with_no_special_characters-2   3.868µ ± 1%   3.913µ ± 1%   +1.16% (p=0.015 n=6)
Build/withSuffixes=false/utf8Allowed=false/Counter_metric-2                            3.975µ ± 1%   4.013µ ± 1%   +0.97% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=false/Gauge_ratio_metric-2                        3.738µ ± 0%   3.808µ ± 0%   +1.87% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=false/Metric_with_per-unit_suffix_notation-2      3.187µ ± 1%   3.246µ ± 1%   +1.85% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=false/Metric_with_special_characters-2            5.612µ ± 1%   5.677µ ± 1%   +1.15% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=false/Metric_starting_with_digit-2                3.357µ ± 1%   3.410µ ± 1%   +1.59% (p=0.002 n=6)
Build/withSuffixes=false/utf8Allowed=false/Metric_with_multiple_underscores-2          6.829µ ± 3%   6.976µ ± 1%        ~ (p=0.065 n=6)
Build/withSuffixes=false/utf8Allowed=false/Metric_with_complex_unit-2                  3.712µ ± 0%   3.801µ ± 0%   +2.41% (p=0.002 n=6)
geomean                                                                                331.5n        338.0n        +1.97%

                                                                                     │   old.txt    │              new.txt               │
                                                                                     │     B/op     │    B/op     vs base                │
NormalizeLabel/empty_label-2                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_colons-2                                                     24.00 ± 0%     24.00 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_capital_letters-2                                            24.00 ± 0%     24.00 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_special_characters-2                                         32.00 ± 0%     32.00 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_foreign_characters-2                                         48.00 ± 0%     48.00 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_dots-2                                                       16.00 ± 0%     16.00 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_starting_with_digits-2                                            24.00 ± 0%     24.00 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_starting_with_underscores-2                                       80.00 ± 0%     80.00 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_starting_with_2_underscores-2                                     48.00 ± 0%     48.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Basic_metric_with_no_special_characters-2     48.00 ± 0%     48.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Counter_metric-2                              96.00 ± 0%     96.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Gauge_ratio_metric-2                          112.0 ± 0%     112.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_per-unit_suffix_notation-2        120.0 ± 0%     120.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_special_characters-2              64.00 ± 0%     64.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_starting_with_digit-2                  40.00 ± 0%     40.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_multiple_underscores-2            80.00 ± 0%     80.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_complex_unit-2                    176.0 ± 0%     176.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Basic_metric_with_no_special_characters-2    160.0 ± 0%     160.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Counter_metric-2                             288.0 ± 0%     288.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Gauge_ratio_metric-2                         208.0 ± 0%     208.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_per-unit_suffix_notation-2       256.0 ± 0%     256.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_special_characters-2             240.0 ± 0%     240.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_starting_with_digit-2                 120.0 ± 0%     120.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_multiple_underscores-2           240.0 ± 0%     240.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_complex_unit-2                   368.0 ± 0%     368.5 ± 0%       ~ (p=1.000 n=6)
Build/withSuffixes=false/utf8Allowed=true/Basic_metric_with_no_special_characters-2    32.00 ± 0%     32.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Counter_metric-2                             32.00 ± 0%     32.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Gauge_ratio_metric-2                         32.00 ± 0%     32.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_per-unit_suffix_notation-2       24.00 ± 0%     24.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_special_characters-2             48.00 ± 0%     48.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_starting_with_digit-2                 24.00 ± 0%     24.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_multiple_underscores-2           64.00 ± 0%     64.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_complex_unit-2                   32.00 ± 0%     32.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Basic_metric_with_no_special_characters-2   172.0 ± 0%     172.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Counter_metric-2                            176.0 ± 0%     176.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Gauge_ratio_metric-2                        168.0 ± 0%     168.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_with_per-unit_suffix_notation-2      144.0 ± 0%     144.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_with_special_characters-2            316.0 ± 0%     316.0 ± 0%       ~ (p=1.000 n=6)
Build/withSuffixes=false/utf8Allowed=false/Metric_starting_with_digit-2                148.0 ± 0%     148.0 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_with_multiple_underscores-2          292.0 ± 0%     292.0 ± 0%       ~ (p=1.000 n=6)
Build/withSuffixes=false/utf8Allowed=false/Metric_with_complex_unit-2                  168.0 ± 0%     168.0 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                                                           ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                                                     │   old.txt    │              new.txt               │
                                                                                     │  allocs/op   │ allocs/op   vs base                │
NormalizeLabel/empty_label-2                                                           0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_colons-2                                                     1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_capital_letters-2                                            1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_special_characters-2                                         1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_foreign_characters-2                                         1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_with_dots-2                                                       1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_starting_with_digits-2                                            2.000 ± 0%     2.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_starting_with_underscores-2                                       2.000 ± 0%     2.000 ± 0%       ~ (p=1.000 n=6) ¹
NormalizeLabel/label_starting_with_2_underscores-2                                     1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Basic_metric_with_no_special_characters-2     2.000 ± 0%     2.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Counter_metric-2                              3.000 ± 0%     3.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Gauge_ratio_metric-2                          3.000 ± 0%     3.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_per-unit_suffix_notation-2        4.000 ± 0%     4.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_special_characters-2              2.000 ± 0%     2.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_starting_with_digit-2                  2.000 ± 0%     2.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_multiple_underscores-2            2.000 ± 0%     2.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=true/Metric_with_complex_unit-2                    5.000 ± 0%     5.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Basic_metric_with_no_special_characters-2    6.000 ± 0%     6.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Counter_metric-2                             8.000 ± 0%     8.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Gauge_ratio_metric-2                         7.000 ± 0%     7.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_per-unit_suffix_notation-2       10.00 ± 0%     10.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_special_characters-2             6.000 ± 0%     6.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_starting_with_digit-2                 6.000 ± 0%     6.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_multiple_underscores-2           6.000 ± 0%     6.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=true/utf8Allowed=false/Metric_with_complex_unit-2                   12.00 ± 0%     12.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Basic_metric_with_no_special_characters-2    1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Counter_metric-2                             1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Gauge_ratio_metric-2                         1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_per-unit_suffix_notation-2       1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_special_characters-2             1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_starting_with_digit-2                 1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_multiple_underscores-2           1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=true/Metric_with_complex_unit-2                   1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Basic_metric_with_no_special_characters-2   30.00 ± 0%     30.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Counter_metric-2                            31.00 ± 0%     31.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Gauge_ratio_metric-2                        29.00 ± 0%     29.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_with_per-unit_suffix_notation-2      25.00 ± 0%     25.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_with_special_characters-2            43.00 ± 0%     43.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_starting_with_digit-2                26.00 ± 0%     26.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_with_multiple_underscores-2          52.00 ± 0%     52.00 ± 0%       ~ (p=1.000 n=6) ¹
Build/withSuffixes=false/utf8Allowed=false/Metric_with_complex_unit-2                  29.00 ± 0%     29.00 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                                                           ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

Adds no allocations or bytes, but adds 10% CPU usage for metrics with a _total or _ratio suffix when UTF8 is allowed and suffixes are added.

Signed-off-by: David Ashpole <dashpole@google.com>
Copy link
Member

@ArthurSens ArthurSens left a comment

Choose a reason for hiding this comment

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

Alright, let's pay the 12% CPU penalty 😬

But I was wondering if we could brainstorm a way to not do this. As @ywwg pointed out in #44 (comment), units should not be added to OTel metric names anyway

@dashpole
Copy link
Contributor Author

Btw, this performance penalty wold only occur if someone is using UTF8Allowed=true and withSuffixes=true, which should be rare (outside of the current Go SDK).

Signed-off-by: David Ashpole <dashpole@google.com>
@dashpole
Copy link
Contributor Author

Results are now ~2% better than before thanks to #48 (comment)

Signed-off-by: David Ashpole <dashpole@google.com>
@ArthurSens
Copy link
Member

Any other concerns @ywwg? We have another release of the collector next Monday, I know it's kinda rushed but it would be nice to have a fix by then

@ArthurSens
Copy link
Member

Spoke a bit offline, I'm taking the liberty to merge since we've got a release to do that requires this fix

@ArthurSens ArthurSens merged commit ab8d56d into prometheus:main Jul 25, 2025
3 checks passed
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.

Duplicate type or unit suffixes when utf8 is allowed

3 participants