mirror of
https://github.com/prometheus/prometheus.git
synced 2025-08-06 14:17:12 +02:00
otlp: update otlptranslator package (#16961)
* otlp: update otlptranslator package Signed-off-by: Owen Williams <owen.williams@grafana.com> * lint Signed-off-by: Owen Williams <owen.williams@grafana.com> * lint Signed-off-by: Owen Williams <owen.williams@grafana.com> * catch err Signed-off-by: Owen Williams <owen.williams@grafana.com> --------- Signed-off-by: Owen Williams <owen.williams@grafana.com>
This commit is contained in:
parent
789fddf25a
commit
5cc49720ac
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/grafana/regexp"
|
"github.com/grafana/regexp"
|
||||||
"github.com/prometheus/common/config"
|
"github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
"github.com/prometheus/otlptranslator"
|
||||||
"github.com/prometheus/sigv4"
|
"github.com/prometheus/sigv4"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
@ -104,9 +105,9 @@ func Load(s string, logger *slog.Logger) (*Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch cfg.OTLPConfig.TranslationStrategy {
|
switch cfg.OTLPConfig.TranslationStrategy {
|
||||||
case UnderscoreEscapingWithSuffixes, UnderscoreEscapingWithoutSuffixes:
|
case otlptranslator.UnderscoreEscapingWithSuffixes, otlptranslator.UnderscoreEscapingWithoutSuffixes:
|
||||||
case "":
|
case "":
|
||||||
case NoTranslation, NoUTF8EscapingWithSuffixes:
|
case otlptranslator.NoTranslation, otlptranslator.NoUTF8EscapingWithSuffixes:
|
||||||
if cfg.GlobalConfig.MetricNameValidationScheme == model.LegacyValidation {
|
if cfg.GlobalConfig.MetricNameValidationScheme == model.LegacyValidation {
|
||||||
return nil, fmt.Errorf("OTLP translation strategy %q is not allowed when UTF8 is disabled", cfg.OTLPConfig.TranslationStrategy)
|
return nil, fmt.Errorf("OTLP translation strategy %q is not allowed when UTF8 is disabled", cfg.OTLPConfig.TranslationStrategy)
|
||||||
}
|
}
|
||||||
@ -257,7 +258,7 @@ var (
|
|||||||
|
|
||||||
// DefaultOTLPConfig is the default OTLP configuration.
|
// DefaultOTLPConfig is the default OTLP configuration.
|
||||||
DefaultOTLPConfig = OTLPConfig{
|
DefaultOTLPConfig = OTLPConfig{
|
||||||
TranslationStrategy: UnderscoreEscapingWithSuffixes,
|
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1531,79 +1532,14 @@ func getGoGC() int {
|
|||||||
return DefaultGoGCPercentage
|
return DefaultGoGCPercentage
|
||||||
}
|
}
|
||||||
|
|
||||||
type translationStrategyOption string
|
|
||||||
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ShouldEscape returns true if the translation strategy requires that metric
|
|
||||||
// names be escaped.
|
|
||||||
func (o translationStrategyOption) ShouldEscape() bool {
|
|
||||||
switch o {
|
|
||||||
case UnderscoreEscapingWithSuffixes, UnderscoreEscapingWithoutSuffixes:
|
|
||||||
return true
|
|
||||||
case NoTranslation, NoUTF8EscapingWithSuffixes:
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShouldAddSuffixes returns a bool deciding whether the given translation
|
|
||||||
// strategy should have suffixes added.
|
|
||||||
func (o translationStrategyOption) ShouldAddSuffixes() bool {
|
|
||||||
switch o {
|
|
||||||
case UnderscoreEscapingWithSuffixes, NoUTF8EscapingWithSuffixes:
|
|
||||||
return true
|
|
||||||
case UnderscoreEscapingWithoutSuffixes, NoTranslation:
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OTLPConfig is the configuration for writing to the OTLP endpoint.
|
// OTLPConfig is the configuration for writing to the OTLP endpoint.
|
||||||
type OTLPConfig struct {
|
type OTLPConfig struct {
|
||||||
PromoteAllResourceAttributes bool `yaml:"promote_all_resource_attributes,omitempty"`
|
PromoteAllResourceAttributes bool `yaml:"promote_all_resource_attributes,omitempty"`
|
||||||
PromoteResourceAttributes []string `yaml:"promote_resource_attributes,omitempty"`
|
PromoteResourceAttributes []string `yaml:"promote_resource_attributes,omitempty"`
|
||||||
IgnoreResourceAttributes []string `yaml:"ignore_resource_attributes,omitempty"`
|
IgnoreResourceAttributes []string `yaml:"ignore_resource_attributes,omitempty"`
|
||||||
TranslationStrategy translationStrategyOption `yaml:"translation_strategy,omitempty"`
|
TranslationStrategy otlptranslator.TranslationStrategyOption `yaml:"translation_strategy,omitempty"`
|
||||||
KeepIdentifyingResourceAttributes bool `yaml:"keep_identifying_resource_attributes,omitempty"`
|
KeepIdentifyingResourceAttributes bool `yaml:"keep_identifying_resource_attributes,omitempty"`
|
||||||
ConvertHistogramsToNHCB bool `yaml:"convert_histograms_to_nhcb,omitempty"`
|
ConvertHistogramsToNHCB bool `yaml:"convert_histograms_to_nhcb,omitempty"`
|
||||||
// PromoteScopeMetadata controls whether to promote OTel scope metadata (i.e. name, version, schema URL, and attributes) to metric labels.
|
// PromoteScopeMetadata controls whether to promote OTel scope metadata (i.e. name, version, schema URL, and attributes) to metric labels.
|
||||||
// As per OTel spec, the aforementioned scope metadata should be identifying, i.e. made into metric labels.
|
// As per OTel spec, the aforementioned scope metadata should be identifying, i.e. made into metric labels.
|
||||||
PromoteScopeMetadata bool `yaml:"promote_scope_metadata,omitempty"`
|
PromoteScopeMetadata bool `yaml:"promote_scope_metadata,omitempty"`
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/prometheus/common/config"
|
"github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/common/promslog"
|
"github.com/prometheus/common/promslog"
|
||||||
|
"github.com/prometheus/otlptranslator"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
@ -170,7 +171,7 @@ var expectedConf = &Config{
|
|||||||
PromoteResourceAttributes: []string{
|
PromoteResourceAttributes: []string{
|
||||||
"k8s.cluster.name", "k8s.job.name", "k8s.namespace.name",
|
"k8s.cluster.name", "k8s.job.name", "k8s.namespace.name",
|
||||||
},
|
},
|
||||||
TranslationStrategy: UnderscoreEscapingWithSuffixes,
|
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||||
},
|
},
|
||||||
|
|
||||||
RemoteReadConfigs: []*RemoteReadConfig{
|
RemoteReadConfigs: []*RemoteReadConfig{
|
||||||
@ -1828,7 +1829,7 @@ func TestOTLPAllowUTF8(t *testing.T) {
|
|||||||
verify := func(t *testing.T, conf *Config, err error) {
|
verify := func(t *testing.T, conf *Config, err error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, NoUTF8EscapingWithSuffixes, conf.OTLPConfig.TranslationStrategy)
|
require.Equal(t, otlptranslator.NoUTF8EscapingWithSuffixes, conf.OTLPConfig.TranslationStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("LoadFile", func(t *testing.T) {
|
t.Run("LoadFile", func(t *testing.T) {
|
||||||
@ -1868,7 +1869,7 @@ func TestOTLPAllowUTF8(t *testing.T) {
|
|||||||
verify := func(t *testing.T, conf *Config, err error) {
|
verify := func(t *testing.T, conf *Config, err error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, NoTranslation, conf.OTLPConfig.TranslationStrategy)
|
require.Equal(t, otlptranslator.NoTranslation, conf.OTLPConfig.TranslationStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("LoadFile", func(t *testing.T) {
|
t.Run("LoadFile", func(t *testing.T) {
|
||||||
@ -1927,7 +1928,7 @@ func TestOTLPAllowUTF8(t *testing.T) {
|
|||||||
verify := func(t *testing.T, conf *Config, err error) {
|
verify := func(t *testing.T, conf *Config, err error) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, UnderscoreEscapingWithSuffixes, conf.OTLPConfig.TranslationStrategy)
|
require.Equal(t, otlptranslator.UnderscoreEscapingWithSuffixes, conf.OTLPConfig.TranslationStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("LoadFile", func(t *testing.T) {
|
t.Run("LoadFile", func(t *testing.T) {
|
||||||
|
2
go.mod
2
go.mod
@ -206,7 +206,7 @@ require (
|
|||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/prometheus/otlptranslator v0.0.0-20250620074007-94f535e0c588
|
github.com/prometheus/otlptranslator v0.0.0-20250731173911-a9673827589a
|
||||||
github.com/prometheus/procfs v0.16.1 // indirect
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/stretchr/objx v0.5.2 // indirect
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -460,8 +460,8 @@ github.com/prometheus/common/assets v0.2.0 h1:0P5OrzoHrYBOSM1OigWL3mY8ZvV2N4zIE/
|
|||||||
github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI=
|
github.com/prometheus/common/assets v0.2.0/go.mod h1:D17UVUE12bHbim7HzwUvtqm6gwBEaDQ0F+hIGbFbccI=
|
||||||
github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
|
github.com/prometheus/exporter-toolkit v0.14.0 h1:NMlswfibpcZZ+H0sZBiTjrA3/aBFHkNZqE+iCj5EmRg=
|
||||||
github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
|
github.com/prometheus/exporter-toolkit v0.14.0/go.mod h1:Gu5LnVvt7Nr/oqTBUC23WILZepW0nffNo10XdhQcwWA=
|
||||||
github.com/prometheus/otlptranslator v0.0.0-20250620074007-94f535e0c588 h1:QlySqDdSESgWDePeAYskbbcKKdowI26m9aU9zloHyYE=
|
github.com/prometheus/otlptranslator v0.0.0-20250731173911-a9673827589a h1:r2csuCATbgDz2Nk2PkKo7b6x7ErrF3NMmxwH0fifqN8=
|
||||||
github.com/prometheus/otlptranslator v0.0.0-20250620074007-94f535e0c588/go.mod h1:P8AwMgdD7XEr6QRUJ2QWLpiAZTgTE2UYgjlu3svompI=
|
github.com/prometheus/otlptranslator v0.0.0-20250731173911-a9673827589a/go.mod h1:P8AwMgdD7XEr6QRUJ2QWLpiAZTgTE2UYgjlu3svompI=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||||
|
@ -120,7 +120,7 @@ var seps = []byte{'\xff'}
|
|||||||
// If settings.PromoteResourceAttributes is not empty, it's a set of resource attributes that should be promoted to labels.
|
// If settings.PromoteResourceAttributes is not empty, it's a set of resource attributes that should be promoted to labels.
|
||||||
func createAttributes(resource pcommon.Resource, attributes pcommon.Map, scope scope, settings Settings,
|
func createAttributes(resource pcommon.Resource, attributes pcommon.Map, scope scope, settings Settings,
|
||||||
ignoreAttrs []string, logOnOverwrite bool, metadata prompb.MetricMetadata, extras ...string,
|
ignoreAttrs []string, logOnOverwrite bool, metadata prompb.MetricMetadata, extras ...string,
|
||||||
) []prompb.Label {
|
) ([]prompb.Label, error) {
|
||||||
resourceAttrs := resource.Attributes()
|
resourceAttrs := resource.Attributes()
|
||||||
serviceName, haveServiceName := resourceAttrs.Get(conventions.AttributeServiceName)
|
serviceName, haveServiceName := resourceAttrs.Get(conventions.AttributeServiceName)
|
||||||
instance, haveInstanceID := resourceAttrs.Get(conventions.AttributeServiceInstanceID)
|
instance, haveInstanceID := resourceAttrs.Get(conventions.AttributeServiceInstanceID)
|
||||||
@ -164,7 +164,10 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, scope s
|
|||||||
l := make(map[string]string, maxLabelCount)
|
l := make(map[string]string, maxLabelCount)
|
||||||
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: settings.AllowUTF8}
|
labelNamer := otlptranslator.LabelNamer{UTF8Allowed: settings.AllowUTF8}
|
||||||
for _, label := range labels {
|
for _, label := range labels {
|
||||||
finalKey := labelNamer.Build(label.Name)
|
finalKey, err := labelNamer.Build(label.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if existingValue, alreadyExists := l[finalKey]; alreadyExists {
|
if existingValue, alreadyExists := l[finalKey]; alreadyExists {
|
||||||
l[finalKey] = existingValue + ";" + label.Value
|
l[finalKey] = existingValue + ";" + label.Value
|
||||||
} else {
|
} else {
|
||||||
@ -173,17 +176,28 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, scope s
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, lbl := range promotedAttrs {
|
for _, lbl := range promotedAttrs {
|
||||||
normalized := labelNamer.Build(lbl.Name)
|
normalized, err := labelNamer.Build(lbl.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if _, exists := l[normalized]; !exists {
|
if _, exists := l[normalized]; !exists {
|
||||||
l[normalized] = lbl.Value
|
l[normalized] = lbl.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if promoteScope {
|
if promoteScope {
|
||||||
|
var rangeErr error
|
||||||
scope.attributes.Range(func(k string, v pcommon.Value) bool {
|
scope.attributes.Range(func(k string, v pcommon.Value) bool {
|
||||||
name := labelNamer.Build("otel_scope_" + k)
|
name, err := labelNamer.Build("otel_scope_" + k)
|
||||||
|
if err != nil {
|
||||||
|
rangeErr = err
|
||||||
|
return false
|
||||||
|
}
|
||||||
l[name] = v.AsString()
|
l[name] = v.AsString()
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
if rangeErr != nil {
|
||||||
|
return nil, rangeErr
|
||||||
|
}
|
||||||
// Scope Name, Version and Schema URL are added after attributes to ensure they are not overwritten by attributes.
|
// Scope Name, Version and Schema URL are added after attributes to ensure they are not overwritten by attributes.
|
||||||
l["otel_scope_name"] = scope.name
|
l["otel_scope_name"] = scope.name
|
||||||
l["otel_scope_version"] = scope.version
|
l["otel_scope_version"] = scope.version
|
||||||
@ -233,7 +247,11 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, scope s
|
|||||||
}
|
}
|
||||||
// internal labels should be maintained.
|
// internal labels should be maintained.
|
||||||
if len(name) <= 4 || name[:2] != "__" || name[len(name)-2:] != "__" {
|
if len(name) <= 4 || name[:2] != "__" || name[len(name)-2:] != "__" {
|
||||||
name = labelNamer.Build(name)
|
var err error
|
||||||
|
name, err = labelNamer.Build(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
l[name] = extras[i+1]
|
l[name] = extras[i+1]
|
||||||
}
|
}
|
||||||
@ -243,7 +261,7 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, scope s
|
|||||||
labels = append(labels, prompb.Label{Name: k, Value: v})
|
labels = append(labels, prompb.Label{Name: k, Value: v})
|
||||||
}
|
}
|
||||||
|
|
||||||
return labels
|
return labels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func aggregationTemporality(metric pmetric.Metric) (pmetric.AggregationTemporality, bool, error) {
|
func aggregationTemporality(metric pmetric.Metric) (pmetric.AggregationTemporality, bool, error) {
|
||||||
@ -278,7 +296,10 @@ func (c *PrometheusConverter) addHistogramDataPoints(ctx context.Context, dataPo
|
|||||||
|
|
||||||
pt := dataPoints.At(x)
|
pt := dataPoints.At(x)
|
||||||
timestamp := convertTimeStamp(pt.Timestamp())
|
timestamp := convertTimeStamp(pt.Timestamp())
|
||||||
baseLabels := createAttributes(resource, pt.Attributes(), scope, settings, nil, false, metadata)
|
baseLabels, err := createAttributes(resource, pt.Attributes(), scope, settings, nil, false, metadata)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// If the sum is unset, it indicates the _sum metric point should be
|
// If the sum is unset, it indicates the _sum metric point should be
|
||||||
// omitted
|
// omitted
|
||||||
@ -488,7 +509,10 @@ func (c *PrometheusConverter) addSummaryDataPoints(ctx context.Context, dataPoin
|
|||||||
|
|
||||||
pt := dataPoints.At(x)
|
pt := dataPoints.At(x)
|
||||||
timestamp := convertTimeStamp(pt.Timestamp())
|
timestamp := convertTimeStamp(pt.Timestamp())
|
||||||
baseLabels := createAttributes(resource, pt.Attributes(), scope, settings, nil, false, metadata)
|
baseLabels, err := createAttributes(resource, pt.Attributes(), scope, settings, nil, false, metadata)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// treat sum as a sample in an individual TimeSeries
|
// treat sum as a sample in an individual TimeSeries
|
||||||
sum := &prompb.Sample{
|
sum := &prompb.Sample{
|
||||||
@ -622,9 +646,9 @@ func (c *PrometheusConverter) addTimeSeriesIfNeeded(lbls []prompb.Label, startTi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// addResourceTargetInfo converts the resource to the target info metric.
|
// addResourceTargetInfo converts the resource to the target info metric.
|
||||||
func addResourceTargetInfo(resource pcommon.Resource, settings Settings, earliestTimestamp, latestTimestamp time.Time, converter *PrometheusConverter) {
|
func addResourceTargetInfo(resource pcommon.Resource, settings Settings, earliestTimestamp, latestTimestamp time.Time, converter *PrometheusConverter) error {
|
||||||
if settings.DisableTargetInfo {
|
if settings.DisableTargetInfo {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes := resource.Attributes()
|
attributes := resource.Attributes()
|
||||||
@ -642,7 +666,7 @@ func addResourceTargetInfo(resource pcommon.Resource, settings Settings, earlies
|
|||||||
}
|
}
|
||||||
if nonIdentifyingAttrsCount == 0 {
|
if nonIdentifyingAttrsCount == 0 {
|
||||||
// If we only have job + instance, then target_info isn't useful, so don't add it.
|
// If we only have job + instance, then target_info isn't useful, so don't add it.
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
name := targetMetricName
|
name := targetMetricName
|
||||||
@ -655,7 +679,10 @@ func addResourceTargetInfo(resource pcommon.Resource, settings Settings, earlies
|
|||||||
// Do not pass identifying attributes as ignoreAttrs below.
|
// Do not pass identifying attributes as ignoreAttrs below.
|
||||||
identifyingAttrs = nil
|
identifyingAttrs = nil
|
||||||
}
|
}
|
||||||
labels := createAttributes(resource, attributes, scope{}, settings, identifyingAttrs, false, prompb.MetricMetadata{}, model.MetricNameLabel, name)
|
labels, err := createAttributes(resource, attributes, scope{}, settings, identifyingAttrs, false, prompb.MetricMetadata{}, model.MetricNameLabel, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
haveIdentifier := false
|
haveIdentifier := false
|
||||||
for _, l := range labels {
|
for _, l := range labels {
|
||||||
if l.Name == model.JobLabel || l.Name == model.InstanceLabel {
|
if l.Name == model.JobLabel || l.Name == model.InstanceLabel {
|
||||||
@ -666,7 +693,7 @@ func addResourceTargetInfo(resource pcommon.Resource, settings Settings, earlies
|
|||||||
|
|
||||||
if !haveIdentifier {
|
if !haveIdentifier {
|
||||||
// We need at least one identifying label to generate target_info.
|
// We need at least one identifying label to generate target_info.
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate target_info samples starting at earliestTimestamp and ending at latestTimestamp,
|
// Generate target_info samples starting at earliestTimestamp and ending at latestTimestamp,
|
||||||
@ -688,6 +715,7 @@ func addResourceTargetInfo(resource pcommon.Resource, settings Settings, earlies
|
|||||||
Value: float64(1),
|
Value: float64(1),
|
||||||
Timestamp: latestTimestamp.UnixMilli(),
|
Timestamp: latestTimestamp.UnixMilli(),
|
||||||
})
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertTimeStamp converts OTLP timestamp in ns to timestamp in ms.
|
// convertTimeStamp converts OTLP timestamp in ns to timestamp in ms.
|
||||||
|
@ -531,7 +531,8 @@ func TestCreateAttributes(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
PromoteScopeMetadata: tc.promoteScope,
|
PromoteScopeMetadata: tc.promoteScope,
|
||||||
}
|
}
|
||||||
lbls := createAttributes(resource, attrs, tc.scope, settings, tc.ignoreAttrs, false, prompb.MetricMetadata{}, model.MetricNameLabel, "test_metric")
|
lbls, err := createAttributes(resource, attrs, tc.scope, settings, tc.ignoreAttrs, false, prompb.MetricMetadata{}, model.MetricNameLabel, "test_metric")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
require.ElementsMatch(t, lbls, tc.expectedLabels)
|
require.ElementsMatch(t, lbls, tc.expectedLabels)
|
||||||
})
|
})
|
||||||
|
@ -52,7 +52,7 @@ func (c *PrometheusConverter) addExponentialHistogramDataPoints(ctx context.Cont
|
|||||||
return annots, err
|
return annots, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lbls := createAttributes(
|
lbls, err := createAttributes(
|
||||||
resource,
|
resource,
|
||||||
pt.Attributes(),
|
pt.Attributes(),
|
||||||
scope,
|
scope,
|
||||||
@ -63,7 +63,9 @@ func (c *PrometheusConverter) addExponentialHistogramDataPoints(ctx context.Cont
|
|||||||
model.MetricNameLabel,
|
model.MetricNameLabel,
|
||||||
metadata.MetricFamilyName,
|
metadata.MetricFamilyName,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
ts, _ := c.getOrCreateTimeSeries(lbls)
|
ts, _ := c.getOrCreateTimeSeries(lbls)
|
||||||
ts.Histograms = append(ts.Histograms, histogram)
|
ts.Histograms = append(ts.Histograms, histogram)
|
||||||
|
|
||||||
@ -271,7 +273,7 @@ func (c *PrometheusConverter) addCustomBucketsHistogramDataPoints(ctx context.Co
|
|||||||
return annots, err
|
return annots, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lbls := createAttributes(
|
lbls, err := createAttributes(
|
||||||
resource,
|
resource,
|
||||||
pt.Attributes(),
|
pt.Attributes(),
|
||||||
scope,
|
scope,
|
||||||
@ -282,6 +284,9 @@ func (c *PrometheusConverter) addCustomBucketsHistogramDataPoints(ctx context.Co
|
|||||||
model.MetricNameLabel,
|
model.MetricNameLabel,
|
||||||
metadata.MetricFamilyName,
|
metadata.MetricFamilyName,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
ts, _ := c.getOrCreateTimeSeries(lbls)
|
ts, _ := c.getOrCreateTimeSeries(lbls)
|
||||||
ts.Histograms = append(ts.Histograms, histogram)
|
ts.Histograms = append(ts.Histograms, histogram)
|
||||||
|
@ -847,6 +847,8 @@ func TestPrometheusConverter_addExponentialHistogramDataPoints(t *testing.T) {
|
|||||||
namer := otlptranslator.MetricNamer{
|
namer := otlptranslator.MetricNamer{
|
||||||
WithMetricSuffixes: true,
|
WithMetricSuffixes: true,
|
||||||
}
|
}
|
||||||
|
name, err := namer.Build(TranslatorMetricFromOtelMetric(metric))
|
||||||
|
require.NoError(t, err)
|
||||||
annots, err := converter.addExponentialHistogramDataPoints(
|
annots, err := converter.addExponentialHistogramDataPoints(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
metric.ExponentialHistogram().DataPoints(),
|
metric.ExponentialHistogram().DataPoints(),
|
||||||
@ -855,7 +857,7 @@ func TestPrometheusConverter_addExponentialHistogramDataPoints(t *testing.T) {
|
|||||||
ExportCreatedMetric: true,
|
ExportCreatedMetric: true,
|
||||||
PromoteScopeMetadata: tt.promoteScope,
|
PromoteScopeMetadata: tt.promoteScope,
|
||||||
},
|
},
|
||||||
prompb.MetricMetadata{MetricFamilyName: namer.Build(TranslatorMetricFromOtelMetric(metric))},
|
prompb.MetricMetadata{MetricFamilyName: name},
|
||||||
pmetric.AggregationTemporalityCumulative,
|
pmetric.AggregationTemporalityCumulative,
|
||||||
tt.scope,
|
tt.scope,
|
||||||
)
|
)
|
||||||
@ -1303,6 +1305,8 @@ func TestPrometheusConverter_addCustomBucketsHistogramDataPoints(t *testing.T) {
|
|||||||
namer := otlptranslator.MetricNamer{
|
namer := otlptranslator.MetricNamer{
|
||||||
WithMetricSuffixes: true,
|
WithMetricSuffixes: true,
|
||||||
}
|
}
|
||||||
|
name, err := namer.Build(TranslatorMetricFromOtelMetric(metric))
|
||||||
|
require.NoError(t, err)
|
||||||
annots, err := converter.addCustomBucketsHistogramDataPoints(
|
annots, err := converter.addCustomBucketsHistogramDataPoints(
|
||||||
context.Background(),
|
context.Background(),
|
||||||
metric.Histogram().DataPoints(),
|
metric.Histogram().DataPoints(),
|
||||||
@ -1312,7 +1316,7 @@ func TestPrometheusConverter_addCustomBucketsHistogramDataPoints(t *testing.T) {
|
|||||||
ConvertHistogramsToNHCB: true,
|
ConvertHistogramsToNHCB: true,
|
||||||
PromoteScopeMetadata: tt.promoteScope,
|
PromoteScopeMetadata: tt.promoteScope,
|
||||||
},
|
},
|
||||||
prompb.MetricMetadata{MetricFamilyName: namer.Build(TranslatorMetricFromOtelMetric(metric))},
|
prompb.MetricMetadata{MetricFamilyName: name},
|
||||||
pmetric.AggregationTemporalityCumulative,
|
pmetric.AggregationTemporalityCumulative,
|
||||||
tt.scope,
|
tt.scope,
|
||||||
)
|
)
|
||||||
|
@ -171,9 +171,14 @@ func (c *PrometheusConverter) FromMetrics(ctx context.Context, md pmetric.Metric
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
promName, err := namer.Build(TranslatorMetricFromOtelMetric(metric))
|
||||||
|
if err != nil {
|
||||||
|
errs = multierr.Append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
metadata := prompb.MetricMetadata{
|
metadata := prompb.MetricMetadata{
|
||||||
Type: otelMetricTypeToPromMetricType(metric),
|
Type: otelMetricTypeToPromMetricType(metric),
|
||||||
MetricFamilyName: namer.Build(TranslatorMetricFromOtelMetric(metric)),
|
MetricFamilyName: promName,
|
||||||
Help: metric.Description(),
|
Help: metric.Description(),
|
||||||
Unit: metric.Unit(),
|
Unit: metric.Unit(),
|
||||||
}
|
}
|
||||||
@ -273,7 +278,10 @@ func (c *PrometheusConverter) FromMetrics(ctx context.Context, md pmetric.Metric
|
|||||||
if earliestTimestamp < pcommon.Timestamp(math.MaxUint64) {
|
if earliestTimestamp < pcommon.Timestamp(math.MaxUint64) {
|
||||||
// We have at least one metric sample for this resource.
|
// We have at least one metric sample for this resource.
|
||||||
// Generate a corresponding target_info series.
|
// Generate a corresponding target_info series.
|
||||||
addResourceTargetInfo(resource, settings, earliestTimestamp.AsTime(), latestTimestamp.AsTime(), c)
|
err := addResourceTargetInfo(resource, settings, earliestTimestamp.AsTime(), latestTimestamp.AsTime(), c)
|
||||||
|
if err != nil {
|
||||||
|
errs = multierr.Append(errs, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,9 +310,11 @@ func TestFromMetrics(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namer := otlptranslator.MetricNamer{}
|
namer := otlptranslator.MetricNamer{}
|
||||||
|
name, err := namer.Build(TranslatorMetricFromOtelMetric(m))
|
||||||
|
require.NoError(t, err)
|
||||||
expMetadata = append(expMetadata, prompb.MetricMetadata{
|
expMetadata = append(expMetadata, prompb.MetricMetadata{
|
||||||
Type: otelMetricTypeToPromMetricType(m),
|
Type: otelMetricTypeToPromMetricType(m),
|
||||||
MetricFamilyName: namer.Build(TranslatorMetricFromOtelMetric(m)),
|
MetricFamilyName: name,
|
||||||
Help: m.Description(),
|
Help: m.Description(),
|
||||||
Unit: m.Unit(),
|
Unit: m.Unit(),
|
||||||
})
|
})
|
||||||
|
@ -37,7 +37,7 @@ func (c *PrometheusConverter) addGaugeNumberDataPoints(ctx context.Context, data
|
|||||||
}
|
}
|
||||||
|
|
||||||
pt := dataPoints.At(x)
|
pt := dataPoints.At(x)
|
||||||
labels := createAttributes(
|
labels, err := createAttributes(
|
||||||
resource,
|
resource,
|
||||||
pt.Attributes(),
|
pt.Attributes(),
|
||||||
scope,
|
scope,
|
||||||
@ -48,6 +48,9 @@ func (c *PrometheusConverter) addGaugeNumberDataPoints(ctx context.Context, data
|
|||||||
model.MetricNameLabel,
|
model.MetricNameLabel,
|
||||||
metadata.MetricFamilyName,
|
metadata.MetricFamilyName,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
sample := &prompb.Sample{
|
sample := &prompb.Sample{
|
||||||
// convert ns to ms
|
// convert ns to ms
|
||||||
Timestamp: convertTimeStamp(pt.Timestamp()),
|
Timestamp: convertTimeStamp(pt.Timestamp()),
|
||||||
@ -77,7 +80,7 @@ func (c *PrometheusConverter) addSumNumberDataPoints(ctx context.Context, dataPo
|
|||||||
}
|
}
|
||||||
|
|
||||||
pt := dataPoints.At(x)
|
pt := dataPoints.At(x)
|
||||||
lbls := createAttributes(
|
lbls, err := createAttributes(
|
||||||
resource,
|
resource,
|
||||||
pt.Attributes(),
|
pt.Attributes(),
|
||||||
scope,
|
scope,
|
||||||
@ -88,6 +91,9 @@ func (c *PrometheusConverter) addSumNumberDataPoints(ctx context.Context, dataPo
|
|||||||
model.MetricNameLabel,
|
model.MetricNameLabel,
|
||||||
metadata.MetricFamilyName,
|
metadata.MetricFamilyName,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
sample := &prompb.Sample{
|
sample := &prompb.Sample{
|
||||||
// convert ns to ms
|
// convert ns to ms
|
||||||
Timestamp: convertTimeStamp(pt.Timestamp()),
|
Timestamp: convertTimeStamp(pt.Timestamp()),
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
common_config "github.com/prometheus/common/config"
|
common_config "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
"github.com/prometheus/otlptranslator"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.opentelemetry.io/collector/pdata/pcommon"
|
"go.opentelemetry.io/collector/pdata/pcommon"
|
||||||
"go.opentelemetry.io/collector/pdata/pmetric"
|
"go.opentelemetry.io/collector/pdata/pmetric"
|
||||||
@ -392,7 +393,7 @@ func TestOTLPWriteHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "NoTranslation/NoTypeAndUnitLabels",
|
name: "NoTranslation/NoTypeAndUnitLabels",
|
||||||
otlpCfg: config.OTLPConfig{
|
otlpCfg: config.OTLPConfig{
|
||||||
TranslationStrategy: config.NoTranslation,
|
TranslationStrategy: otlptranslator.NoTranslation,
|
||||||
},
|
},
|
||||||
expectedSamples: []mockSample{
|
expectedSamples: []mockSample{
|
||||||
{
|
{
|
||||||
@ -418,7 +419,7 @@ func TestOTLPWriteHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "NoTranslation/WithTypeAndUnitLabels",
|
name: "NoTranslation/WithTypeAndUnitLabels",
|
||||||
otlpCfg: config.OTLPConfig{
|
otlpCfg: config.OTLPConfig{
|
||||||
TranslationStrategy: config.NoTranslation,
|
TranslationStrategy: otlptranslator.NoTranslation,
|
||||||
},
|
},
|
||||||
typeAndUnitLabels: true,
|
typeAndUnitLabels: true,
|
||||||
expectedSamples: []mockSample{
|
expectedSamples: []mockSample{
|
||||||
@ -447,7 +448,7 @@ func TestOTLPWriteHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "UnderscoreEscapingWithSuffixes/NoTypeAndUnitLabels",
|
name: "UnderscoreEscapingWithSuffixes/NoTypeAndUnitLabels",
|
||||||
otlpCfg: config.OTLPConfig{
|
otlpCfg: config.OTLPConfig{
|
||||||
TranslationStrategy: config.UnderscoreEscapingWithSuffixes,
|
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||||
},
|
},
|
||||||
expectedSamples: []mockSample{
|
expectedSamples: []mockSample{
|
||||||
{
|
{
|
||||||
@ -473,7 +474,7 @@ func TestOTLPWriteHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "UnderscoreEscapingWithoutSuffixes",
|
name: "UnderscoreEscapingWithoutSuffixes",
|
||||||
otlpCfg: config.OTLPConfig{
|
otlpCfg: config.OTLPConfig{
|
||||||
TranslationStrategy: config.UnderscoreEscapingWithoutSuffixes,
|
TranslationStrategy: otlptranslator.UnderscoreEscapingWithoutSuffixes,
|
||||||
},
|
},
|
||||||
expectedSamples: []mockSample{
|
expectedSamples: []mockSample{
|
||||||
{
|
{
|
||||||
@ -499,7 +500,7 @@ func TestOTLPWriteHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "UnderscoreEscapingWithSuffixes/WithTypeAndUnitLabels",
|
name: "UnderscoreEscapingWithSuffixes/WithTypeAndUnitLabels",
|
||||||
otlpCfg: config.OTLPConfig{
|
otlpCfg: config.OTLPConfig{
|
||||||
TranslationStrategy: config.UnderscoreEscapingWithSuffixes,
|
TranslationStrategy: otlptranslator.UnderscoreEscapingWithSuffixes,
|
||||||
},
|
},
|
||||||
typeAndUnitLabels: true,
|
typeAndUnitLabels: true,
|
||||||
expectedSamples: []mockSample{
|
expectedSamples: []mockSample{
|
||||||
@ -528,7 +529,7 @@ func TestOTLPWriteHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "NoUTF8EscapingWithSuffixes/NoTypeAndUnitLabels",
|
name: "NoUTF8EscapingWithSuffixes/NoTypeAndUnitLabels",
|
||||||
otlpCfg: config.OTLPConfig{
|
otlpCfg: config.OTLPConfig{
|
||||||
TranslationStrategy: config.NoUTF8EscapingWithSuffixes,
|
TranslationStrategy: otlptranslator.NoUTF8EscapingWithSuffixes,
|
||||||
},
|
},
|
||||||
expectedSamples: []mockSample{
|
expectedSamples: []mockSample{
|
||||||
{
|
{
|
||||||
@ -554,7 +555,7 @@ func TestOTLPWriteHandler(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "NoUTF8EscapingWithSuffixes/WithTypeAndUnitLabels",
|
name: "NoUTF8EscapingWithSuffixes/WithTypeAndUnitLabels",
|
||||||
otlpCfg: config.OTLPConfig{
|
otlpCfg: config.OTLPConfig{
|
||||||
TranslationStrategy: config.NoUTF8EscapingWithSuffixes,
|
TranslationStrategy: otlptranslator.NoUTF8EscapingWithSuffixes,
|
||||||
},
|
},
|
||||||
typeAndUnitLabels: true,
|
typeAndUnitLabels: true,
|
||||||
expectedSamples: []mockSample{
|
expectedSamples: []mockSample{
|
||||||
|
Loading…
Reference in New Issue
Block a user