otlptranslator

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2025 License: Apache-2.0 Imports: 5 Imported by: 17

README

OTLP Prometheus Translator

A Go library for converting OpenTelemetry Protocol (OTLP) metric and attribute names to Prometheus-compliant formats.

Part of the Prometheus ecosystem, following the OpenTelemetry to Prometheus compatibility specification.

Features

  • 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.

Installation

go get github.com/prometheus/otlptranslator

Quick Start

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
}

Usage Examples

Metric Name Translation
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
Label Translation
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
Unit Translation
unitNamer := otlptranslator.UnitNamer{UTF8Allowed: false}

unitNamer.Build("s")           // seconds
unitNamer.Build("By")          // bytes
unitNamer.Build("requests/s")  // requests_per_second
unitNamer.Build("1")           // "" (dimensionless)
Configuration Options
// 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,
}

License

Licensed under the Apache License 2.0 - see the LICENSE file for details.

Documentation

Overview

Copyright 2025 The Prometheus Authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Package otlptranslator provides utilities for converting OpenTelemetry Protocol (OTLP) metric and attribute names to Prometheus-compliant formats.

This package is designed to help users translate OpenTelemetry metrics to Prometheus metrics while following the official OpenTelemetry to Prometheus compatibility specification.

Main components:

  • MetricNamer: Translates OTLP metric names to Prometheus metric names
  • LabelNamer: Translates OTLP attribute names to Prometheus label names
  • UnitNamer: Translates OTLP units to Prometheus unit conventions

Index

Constants

View Source
const (
	// ExemplarTraceIDKey is the key used to store the trace ID in Prometheus
	// exemplars:
	// https://github.com/open-telemetry/opentelemetry-specification/blob/e6eccba97ebaffbbfad6d4358408a2cead0ec2df/specification/compatibility/prometheus_and_openmetrics.md#exemplars
	ExemplarTraceIDKey = "trace_id"
	// ExemplarSpanIDKey is the key used to store the Span ID in Prometheus
	// exemplars:
	// https://github.com/open-telemetry/opentelemetry-specification/blob/e6eccba97ebaffbbfad6d4358408a2cead0ec2df/specification/compatibility/prometheus_and_openmetrics.md#exemplars
	ExemplarSpanIDKey = "span_id"
	// ScopeNameLabelKey is the name of the label key used to identify the name
	// of the OpenTelemetry scope which produced the metric:
	// https://github.com/open-telemetry/opentelemetry-specification/blob/e6eccba97ebaffbbfad6d4358408a2cead0ec2df/specification/compatibility/prometheus_and_openmetrics.md#instrumentation-scope
	ScopeNameLabelKey = "otel_scope_name"
	// ScopeVersionLabelKey is the name of the label key used to identify the
	// version of the OpenTelemetry scope which produced the metric:
	// https://github.com/open-telemetry/opentelemetry-specification/blob/e6eccba97ebaffbbfad6d4358408a2cead0ec2df/specification/compatibility/prometheus_and_openmetrics.md#instrumentation-scope
	ScopeVersionLabelKey = "otel_scope_version"
	// TargetInfoMetricName is the name of the metric used to preserve resource
	// attributes in Prometheus format:
	// https://github.com/open-telemetry/opentelemetry-specification/blob/e6eccba97ebaffbbfad6d4358408a2cead0ec2df/specification/compatibility/prometheus_and_openmetrics.md#resource-attributes-1
	// It originates from OpenMetrics:
	// https://github.com/OpenObservability/OpenMetrics/blob/1386544931307dff279688f332890c31b6c5de36/specification/OpenMetrics.md#supporting-target-metadata-in-both-push-based-and-pull-based-systems
	TargetInfoMetricName = "target_info"
)
View Source
const (
	// MetricTypeUnknown represents an unknown metric type.
	MetricTypeUnknown = iota
	// MetricTypeNonMonotonicCounter represents a counter that is not monotonically increasing, also known as delta counter.
	MetricTypeNonMonotonicCounter
	// MetricTypeMonotonicCounter represents a counter that is monotonically increasing, also known as cumulative counter.
	MetricTypeMonotonicCounter
	// MetricTypeGauge represents a gauge metric.
	MetricTypeGauge
	// MetricTypeHistogram represents a histogram metric.
	MetricTypeHistogram
	// MetricTypeExponentialHistogram represents an exponential histogram metric.
	MetricTypeExponentialHistogram
	// MetricTypeSummary represents a summary metric.
	MetricTypeSummary
)

Variables

This section is empty.

Functions

This section is empty.

Types

type LabelNamer

type LabelNamer struct {
	UTF8Allowed bool
}

LabelNamer is a helper struct to build label names. It translates OpenTelemetry Protocol (OTLP) attribute names to Prometheus-compliant label names.

Example usage:

namer := LabelNamer{UTF8Allowed: false}
result := namer.Build("http.method") // "http_method"

func (*LabelNamer) Build

func (ln *LabelNamer) Build(label string) (normalizedName string, err error)

Build normalizes the specified label to follow Prometheus label names standard.

Translation rules:

  • Replaces invalid characters with underscores
  • Prefixes labels with invalid start characters (numbers or `_`) with "key"
  • Preserves double underscore labels (reserved names)
  • If UTF8Allowed is true, returns label as-is

Examples:

namer := LabelNamer{UTF8Allowed: false}
namer.Build("http.method")     // "http_method"
namer.Build("123invalid")      // "key_123invalid"
namer.Build("__reserved__")    // "__reserved__" (preserved)

type Metric

type Metric struct {
	Name string
	Unit string
	Type MetricType
}

Metric is a helper struct that holds information about a metric. It represents an OpenTelemetry metric with its name, unit, and type.

Example:

metric := Metric{
	Name: "http.server.request.duration",
	Unit: "s",
	Type: MetricTypeHistogram,
}

type MetricNamer

type MetricNamer struct {
	Namespace          string
	WithMetricSuffixes bool
	UTF8Allowed        bool
}

MetricNamer is a helper struct to build metric names. It converts OpenTelemetry Protocol (OTLP) metric names to Prometheus-compliant metric names.

Example usage:

namer := MetricNamer{
	WithMetricSuffixes: true,
	UTF8Allowed:        false,
}

metric := Metric{
	Name: "http.server.duration",
	Unit: "s",
	Type: MetricTypeHistogram,
}

result := namer.Build(metric) // "http_server_duration_seconds"

func NewMetricNamer added in v0.0.2

func NewMetricNamer(namespace string, strategy TranslationStrategyOption) MetricNamer

NewMetricNamer creates a MetricNamer with the specified namespace (can be blank) and the requested Translation Strategy.

func (*MetricNamer) Build

func (mn *MetricNamer) Build(metric Metric) (string, error)

Build builds a metric name for the specified metric.

The method applies different transformations based on the MetricNamer configuration:

  • If UTF8Allowed is true, doesn't translate names - all characters must be valid UTF-8, however.
  • If UTF8Allowed is false, translates metric names to comply with legacy Prometheus name scheme by escaping invalid characters to `_`.
  • If WithMetricSuffixes is true, adds appropriate suffixes based on type and unit.

See rules at https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels

Examples:

namer := MetricNamer{WithMetricSuffixes: true, UTF8Allowed: false}

// Counter gets _total suffix
counter := Metric{Name: "requests.count", Unit: "1", Type: MetricTypeMonotonicCounter}
result := namer.Build(counter) // "requests_count_total"

// Gauge with unit suffix
gauge := Metric{Name: "memory.usage", Unit: "By", Type: MetricTypeGauge}
result = namer.Build(gauge) // "memory_usage_bytes"

type MetricType

type MetricType int

MetricType is a representation of metric types from OpenTelemetry. Different types of Sums were introduced based on their metric temporalities. For more details, see: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#sums

type TranslationStrategyOption added in v0.0.2

type TranslationStrategyOption string

TranslationStrategyOption is a constant that defines how metric and label names should be handled during translation. The recommended approach is to use either UnderscoreEscapingWithSuffixes for full Prometheus-style compatibility, or NoTranslation for Otel-style names.

var (
	// NoUTF8EscapingWithSuffixes will accept metric/label names as they are. Unit
	// and type suffixes may be added to metric names, according to certain rules.
	NoUTF8EscapingWithSuffixes TranslationStrategyOption = "NoUTF8EscapingWithSuffixes"
	// UnderscoreEscapingWithSuffixes is the default option for translating OTLP
	// to Prometheus. This option will translate metric name characters that are
	// not alphanumerics/underscores/colons to underscores, and label name
	// characters that are not alphanumerics/underscores to underscores. Unit and
	// type suffixes may be appended to metric names, according to certain rules.
	UnderscoreEscapingWithSuffixes TranslationStrategyOption = "UnderscoreEscapingWithSuffixes"
	// UnderscoreEscapingWithoutSuffixes translates metric name characters that
	// are not alphanumerics/underscores/colons to underscores, and label name
	// characters that are not alphanumerics/underscores to underscores, but
	// unlike UnderscoreEscapingWithSuffixes it does not append any suffixes to
	// the names.
	UnderscoreEscapingWithoutSuffixes TranslationStrategyOption = "UnderscoreEscapingWithoutSuffixes"
	// NoTranslation (EXPERIMENTAL): disables all translation of incoming metric
	// and label names. This offers a way for the OTLP users to use native metric
	// names, reducing confusion.
	//
	// WARNING: This setting has significant known risks and limitations (see
	// https://prometheus.io/docs/practices/naming/  for details): * Impaired UX
	// when using PromQL in plain YAML (e.g. alerts, rules, dashboard, autoscaling
	// configuration). * Series collisions which in the best case may result in
	// OOO errors, in the worst case a silently malformed time series. For
	// instance, you may end up in situation of ingesting `foo.bar` series with
	// unit `seconds` and a separate series `foo.bar` with unit `milliseconds`.
	//
	// As a result, this setting is experimental and currently, should not be used
	// in production systems.
	//
	// TODO(ArthurSens): Mention `type-and-unit-labels` feature
	// (https://github.com/prometheus/proposals/pull/39) once released, as
	// potential mitigation of the above risks.
	NoTranslation TranslationStrategyOption = "NoTranslation"
)

func (TranslationStrategyOption) ShouldAddSuffixes added in v0.0.2

func (o TranslationStrategyOption) ShouldAddSuffixes() bool

ShouldAddSuffixes returns a bool deciding whether the given translation strategy should have suffixes added.

func (TranslationStrategyOption) ShouldEscape added in v0.0.2

func (o TranslationStrategyOption) ShouldEscape() bool

ShouldEscape returns true if the translation strategy requires that metric names be escaped.

type UnitNamer

type UnitNamer struct {
	UTF8Allowed bool
}

UnitNamer is a helper for building compliant unit names. It processes OpenTelemetry Protocol (OTLP) unit strings and converts them to Prometheus-compliant unit names.

Example usage:

namer := UnitNamer{UTF8Allowed: false}
result := namer.Build("s")     // "seconds"
result = namer.Build("By/s")   // "bytes_per_second"

func (*UnitNamer) Build

func (un *UnitNamer) Build(unit string) string

Build builds a unit name for the specified unit string. It processes the unit by splitting it into main and per components, applying unit mappings, and cleaning up invalid characters when UTF8Allowed is false.

Unit mappings include:

  • Time: s→seconds, ms→milliseconds, h→hours
  • Bytes: By→bytes, KBy→kilobytes, MBy→megabytes
  • SI: m→meters, V→volts, W→watts
  • Special: 1→"" (empty), %→percent

Examples:

namer := UnitNamer{UTF8Allowed: false}
namer.Build("s")           // "seconds"
namer.Build("requests/s")  // "requests_per_second"
namer.Build("1")           // "" (dimensionless)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL