Skip to content

Commit 2bff18e

Browse files
committed
fix prometheus tests
1 parent c6e6acc commit 2bff18e

File tree

4 files changed

+51
-35
lines changed

4 files changed

+51
-35
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
88

99
## [Unreleased]
1010

11+
### Changed
12+
13+
- Update `github.com/prometheus/common` to v0.62.0., which changes the `NameValidationScheme` to `NoEscaping`. This allows metrics names to keep original delimiters (e.g. `.`), rather than replacing with underscores. This is controlled by the `Content-Type` header, or can be reverted by setting `NameValidationScheme` to `LegacyValidation` in `github.com/prometheus/common/model` (#6198)
14+
1115
### Added
1216

1317
- Add `ValueFromAttribute` and `KeyValueFromAttribute` in `go.opentelemetry.io/otel/log`. (#6180)

exporters/prometheus/config_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func TestNewConfig(t *testing.T) {
133133
},
134134
wantConfig: config{
135135
registerer: prometheus.DefaultRegisterer,
136-
namespace: "test_",
136+
namespace: "test/_",
137137
},
138138
},
139139
}

exporters/prometheus/exporter.go

+41-29
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ type collector struct {
9696

9797
// prometheus counters MUST have a _total suffix by default:
9898
// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/compatibility/prometheus_and_openmetrics.md
99-
const counterSuffix = "_total"
99+
const counterSuffix = "total"
100100

101101
// New returns a Prometheus Exporter.
102102
func New(opts ...Option) (*Exporter, error) {
@@ -368,38 +368,38 @@ func createScopeInfoMetric(scope instrumentation.Scope) (prometheus.Metric, erro
368368

369369
var unitSuffixes = map[string]string{
370370
// Time
371-
"d": "_days",
372-
"h": "_hours",
373-
"min": "_minutes",
374-
"s": "_seconds",
375-
"ms": "_milliseconds",
376-
"us": "_microseconds",
377-
"ns": "_nanoseconds",
371+
"d": "days",
372+
"h": "hours",
373+
"min": "minutes",
374+
"s": "seconds",
375+
"ms": "milliseconds",
376+
"us": "microseconds",
377+
"ns": "nanoseconds",
378378

379379
// Bytes
380-
"By": "_bytes",
381-
"KiBy": "_kibibytes",
382-
"MiBy": "_mebibytes",
383-
"GiBy": "_gibibytes",
384-
"TiBy": "_tibibytes",
385-
"KBy": "_kilobytes",
386-
"MBy": "_megabytes",
387-
"GBy": "_gigabytes",
388-
"TBy": "_terabytes",
380+
"By": "bytes",
381+
"KiBy": "kibibytes",
382+
"MiBy": "mebibytes",
383+
"GiBy": "gibibytes",
384+
"TiBy": "tibibytes",
385+
"KBy": "kilobytes",
386+
"MBy": "megabytes",
387+
"GBy": "gigabytes",
388+
"TBy": "terabytes",
389389

390390
// SI
391-
"m": "_meters",
392-
"V": "_volts",
393-
"A": "_amperes",
394-
"J": "_joules",
395-
"W": "_watts",
396-
"g": "_grams",
391+
"m": "meters",
392+
"V": "volts",
393+
"A": "amperes",
394+
"J": "joules",
395+
"W": "watts",
396+
"g": "grams",
397397

398398
// Misc
399-
"Cel": "_celsius",
400-
"Hz": "_hertz",
401-
"1": "_ratio",
402-
"%": "_percent",
399+
"Cel": "celsius",
400+
"Hz": "hertz",
401+
"1": "ratio",
402+
"%": "percent",
403403
}
404404

405405
// getName returns the sanitized name, prefixed with the namespace and suffixed with unit.
@@ -414,19 +414,31 @@ func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
414414
// Remove the _total suffix here, as we will re-add the total suffix
415415
// later, and it needs to come after the unit suffix.
416416
name = strings.TrimSuffix(name, counterSuffix)
417+
// If the last character is an underscore, or would be converted to an underscore, trim it from the name.
418+
// an underscore will be added back in later.
419+
if convertsToUnderscore(rune(name[len(name)-1])) {
420+
name = name[:len(name)-1]
421+
}
417422
}
418423
if c.namespace != "" {
419424
name = c.namespace + name
420425
}
421426
if suffix, ok := unitSuffixes[m.Unit]; ok && !c.withoutUnits && !strings.HasSuffix(name, suffix) {
422-
name += suffix
427+
name += "_" + suffix
423428
}
424429
if addCounterSuffix {
425-
name += counterSuffix
430+
name += "_" + counterSuffix
426431
}
427432
return name
428433
}
429434

435+
// convertsToUnderscore returns true if the character would be converted to an
436+
// underscore when the escaping scheme is underscore escaping. This is meant to
437+
// capture any character that should be considered a "delimiter".
438+
func convertsToUnderscore(b rune) bool {
439+
return !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == ':' || (b >= '0' && b <= '9'))
440+
}
441+
430442
func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType {
431443
switch v := m.Data.(type) {
432444
case metricdata.Histogram[int64], metricdata.Histogram[float64]:

exporters/prometheus/exporter_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestPrometheusExporter(t *testing.T) {
3535
recordMetrics func(ctx context.Context, meter otelmetric.Meter)
3636
options []Option
3737
expectedFile string
38-
enableUTF8 bool
38+
disableUTF8 bool
3939
}{
4040
{
4141
name: "counter",
@@ -195,6 +195,7 @@ func TestPrometheusExporter(t *testing.T) {
195195
{
196196
name: "sanitized attributes to labels",
197197
expectedFile: "testdata/sanitized_labels.txt",
198+
disableUTF8: true,
198199
options: []Option{WithoutUnits()},
199200
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
200201
opt := otelmetric.WithAttributes(
@@ -404,7 +405,6 @@ func TestPrometheusExporter(t *testing.T) {
404405
{
405406
name: "counter utf-8",
406407
expectedFile: "testdata/counter_utf8.txt",
407-
enableUTF8: true,
408408
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
409409
opt := otelmetric.WithAttributes(
410410
attribute.Key("A.G").String("B"),
@@ -471,11 +471,11 @@ func TestPrometheusExporter(t *testing.T) {
471471

472472
for _, tc := range testCases {
473473
t.Run(tc.name, func(t *testing.T) {
474-
if tc.enableUTF8 {
475-
model.NameValidationScheme = model.UTF8Validation
474+
if tc.disableUTF8 {
475+
model.NameValidationScheme = model.LegacyValidation
476476
defer func() {
477477
// Reset to defaults
478-
model.NameValidationScheme = model.LegacyValidation
478+
model.NameValidationScheme = model.UTF8Validation
479479
}()
480480
}
481481
ctx := context.Background()

0 commit comments

Comments
 (0)