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

Expand the set of units supported by the prometheus exporter #4374

Merged
merged 4 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- The `go.opentelemetry.io/otel/semconv/v1.21.0` package.
The package contains semantic conventions from the `v1.21.0` version of the OpenTelemetry Semantic Conventions. (#4362)
- Document the `Temporality` and `Aggregation` methods of the `"go.opentelemetry.io/otel/sdk/metric".Exporter"` need to be concurrent safe. (#4381)
- Expand the set of units supported by the prometheus exporter, and don't add unit suffixes if they are already present in `go.opentelemetry.op/otel/exporters/prometheus` (#4374)

### Changed

Expand Down
38 changes: 34 additions & 4 deletions exporters/prometheus/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,39 @@ func sanitizeRune(r rune) rune {
}

var unitSuffixes = map[string]string{
"1": "_ratio",
"By": "_bytes",
"ms": "_milliseconds",
// Time
"d": "_days",
"h": "_hours",
"min": "_minutes",
"s": "_seconds",
"ms": "_milliseconds",
"us": "_microseconds",
"ns": "_nanoseconds",

// Bytes
"By": "_bytes",
"KiBy": "_kibibytes",
"MiBy": "_mebibytes",
"GiBy": "_gibibytes",
"TiBy": "_tibibytes",
"KBy": "_kilobytes",
"MBy": "_megabytes",
"GBy": "_gigabytes",
"TBy": "_terabytes",

// SI
"m": "_meters",
"V": "_volts",
"A": "_amperes",
"J": "_joules",
"W": "_watts",
"g": "_grams",

// Misc
"Cel": "_celsius",
"Hz": "_hertz",
"1": "_ratio",
"%": "_percent",
}

// getName returns the sanitized name, prefixed with the namespace and suffixed with unit.
Expand All @@ -344,7 +374,7 @@ func (c *collector) getName(m metricdata.Metrics) string {
if c.withoutUnits {
return name
}
if suffix, ok := unitSuffixes[m.Unit]; ok {
if suffix, ok := unitSuffixes[m.Unit]; ok && !strings.HasSuffix(name, suffix) {
name += suffix
}
return name
Expand Down
43 changes: 36 additions & 7 deletions exporters/prometheus/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,36 @@ func TestPrometheusExporter(t *testing.T) {
counter, err := meter.Float64Counter(
"foo",
otelmetric.WithDescription("a simple counter"),
otelmetric.WithUnit("ms"),
otelmetric.WithUnit("s"),
)
require.NoError(t, err)
counter.Add(ctx, 5, opt)
counter.Add(ctx, 10.3, opt)
counter.Add(ctx, 9, opt)

attrs2 := attribute.NewSet(
attribute.Key("A").String("D"),
attribute.Key("C").String("B"),
attribute.Key("E").Bool(true),
attribute.Key("F").Int(42),
)
counter.Add(ctx, 5, otelmetric.WithAttributeSet(attrs2))
},
},
{
name: "counter that already has the unit suffix",
expectedFile: "testdata/counter.txt",
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
opt := otelmetric.WithAttributes(
attribute.Key("A").String("B"),
attribute.Key("C").String("D"),
attribute.Key("E").Bool(true),
attribute.Key("F").Int(42),
)
counter, err := meter.Float64Counter(
"foo.seconds",
otelmetric.WithDescription("a simple counter"),
otelmetric.WithUnit("s"),
)
require.NoError(t, err)
counter.Add(ctx, 5, opt)
Expand Down Expand Up @@ -85,7 +114,7 @@ func TestPrometheusExporter(t *testing.T) {
counter, err := meter.Float64Counter(
"foo",
otelmetric.WithDescription("a simple counter without a total suffix"),
otelmetric.WithUnit("ms"),
otelmetric.WithUnit("s"),
)
require.NoError(t, err)
counter.Add(ctx, 5, opt)
Expand Down Expand Up @@ -415,15 +444,15 @@ func TestMultiScopes(t *testing.T) {
fooCounter, err := provider.Meter("meterfoo", otelmetric.WithInstrumentationVersion("v0.1.0")).
Int64Counter(
"foo",
otelmetric.WithUnit("ms"),
otelmetric.WithUnit("s"),
otelmetric.WithDescription("meter foo counter"))
assert.NoError(t, err)
fooCounter.Add(ctx, 100, otelmetric.WithAttributes(attribute.String("type", "foo")))

barCounter, err := provider.Meter("meterbar", otelmetric.WithInstrumentationVersion("v0.1.0")).
Int64Counter(
"bar",
otelmetric.WithUnit("ms"),
otelmetric.WithUnit("s"),
otelmetric.WithDescription("meter bar counter"))
assert.NoError(t, err)
barCounter.Add(ctx, 200, otelmetric.WithAttributes(attribute.String("type", "bar")))
Expand Down Expand Up @@ -571,7 +600,7 @@ func TestDuplicateMetrics(t *testing.T) {
bazA.Add(ctx, 100, withTypeBar)

bazB, err := meterB.Int64Counter("bar",
otelmetric.WithUnit("ms"),
otelmetric.WithUnit("s"),
otelmetric.WithDescription("meter bar"))
assert.NoError(t, err)
bazB.Add(ctx, 100, withTypeBar)
Expand All @@ -589,7 +618,7 @@ func TestDuplicateMetrics(t *testing.T) {
barA.Add(ctx, 100, withTypeBar)

barB, err := meterB.Int64UpDownCounter("bar",
otelmetric.WithUnit("ms"),
otelmetric.WithUnit("s"),
otelmetric.WithDescription("meter gauge bar"))
assert.NoError(t, err)
barB.Add(ctx, 100, withTypeBar)
Expand All @@ -607,7 +636,7 @@ func TestDuplicateMetrics(t *testing.T) {
barA.Record(ctx, 100, withAB)

barB, err := meterB.Int64Histogram("bar",
otelmetric.WithUnit("ms"),
otelmetric.WithUnit("s"),
otelmetric.WithDescription("meter histogram bar"))
assert.NoError(t, err)
barB.Record(ctx, 100, withAB)
Expand Down
8 changes: 4 additions & 4 deletions exporters/prometheus/testdata/counter.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# HELP foo_milliseconds_total a simple counter
# TYPE foo_milliseconds_total counter
foo_milliseconds_total{A="B",C="D",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 24.3
foo_milliseconds_total{A="D",C="B",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 5
# HELP foo_seconds_total a simple counter
# TYPE foo_seconds_total counter
foo_seconds_total{A="B",C="D",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 24.3
foo_seconds_total{A="D",C="B",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 5
# HELP otel_scope_info Instrumentation Scope metadata
# TYPE otel_scope_info gauge
otel_scope_info{otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 1
Expand Down
8 changes: 4 additions & 4 deletions exporters/prometheus/testdata/counter_disabled_suffix.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# HELP foo_milliseconds a simple counter without a total suffix
# TYPE foo_milliseconds counter
foo_milliseconds{A="B",C="D",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 24.3
foo_milliseconds{A="D",C="B",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 5
# HELP foo_seconds a simple counter without a total suffix
# TYPE foo_seconds counter
foo_seconds{A="B",C="D",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 24.3
foo_seconds{A="D",C="B",E="true",F="42",otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 5
# HELP otel_scope_info Instrumentation Scope metadata
# TYPE otel_scope_info gauge
otel_scope_info{otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 1
Expand Down
12 changes: 6 additions & 6 deletions exporters/prometheus/testdata/multi_scopes.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# HELP bar_milliseconds_total meter bar counter
# TYPE bar_milliseconds_total counter
bar_milliseconds_total{otel_scope_name="meterbar",otel_scope_version="v0.1.0",type="bar"} 200
# HELP foo_milliseconds_total meter foo counter
# TYPE foo_milliseconds_total counter
foo_milliseconds_total{otel_scope_name="meterfoo",otel_scope_version="v0.1.0",type="foo"} 100
# HELP bar_seconds_total meter bar counter
# TYPE bar_seconds_total counter
bar_seconds_total{otel_scope_name="meterbar",otel_scope_version="v0.1.0",type="bar"} 200
# HELP foo_seconds_total meter foo counter
# TYPE foo_seconds_total counter
foo_seconds_total{otel_scope_name="meterfoo",otel_scope_version="v0.1.0",type="foo"} 100
# HELP otel_scope_info Instrumentation Scope metadata
# TYPE otel_scope_info gauge
otel_scope_info{otel_scope_name="meterfoo",otel_scope_version="v0.1.0"} 1
Expand Down