A Go library for converting OpenTelemetry Protocol (OTLP) metric and attribute names to Prometheus-compliant formats. This is an internal library for both Prometheus and Open Telemetry, without any stability guarantees for external usage.
Part of the Prometheus ecosystem, following the OpenTelemetry to Prometheus compatibility specification.
- Metric Name and Label Translation: Convert OTLP metric names and attributes to Prometheus-compliant format
- Unit Handling: Translate OTLP units to Prometheus unit conventions
- Type-Aware Suffixes: Optionally append
_total
,_ratio
based on metric type - Namespace Support: Add configurable namespace prefixes
- UTF-8 Support: Choose between Prometheus legacy scheme compliant metric/label names (
[a-zA-Z0-9:_]
) or untranslated metric/label names - Translation Strategy Configuration: Select a translation strategy with a standard set of strings.
go get github.com/prometheus/otlptranslator
package main
import (
"fmt"
"github.com/prometheus/otlptranslator"
)
func main() {
// Create a metric namer using traditional Prometheus name translation, with suffixes added and UTF-8 disallowed.
strategy := otlptranslator.UnderscoreEscapingWithSuffixes
namer := otlptranslator.NewMetricNamer("myapp", strategy)
// Translate OTLP metric to Prometheus format
metric := otlptranslator.Metric{
Name: "http.server.request.duration",
Unit: "s",
Type: otlptranslator.MetricTypeHistogram,
}
fmt.Println(namer.Build(metric)) // Output: myapp_http_server_request_duration_seconds
// Translate label names
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: false}
fmt.Println(labelNamer.Build("http.method")) // Output: http_method
}
namer := otlptranslator.MetricNamer{WithMetricSuffixes: true, UTF8Allowed: false}
// Counter gets _total suffix
counter := otlptranslator.Metric{
Name: "requests.count", Unit: "1", Type: otlptranslator.MetricTypeMonotonicCounter,
}
fmt.Println(namer.Build(counter)) // requests_count_total
// Gauge with unit conversion
gauge := otlptranslator.Metric{
Name: "memory.usage", Unit: "By", Type: otlptranslator.MetricTypeGauge,
}
fmt.Println(namer.Build(gauge)) // memory_usage_bytes
// Dimensionless gauge gets _ratio suffix
ratio := otlptranslator.Metric{
Name: "cpu.utilization", Unit: "1", Type: otlptranslator.MetricTypeGauge,
}
fmt.Println(namer.Build(ratio)) // cpu_utilization_ratio
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: false}
labelNamer.Build("http.method") // http_method
labelNamer.Build("123invalid") // key_123invalid
labelNamer.Build("_private") // key_private
labelNamer.Build("__reserved__") // __reserved__ (preserved)
labelNamer.Build("label@with$symbols") // label_with_symbols
unitNamer := otlptranslator.UnitNamer{UTF8Allowed: false}
unitNamer.Build("s") // seconds
unitNamer.Build("By") // bytes
unitNamer.Build("requests/s") // requests_per_second
unitNamer.Build("1") // "" (dimensionless)
// Prometheus-compliant mode - supports [a-zA-Z0-9:_]
compliantNamer := otlptranslator.MetricNamer{UTF8Allowed: false, WithMetricSuffixes: true}
// Transparent pass-through mode, aka "NoTranslation"
utf8Namer := otlptranslator.MetricNamer{UTF8Allowed: true, WithMetricSuffixes: false}
utf8Namer = otlptranslator.NewMetricNamer("", otlpTranslator.NoTranslation)
// With namespace and suffixes
productionNamer := otlptranslator.MetricNamer{
Namespace: "myservice",
WithMetricSuffixes: true,
UTF8Allowed: false,
}
Licensed under the Apache License 2.0 - see the LICENSE file for details.