mirror of
https://github.com/prometheus/prometheus.git
synced 2025-08-05 21:57:09 +02:00
Migrate otlptranslator package to prometheus/otlptranslator (#16240)
* Migrate otlptranslator package to prometheus/otlp-prometheus-translator --------- Signed-off-by: Arthur Silva Sens <arthursens2005@gmail.com>
This commit is contained in:
parent
eac37157ee
commit
b39672736a
11
go.mod
11
go.mod
@ -62,7 +62,7 @@ require (
|
|||||||
github.com/vultr/govultr/v2 v2.17.2
|
github.com/vultr/govultr/v2 v2.17.2
|
||||||
go.opentelemetry.io/collector/component v1.27.0
|
go.opentelemetry.io/collector/component v1.27.0
|
||||||
go.opentelemetry.io/collector/consumer v1.27.0
|
go.opentelemetry.io/collector/consumer v1.27.0
|
||||||
go.opentelemetry.io/collector/pdata v1.27.0
|
go.opentelemetry.io/collector/pdata v1.28.1
|
||||||
go.opentelemetry.io/collector/processor v0.121.0
|
go.opentelemetry.io/collector/processor v0.121.0
|
||||||
go.opentelemetry.io/collector/semconv v0.121.0
|
go.opentelemetry.io/collector/semconv v0.121.0
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0
|
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0
|
||||||
@ -80,7 +80,7 @@ require (
|
|||||||
go.uber.org/multierr v1.11.0
|
go.uber.org/multierr v1.11.0
|
||||||
golang.org/x/oauth2 v0.27.0
|
golang.org/x/oauth2 v0.27.0
|
||||||
golang.org/x/sync v0.12.0
|
golang.org/x/sync v0.12.0
|
||||||
golang.org/x/sys v0.30.0
|
golang.org/x/sys v0.31.0
|
||||||
golang.org/x/text v0.23.0
|
golang.org/x/text v0.23.0
|
||||||
google.golang.org/api v0.224.0
|
google.golang.org/api v0.224.0
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb
|
||||||
@ -181,6 +181,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-20250320144820-d800c8b0eb07
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.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
|
||||||
@ -193,11 +194,11 @@ require (
|
|||||||
go.opentelemetry.io/collector/pipeline v0.121.0 // indirect
|
go.opentelemetry.io/collector/pipeline v0.121.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/crypto v0.35.0 // indirect
|
golang.org/x/crypto v0.36.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
|
||||||
golang.org/x/mod v0.23.0 // indirect
|
golang.org/x/mod v0.23.0 // indirect
|
||||||
golang.org/x/net v0.35.0 // indirect
|
golang.org/x/net v0.37.0 // indirect
|
||||||
golang.org/x/term v0.29.0 // indirect
|
golang.org/x/term v0.30.0 // indirect
|
||||||
golang.org/x/time v0.10.0 // indirect
|
golang.org/x/time v0.10.0 // indirect
|
||||||
golang.org/x/tools v0.30.0 // indirect
|
golang.org/x/tools v0.30.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||||
|
22
go.sum
22
go.sum
@ -424,6 +424,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-20250320144820-d800c8b0eb07 h1:YaJ1JqyKGIUFIMUpMeT22yewZMXiTt5sLgWG1D/m4Yc=
|
||||||
|
github.com/prometheus/otlptranslator v0.0.0-20250320144820-d800c8b0eb07/go.mod h1:ZO/4EUanXL7wbvfMHcS+rq9sCBxICdaU8RBFkVg5wv0=
|
||||||
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=
|
||||||
@ -496,8 +498,8 @@ go.opentelemetry.io/collector/consumer/consumertest v0.121.0 h1:EIJPAXQY0w9j1k/e
|
|||||||
go.opentelemetry.io/collector/consumer/consumertest v0.121.0/go.mod h1:Hmj+TizzsLU0EmS2n/rJYScOybNmm3mrAjis6ed7qTw=
|
go.opentelemetry.io/collector/consumer/consumertest v0.121.0/go.mod h1:Hmj+TizzsLU0EmS2n/rJYScOybNmm3mrAjis6ed7qTw=
|
||||||
go.opentelemetry.io/collector/consumer/xconsumer v0.121.0 h1:/FJ7L6+G++FvktXc/aBnnYDIKLoYsWLh0pKbvzFFwF8=
|
go.opentelemetry.io/collector/consumer/xconsumer v0.121.0 h1:/FJ7L6+G++FvktXc/aBnnYDIKLoYsWLh0pKbvzFFwF8=
|
||||||
go.opentelemetry.io/collector/consumer/xconsumer v0.121.0/go.mod h1:KKy8Qg/vOnyseoi7A9/x1a1oEqSmf0WBHkJFlnQH0Ow=
|
go.opentelemetry.io/collector/consumer/xconsumer v0.121.0/go.mod h1:KKy8Qg/vOnyseoi7A9/x1a1oEqSmf0WBHkJFlnQH0Ow=
|
||||||
go.opentelemetry.io/collector/pdata v1.27.0 h1:66yI7FYkUDia74h48Fd2/KG2Vk8DxZnGw54wRXykCEU=
|
go.opentelemetry.io/collector/pdata v1.28.1 h1:ORl5WLpQJvjzBVpHu12lqKMdcf/qDBwRXMcUubhybiQ=
|
||||||
go.opentelemetry.io/collector/pdata v1.27.0/go.mod h1:18e8/xDZsqyj00h/5HM5GLdJgBzzG9Ei8g9SpNoiMtI=
|
go.opentelemetry.io/collector/pdata v1.28.1/go.mod h1:asKE8MD/4SOKz1mCrGdAz4VO2U2HUNg8A6094uK7pq0=
|
||||||
go.opentelemetry.io/collector/pdata/pprofile v0.121.0 h1:DFBelDRsZYxEaSoxSRtseAazsHJfqfC/Yl64uPicl2g=
|
go.opentelemetry.io/collector/pdata/pprofile v0.121.0 h1:DFBelDRsZYxEaSoxSRtseAazsHJfqfC/Yl64uPicl2g=
|
||||||
go.opentelemetry.io/collector/pdata/pprofile v0.121.0/go.mod h1:j/fjrd7ybJp/PXkba92QLzx7hykUVmU8x/WJvI2JWSg=
|
go.opentelemetry.io/collector/pdata/pprofile v0.121.0/go.mod h1:j/fjrd7ybJp/PXkba92QLzx7hykUVmU8x/WJvI2JWSg=
|
||||||
go.opentelemetry.io/collector/pdata/testdata v0.121.0 h1:FFz+rdb7o6JRZ82Zmp6WKEdKnEMaoF3jLb7F1F21ijg=
|
go.opentelemetry.io/collector/pdata/testdata v0.121.0 h1:FFz+rdb7o6JRZ82Zmp6WKEdKnEMaoF3jLb7F1F21ijg=
|
||||||
@ -549,8 +551,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
||||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
@ -567,8 +569,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
||||||
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -604,11 +606,11 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
||||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
@ -1,306 +0,0 @@
|
|||||||
// Copyright 2024 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.
|
|
||||||
// Provenance-includes-location: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/95e8f8fdc2a9dc87230406c9a3cf02be4fd68bea/pkg/translator/prometheus/normalize_name.go
|
|
||||||
// Provenance-includes-license: Apache-2.0
|
|
||||||
// Provenance-includes-copyright: Copyright The OpenTelemetry Authors.
|
|
||||||
|
|
||||||
package prometheus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"slices"
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"go.opentelemetry.io/collector/pdata/pmetric"
|
|
||||||
)
|
|
||||||
|
|
||||||
// The map to translate OTLP units to Prometheus units
|
|
||||||
// OTLP metrics use the c/s notation as specified at https://ucum.org/ucum.html
|
|
||||||
// (See also https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/README.md#instrument-units)
|
|
||||||
// Prometheus best practices for units: https://prometheus.io/docs/practices/naming/#base-units
|
|
||||||
// OpenMetrics specification for units: https://github.com/prometheus/OpenMetrics/blob/v1.0.0/specification/OpenMetrics.md#units-and-base-units
|
|
||||||
var unitMap = map[string]string{
|
|
||||||
// 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": "",
|
|
||||||
"%": "percent",
|
|
||||||
}
|
|
||||||
|
|
||||||
// The map that translates the "per" unit
|
|
||||||
// Example: s => per second (singular)
|
|
||||||
var perUnitMap = map[string]string{
|
|
||||||
"s": "second",
|
|
||||||
"m": "minute",
|
|
||||||
"h": "hour",
|
|
||||||
"d": "day",
|
|
||||||
"w": "week",
|
|
||||||
"mo": "month",
|
|
||||||
"y": "year",
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildCompliantMetricName builds a Prometheus-compliant metric name for the specified metric.
|
|
||||||
//
|
|
||||||
// Metric name is prefixed with specified namespace and underscore (if any).
|
|
||||||
// Namespace is not cleaned up. Make sure specified namespace follows Prometheus
|
|
||||||
// naming convention.
|
|
||||||
//
|
|
||||||
// See rules at https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels,
|
|
||||||
// https://prometheus.io/docs/practices/naming/#metric-and-label-naming
|
|
||||||
// and https://github.com/open-telemetry/opentelemetry-specification/blob/v1.38.0/specification/compatibility/prometheus_and_openmetrics.md#otlp-metric-points-to-prometheus.
|
|
||||||
func BuildCompliantMetricName(metric pmetric.Metric, namespace string, addMetricSuffixes bool) string {
|
|
||||||
// Full normalization following standard Prometheus naming conventions
|
|
||||||
if addMetricSuffixes {
|
|
||||||
return normalizeName(metric, namespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple case (no full normalization, no units, etc.).
|
|
||||||
metricName := strings.Join(strings.FieldsFunc(metric.Name(), func(r rune) bool {
|
|
||||||
return invalidMetricCharRE.MatchString(string(r))
|
|
||||||
}), "_")
|
|
||||||
|
|
||||||
// Namespace?
|
|
||||||
if namespace != "" {
|
|
||||||
return namespace + "_" + metricName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metric name starts with a digit? Prefix it with an underscore.
|
|
||||||
if metricName != "" && unicode.IsDigit(rune(metricName[0])) {
|
|
||||||
metricName = "_" + metricName
|
|
||||||
}
|
|
||||||
|
|
||||||
return metricName
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
nonMetricNameCharRE = regexp.MustCompile(`[^a-zA-Z0-9:]`)
|
|
||||||
// Regexp for metric name characters that should be replaced with _.
|
|
||||||
invalidMetricCharRE = regexp.MustCompile(`[^a-zA-Z0-9:_]`)
|
|
||||||
multipleUnderscoresRE = regexp.MustCompile(`__+`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Build a normalized name for the specified metric.
|
|
||||||
func normalizeName(metric pmetric.Metric, namespace string) string {
|
|
||||||
// Split metric name into "tokens" (of supported metric name runes).
|
|
||||||
// Note that this has the side effect of replacing multiple consecutive underscores with a single underscore.
|
|
||||||
// This is part of the OTel to Prometheus specification: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.38.0/specification/compatibility/prometheus_and_openmetrics.md#otlp-metric-points-to-prometheus.
|
|
||||||
nameTokens := strings.FieldsFunc(
|
|
||||||
metric.Name(),
|
|
||||||
func(r rune) bool { return nonMetricNameCharRE.MatchString(string(r)) },
|
|
||||||
)
|
|
||||||
|
|
||||||
mainUnitSuffix, perUnitSuffix := buildUnitSuffixes(metric.Unit())
|
|
||||||
nameTokens = addUnitTokens(nameTokens, cleanUpUnit(mainUnitSuffix), cleanUpUnit(perUnitSuffix))
|
|
||||||
|
|
||||||
// Append _total for Counters
|
|
||||||
if metric.Type() == pmetric.MetricTypeSum && metric.Sum().IsMonotonic() {
|
|
||||||
nameTokens = append(removeItem(nameTokens, "total"), "total")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append _ratio for metrics with unit "1"
|
|
||||||
// Some OTel receivers improperly use unit "1" for counters of objects
|
|
||||||
// See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aissue+some+metric+units+don%27t+follow+otel+semantic+conventions
|
|
||||||
// Until these issues have been fixed, we're appending `_ratio` for gauges ONLY
|
|
||||||
// Theoretically, counters could be ratios as well, but it's absurd (for mathematical reasons)
|
|
||||||
if metric.Unit() == "1" && metric.Type() == pmetric.MetricTypeGauge {
|
|
||||||
nameTokens = append(removeItem(nameTokens, "ratio"), "ratio")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Namespace?
|
|
||||||
if namespace != "" {
|
|
||||||
nameTokens = append([]string{namespace}, nameTokens...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the string from the tokens, separated with underscores
|
|
||||||
normalizedName := strings.Join(nameTokens, "_")
|
|
||||||
|
|
||||||
// Metric name cannot start with a digit, so prefix it with "_" in this case
|
|
||||||
if normalizedName != "" && unicode.IsDigit(rune(normalizedName[0])) {
|
|
||||||
normalizedName = "_" + normalizedName
|
|
||||||
}
|
|
||||||
|
|
||||||
return normalizedName
|
|
||||||
}
|
|
||||||
|
|
||||||
// addUnitTokens will add the suffixes to the nameTokens if they are not already present.
|
|
||||||
// It will also remove trailing underscores from the main suffix to avoid double underscores
|
|
||||||
// when joining the tokens.
|
|
||||||
//
|
|
||||||
// If the 'per' unit ends with underscore, the underscore will be removed. If the per unit is just
|
|
||||||
// 'per_', it will be entirely removed.
|
|
||||||
func addUnitTokens(nameTokens []string, mainUnitSuffix, perUnitSuffix string) []string {
|
|
||||||
if slices.Contains(nameTokens, mainUnitSuffix) {
|
|
||||||
mainUnitSuffix = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if perUnitSuffix == "per_" {
|
|
||||||
perUnitSuffix = ""
|
|
||||||
} else {
|
|
||||||
perUnitSuffix = strings.TrimSuffix(perUnitSuffix, "_")
|
|
||||||
if slices.Contains(nameTokens, perUnitSuffix) {
|
|
||||||
perUnitSuffix = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if perUnitSuffix != "" {
|
|
||||||
mainUnitSuffix = strings.TrimSuffix(mainUnitSuffix, "_")
|
|
||||||
}
|
|
||||||
|
|
||||||
if mainUnitSuffix != "" {
|
|
||||||
nameTokens = append(nameTokens, mainUnitSuffix)
|
|
||||||
}
|
|
||||||
if perUnitSuffix != "" {
|
|
||||||
nameTokens = append(nameTokens, perUnitSuffix)
|
|
||||||
}
|
|
||||||
return nameTokens
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanUpUnit cleans up unit so it matches model.LabelNameRE.
|
|
||||||
func cleanUpUnit(unit string) string {
|
|
||||||
// Multiple consecutive underscores are replaced with a single underscore.
|
|
||||||
// This is part of the OTel to Prometheus specification: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.38.0/specification/compatibility/prometheus_and_openmetrics.md#otlp-metric-points-to-prometheus.
|
|
||||||
return strings.TrimPrefix(multipleUnderscoresRE.ReplaceAllString(
|
|
||||||
nonMetricNameCharRE.ReplaceAllString(unit, "_"),
|
|
||||||
"_",
|
|
||||||
), "_")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the Prometheus "basic" unit corresponding to the specified "basic" unit
|
|
||||||
// Returns the specified unit if not found in unitMap
|
|
||||||
func unitMapGetOrDefault(unit string) string {
|
|
||||||
if promUnit, ok := unitMap[unit]; ok {
|
|
||||||
return promUnit
|
|
||||||
}
|
|
||||||
return unit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the Prometheus "per" unit corresponding to the specified "per" unit
|
|
||||||
// Returns the specified unit if not found in perUnitMap
|
|
||||||
func perUnitMapGetOrDefault(perUnit string) string {
|
|
||||||
if promPerUnit, ok := perUnitMap[perUnit]; ok {
|
|
||||||
return promPerUnit
|
|
||||||
}
|
|
||||||
return perUnit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the specified value from the slice
|
|
||||||
func removeItem(slice []string, value string) []string {
|
|
||||||
newSlice := make([]string, 0, len(slice))
|
|
||||||
for _, sliceEntry := range slice {
|
|
||||||
if sliceEntry != value {
|
|
||||||
newSlice = append(newSlice, sliceEntry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newSlice
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildMetricName builds a valid metric name but without following Prometheus naming conventions.
|
|
||||||
// It doesn't do any character transformation, it only prefixes the metric name with the namespace, if any,
|
|
||||||
// and adds metric type suffixes, e.g. "_total" for counters and unit suffixes.
|
|
||||||
//
|
|
||||||
// Differently from BuildCompliantMetricName, it doesn't check for the presence of unit and type suffixes.
|
|
||||||
// If "addMetricSuffixes" is true, it will add them anyway.
|
|
||||||
//
|
|
||||||
// Please use BuildCompliantMetricName for a metric name that follows Prometheus naming conventions.
|
|
||||||
func BuildMetricName(metric pmetric.Metric, namespace string, addMetricSuffixes bool) string {
|
|
||||||
metricName := metric.Name()
|
|
||||||
|
|
||||||
if namespace != "" {
|
|
||||||
metricName = namespace + "_" + metricName
|
|
||||||
}
|
|
||||||
|
|
||||||
if addMetricSuffixes {
|
|
||||||
mainUnitSuffix, perUnitSuffix := buildUnitSuffixes(metric.Unit())
|
|
||||||
if mainUnitSuffix != "" {
|
|
||||||
metricName = metricName + "_" + mainUnitSuffix
|
|
||||||
}
|
|
||||||
if perUnitSuffix != "" {
|
|
||||||
metricName = metricName + "_" + perUnitSuffix
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append _total for Counters
|
|
||||||
if metric.Type() == pmetric.MetricTypeSum && metric.Sum().IsMonotonic() {
|
|
||||||
metricName = metricName + "_total"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append _ratio for metrics with unit "1"
|
|
||||||
// Some OTel receivers improperly use unit "1" for counters of objects
|
|
||||||
// See https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aissue+some+metric+units+don%27t+follow+otel+semantic+conventions
|
|
||||||
// Until these issues have been fixed, we're appending `_ratio` for gauges ONLY
|
|
||||||
// Theoretically, counters could be ratios as well, but it's absurd (for mathematical reasons)
|
|
||||||
if metric.Unit() == "1" && metric.Type() == pmetric.MetricTypeGauge {
|
|
||||||
metricName = metricName + "_ratio"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return metricName
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildUnitSuffixes builds the main and per unit suffixes for the specified unit
|
|
||||||
// but doesn't do any special character transformation to accommodate Prometheus naming conventions.
|
|
||||||
// Removing trailing underscores or appending suffixes is done in the caller.
|
|
||||||
func buildUnitSuffixes(unit string) (mainUnitSuffix, perUnitSuffix string) {
|
|
||||||
// Split unit at the '/' if any
|
|
||||||
unitTokens := strings.SplitN(unit, "/", 2)
|
|
||||||
|
|
||||||
if len(unitTokens) > 0 {
|
|
||||||
// Main unit
|
|
||||||
// Update if not blank and doesn't contain '{}'
|
|
||||||
mainUnitOTel := strings.TrimSpace(unitTokens[0])
|
|
||||||
if mainUnitOTel != "" && !strings.ContainsAny(mainUnitOTel, "{}") {
|
|
||||||
mainUnitSuffix = unitMapGetOrDefault(mainUnitOTel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per unit
|
|
||||||
// Update if not blank and doesn't contain '{}'
|
|
||||||
if len(unitTokens) > 1 && unitTokens[1] != "" {
|
|
||||||
perUnitOTel := strings.TrimSpace(unitTokens[1])
|
|
||||||
if perUnitOTel != "" && !strings.ContainsAny(perUnitOTel, "{}") {
|
|
||||||
perUnitSuffix = perUnitMapGetOrDefault(perUnitOTel)
|
|
||||||
}
|
|
||||||
if perUnitSuffix != "" {
|
|
||||||
perUnitSuffix = "per_" + perUnitSuffix
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mainUnitSuffix, perUnitSuffix
|
|
||||||
}
|
|
@ -1,257 +0,0 @@
|
|||||||
// Copyright 2024 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.
|
|
||||||
// Provenance-includes-location: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/95e8f8fdc2a9dc87230406c9a3cf02be4fd68bea/pkg/translator/prometheus/normalize_name_test.go
|
|
||||||
// Provenance-includes-license: Apache-2.0
|
|
||||||
// Provenance-includes-copyright: Copyright The OpenTelemetry Authors.
|
|
||||||
|
|
||||||
package prometheus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestByte(t *testing.T) {
|
|
||||||
require.Equal(t, "system_filesystem_usage_bytes", normalizeName(createGauge("system.filesystem.usage", "By"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestByteCounter(t *testing.T) {
|
|
||||||
require.Equal(t, "system_io_bytes_total", normalizeName(createCounter("system.io", "By"), ""))
|
|
||||||
require.Equal(t, "network_transmitted_bytes_total", normalizeName(createCounter("network_transmitted_bytes_total", "By"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWhiteSpaces(t *testing.T) {
|
|
||||||
require.Equal(t, "system_filesystem_usage_bytes", normalizeName(createGauge("\t system.filesystem.usage ", " By\t"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNonStandardUnit(t *testing.T) {
|
|
||||||
require.Equal(t, "system_network_dropped", normalizeName(createGauge("system.network.dropped", "{packets}"), ""))
|
|
||||||
// The normal metric name character set is allowed in non-standard units.
|
|
||||||
require.Equal(t, "system_network_dropped_nonstandard:_1", normalizeName(createGauge("system.network.dropped", "nonstandard:_1"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNonStandardUnitCounter(t *testing.T) {
|
|
||||||
require.Equal(t, "system_network_dropped_total", normalizeName(createCounter("system.network.dropped", "{packets}"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBrokenUnit(t *testing.T) {
|
|
||||||
require.Equal(t, "system_network_dropped_packets", normalizeName(createGauge("system.network.dropped", "packets"), ""))
|
|
||||||
require.Equal(t, "system_network_packets_dropped", normalizeName(createGauge("system.network.packets.dropped", "packets"), ""))
|
|
||||||
require.Equal(t, "system_network_packets", normalizeName(createGauge("system.network.packets", "packets"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBrokenUnitCounter(t *testing.T) {
|
|
||||||
require.Equal(t, "system_network_dropped_packets_total", normalizeName(createCounter("system.network.dropped", "packets"), ""))
|
|
||||||
require.Equal(t, "system_network_packets_dropped_total", normalizeName(createCounter("system.network.packets.dropped", "packets"), ""))
|
|
||||||
require.Equal(t, "system_network_packets_total", normalizeName(createCounter("system.network.packets", "packets"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRatio(t *testing.T) {
|
|
||||||
require.Equal(t, "hw_gpu_memory_utilization_ratio", normalizeName(createGauge("hw.gpu.memory.utilization", "1"), ""))
|
|
||||||
require.Equal(t, "hw_fan_speed_ratio", normalizeName(createGauge("hw.fan.speed_ratio", "1"), ""))
|
|
||||||
require.Equal(t, "objects_total", normalizeName(createCounter("objects", "1"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHertz(t *testing.T) {
|
|
||||||
require.Equal(t, "hw_cpu_speed_limit_hertz", normalizeName(createGauge("hw.cpu.speed_limit", "Hz"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPer(t *testing.T) {
|
|
||||||
require.Equal(t, "broken_metric_speed_km_per_hour", normalizeName(createGauge("broken.metric.speed", "km/h"), ""))
|
|
||||||
require.Equal(t, "astro_light_speed_limit_meters_per_second", normalizeName(createGauge("astro.light.speed_limit", "m/s"), ""))
|
|
||||||
// The normal metric name character set is allowed in non-standard units.
|
|
||||||
require.Equal(t, "system_network_dropped_non_per_standard:_1", normalizeName(createGauge("system.network.dropped", "non/standard:_1"), ""))
|
|
||||||
|
|
||||||
t.Run("invalid per unit", func(t *testing.T) {
|
|
||||||
require.Equal(t, "broken_metric_speed_km", normalizeName(createGauge("broken.metric.speed", "km/°"), ""))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPercent(t *testing.T) {
|
|
||||||
require.Equal(t, "broken_metric_success_ratio_percent", normalizeName(createGauge("broken.metric.success_ratio", "%"), ""))
|
|
||||||
require.Equal(t, "broken_metric_success_percent", normalizeName(createGauge("broken.metric.success_percent", "%"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEmpty(t *testing.T) {
|
|
||||||
require.Equal(t, "test_metric_no_unit", normalizeName(createGauge("test.metric.no_unit", ""), ""))
|
|
||||||
require.Equal(t, "test_metric_spaces", normalizeName(createGauge("test.metric.spaces", " \t "), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOTelReceivers(t *testing.T) {
|
|
||||||
require.Equal(t, "active_directory_ds_replication_network_io_bytes_total", normalizeName(createCounter("active_directory.ds.replication.network.io", "By"), ""))
|
|
||||||
require.Equal(t, "active_directory_ds_replication_sync_object_pending_total", normalizeName(createCounter("active_directory.ds.replication.sync.object.pending", "{objects}"), ""))
|
|
||||||
require.Equal(t, "active_directory_ds_replication_object_rate_per_second", normalizeName(createGauge("active_directory.ds.replication.object.rate", "{objects}/s"), ""))
|
|
||||||
require.Equal(t, "active_directory_ds_name_cache_hit_rate_percent", normalizeName(createGauge("active_directory.ds.name_cache.hit_rate", "%"), ""))
|
|
||||||
require.Equal(t, "active_directory_ds_ldap_bind_last_successful_time_milliseconds", normalizeName(createGauge("active_directory.ds.ldap.bind.last_successful.time", "ms"), ""))
|
|
||||||
require.Equal(t, "apache_current_connections", normalizeName(createGauge("apache.current_connections", "connections"), ""))
|
|
||||||
require.Equal(t, "apache_workers_connections", normalizeName(createGauge("apache.workers", "connections"), ""))
|
|
||||||
require.Equal(t, "apache_requests_total", normalizeName(createCounter("apache.requests", "1"), ""))
|
|
||||||
require.Equal(t, "bigip_virtual_server_request_count_total", normalizeName(createCounter("bigip.virtual_server.request.count", "{requests}"), ""))
|
|
||||||
require.Equal(t, "system_cpu_utilization_ratio", normalizeName(createGauge("system.cpu.utilization", "1"), ""))
|
|
||||||
require.Equal(t, "system_disk_operation_time_seconds_total", normalizeName(createCounter("system.disk.operation_time", "s"), ""))
|
|
||||||
require.Equal(t, "system_cpu_load_average_15m_ratio", normalizeName(createGauge("system.cpu.load_average.15m", "1"), ""))
|
|
||||||
require.Equal(t, "memcached_operation_hit_ratio_percent", normalizeName(createGauge("memcached.operation_hit_ratio", "%"), ""))
|
|
||||||
require.Equal(t, "mongodbatlas_process_asserts_per_second", normalizeName(createGauge("mongodbatlas.process.asserts", "{assertions}/s"), ""))
|
|
||||||
require.Equal(t, "mongodbatlas_process_journaling_data_files_mebibytes", normalizeName(createGauge("mongodbatlas.process.journaling.data_files", "MiBy"), ""))
|
|
||||||
require.Equal(t, "mongodbatlas_process_network_io_bytes_per_second", normalizeName(createGauge("mongodbatlas.process.network.io", "By/s"), ""))
|
|
||||||
require.Equal(t, "mongodbatlas_process_oplog_rate_gibibytes_per_hour", normalizeName(createGauge("mongodbatlas.process.oplog.rate", "GiBy/h"), ""))
|
|
||||||
require.Equal(t, "mongodbatlas_process_db_query_targeting_scanned_per_returned", normalizeName(createGauge("mongodbatlas.process.db.query_targeting.scanned_per_returned", "{scanned}/{returned}"), ""))
|
|
||||||
require.Equal(t, "nginx_requests", normalizeName(createGauge("nginx.requests", "requests"), ""))
|
|
||||||
require.Equal(t, "nginx_connections_accepted", normalizeName(createGauge("nginx.connections_accepted", "connections"), ""))
|
|
||||||
require.Equal(t, "nsxt_node_memory_usage_kilobytes", normalizeName(createGauge("nsxt.node.memory.usage", "KBy"), ""))
|
|
||||||
require.Equal(t, "redis_latest_fork_microseconds", normalizeName(createGauge("redis.latest_fork", "us"), ""))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNamespace(t *testing.T) {
|
|
||||||
require.Equal(t, "space_test", normalizeName(createGauge("test", ""), "space"))
|
|
||||||
require.Equal(t, "space_test", normalizeName(createGauge("#test", ""), "space"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCleanUpUnit(t *testing.T) {
|
|
||||||
require.Equal(t, "", cleanUpUnit(""))
|
|
||||||
require.Equal(t, "a_b", cleanUpUnit("a b"))
|
|
||||||
require.Equal(t, "hello_world", cleanUpUnit("hello, world"))
|
|
||||||
require.Equal(t, "hello_you_2", cleanUpUnit("hello you 2"))
|
|
||||||
require.Equal(t, "1000", cleanUpUnit("$1000"))
|
|
||||||
require.Equal(t, "", cleanUpUnit("*+$^=)"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUnitMapGetOrDefault(t *testing.T) {
|
|
||||||
require.Equal(t, "", unitMapGetOrDefault(""))
|
|
||||||
require.Equal(t, "seconds", unitMapGetOrDefault("s"))
|
|
||||||
require.Equal(t, "invalid", unitMapGetOrDefault("invalid"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPerUnitMapGetOrDefault(t *testing.T) {
|
|
||||||
require.Equal(t, "", perUnitMapGetOrDefault(""))
|
|
||||||
require.Equal(t, "second", perUnitMapGetOrDefault("s"))
|
|
||||||
require.Equal(t, "invalid", perUnitMapGetOrDefault("invalid"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildUnitSuffixes(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
unit string
|
|
||||||
expectedMain string
|
|
||||||
expectedPer string
|
|
||||||
}{
|
|
||||||
{"", "", ""},
|
|
||||||
{"s", "seconds", ""},
|
|
||||||
{"By/s", "bytes", "per_second"},
|
|
||||||
{"requests/m", "requests", "per_minute"},
|
|
||||||
{"{invalid}/second", "", "per_second"},
|
|
||||||
{"bytes/{invalid}", "bytes", ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
mainUnitSuffix, perUnitSuffix := buildUnitSuffixes(test.unit)
|
|
||||||
require.Equal(t, test.expectedMain, mainUnitSuffix)
|
|
||||||
require.Equal(t, test.expectedPer, perUnitSuffix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAddUnitTokens(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
nameTokens []string
|
|
||||||
mainUnitSuffix string
|
|
||||||
perUnitSuffix string
|
|
||||||
expected []string
|
|
||||||
}{
|
|
||||||
{[]string{}, "", "", []string{}},
|
|
||||||
{[]string{"token1"}, "main", "", []string{"token1", "main"}},
|
|
||||||
{[]string{"token1"}, "", "per", []string{"token1", "per"}},
|
|
||||||
{[]string{"token1"}, "main", "per", []string{"token1", "main", "per"}},
|
|
||||||
{[]string{"token1", "per"}, "main", "per", []string{"token1", "per", "main"}},
|
|
||||||
{[]string{"token1", "main"}, "main", "per", []string{"token1", "main", "per"}},
|
|
||||||
{[]string{"token1"}, "main_", "per", []string{"token1", "main", "per"}},
|
|
||||||
{[]string{"token1"}, "main_unit", "per_seconds_", []string{"token1", "main_unit", "per_seconds"}}, // trailing underscores are removed
|
|
||||||
{[]string{"token1"}, "main_unit", "per_", []string{"token1", "main_unit"}}, // 'per_' is removed entirely
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
result := addUnitTokens(test.nameTokens, test.mainUnitSuffix, test.perUnitSuffix)
|
|
||||||
require.Equal(t, test.expected, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRemoveItem(t *testing.T) {
|
|
||||||
require.Equal(t, []string{}, removeItem([]string{}, "test"))
|
|
||||||
require.Equal(t, []string{}, removeItem([]string{}, ""))
|
|
||||||
require.Equal(t, []string{"a", "b", "c"}, removeItem([]string{"a", "b", "c"}, "d"))
|
|
||||||
require.Equal(t, []string{"a", "b", "c"}, removeItem([]string{"a", "b", "c"}, ""))
|
|
||||||
require.Equal(t, []string{"a", "b"}, removeItem([]string{"a", "b", "c"}, "c"))
|
|
||||||
require.Equal(t, []string{"a", "c"}, removeItem([]string{"a", "b", "c"}, "b"))
|
|
||||||
require.Equal(t, []string{"b", "c"}, removeItem([]string{"a", "b", "c"}, "a"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildCompliantMetricNameWithSuffixes(t *testing.T) {
|
|
||||||
require.Equal(t, "system_io_bytes_total", BuildCompliantMetricName(createCounter("system.io", "By"), "", true))
|
|
||||||
require.Equal(t, "system_network_io_bytes_total", BuildCompliantMetricName(createCounter("network.io", "By"), "system", true))
|
|
||||||
require.Equal(t, "_3_14_digits", BuildCompliantMetricName(createGauge("3.14 digits", ""), "", true))
|
|
||||||
require.Equal(t, "envoy_rule_engine_zlib_buf_error", BuildCompliantMetricName(createGauge("envoy__rule_engine_zlib_buf_error", ""), "", true))
|
|
||||||
require.Equal(t, ":foo::bar", BuildCompliantMetricName(createGauge(":foo::bar", ""), "", true))
|
|
||||||
require.Equal(t, ":foo::bar_total", BuildCompliantMetricName(createCounter(":foo::bar", ""), "", true))
|
|
||||||
// Gauges with unit 1 are considered ratios.
|
|
||||||
require.Equal(t, "foo_bar_ratio", BuildCompliantMetricName(createGauge("foo.bar", "1"), "", true))
|
|
||||||
// Slashes in units are converted.
|
|
||||||
require.Equal(t, "system_io_foo_per_bar_total", BuildCompliantMetricName(createCounter("system.io", "foo/bar"), "", true))
|
|
||||||
require.Equal(t, "metric_with_foreign_characters_total", BuildCompliantMetricName(createCounter("metric_with_字符_foreign_characters", ""), "", true))
|
|
||||||
// Removes non aplhanumerical characters from units, but leaves colons.
|
|
||||||
require.Equal(t, "temperature_:C", BuildCompliantMetricName(createGauge("temperature", "%*()°:C"), "", true))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildCompliantMetricNameWithoutSuffixes(t *testing.T) {
|
|
||||||
require.Equal(t, "system_io", BuildCompliantMetricName(createCounter("system.io", "By"), "", false))
|
|
||||||
require.Equal(t, "system_network_io", BuildCompliantMetricName(createCounter("network.io", "By"), "system", false))
|
|
||||||
require.Equal(t, "system_network_I_O", BuildCompliantMetricName(createCounter("network (I/O)", "By"), "system", false))
|
|
||||||
require.Equal(t, "_3_14_digits", BuildCompliantMetricName(createGauge("3.14 digits", "By"), "", false))
|
|
||||||
require.Equal(t, "envoy__rule_engine_zlib_buf_error", BuildCompliantMetricName(createGauge("envoy__rule_engine_zlib_buf_error", ""), "", false))
|
|
||||||
require.Equal(t, ":foo::bar", BuildCompliantMetricName(createGauge(":foo::bar", ""), "", false))
|
|
||||||
require.Equal(t, ":foo::bar", BuildCompliantMetricName(createCounter(":foo::bar", ""), "", false))
|
|
||||||
require.Equal(t, "foo_bar", BuildCompliantMetricName(createGauge("foo.bar", "1"), "", false))
|
|
||||||
require.Equal(t, "system_io", BuildCompliantMetricName(createCounter("system.io", "foo/bar"), "", false))
|
|
||||||
require.Equal(t, "metric_with___foreign_characters", BuildCompliantMetricName(createCounter("metric_with_字符_foreign_characters", ""), "", false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildMetricNameWithSuffixes(t *testing.T) {
|
|
||||||
require.Equal(t, "system.io_bytes_total", BuildMetricName(createCounter("system.io", "By"), "", true))
|
|
||||||
require.Equal(t, "system_network.io_bytes_total", BuildMetricName(createCounter("network.io", "By"), "system", true))
|
|
||||||
require.Equal(t, "3.14 digits", BuildMetricName(createGauge("3.14 digits", ""), "", true))
|
|
||||||
require.Equal(t, "envoy__rule_engine_zlib_buf_error", BuildMetricName(createGauge("envoy__rule_engine_zlib_buf_error", ""), "", true))
|
|
||||||
require.Equal(t, ":foo::bar", BuildMetricName(createGauge(":foo::bar", ""), "", true))
|
|
||||||
require.Equal(t, ":foo::bar_total", BuildMetricName(createCounter(":foo::bar", ""), "", true))
|
|
||||||
// Gauges with unit 1 are considered ratios.
|
|
||||||
require.Equal(t, "foo.bar_ratio", BuildMetricName(createGauge("foo.bar", "1"), "", true))
|
|
||||||
// Slashes in units are converted.
|
|
||||||
require.Equal(t, "system.io_foo_per_bar_total", BuildMetricName(createCounter("system.io", "foo/bar"), "", true))
|
|
||||||
require.Equal(t, "metric_with_字符_foreign_characters_total", BuildMetricName(createCounter("metric_with_字符_foreign_characters", ""), "", true))
|
|
||||||
require.Equal(t, "temperature_%*()°C", BuildMetricName(createGauge("temperature", "%*()°C"), "", true)) // Keeps the all characters in unit
|
|
||||||
// Tests below show weird interactions that users can have with the metric names.
|
|
||||||
// With BuildMetricName we don't check if units/type suffixes are already present in the metric name, we always add them.
|
|
||||||
require.Equal(t, "system_io_seconds_seconds", BuildMetricName(createGauge("system_io_seconds", "s"), "", true))
|
|
||||||
require.Equal(t, "system_io_total_total", BuildMetricName(createCounter("system_io_total", ""), "", true))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildMetricNameWithoutSuffixes(t *testing.T) {
|
|
||||||
require.Equal(t, "system.io", BuildMetricName(createCounter("system.io", "By"), "", false))
|
|
||||||
require.Equal(t, "system_network.io", BuildMetricName(createCounter("network.io", "By"), "system", false))
|
|
||||||
require.Equal(t, "3.14 digits", BuildMetricName(createGauge("3.14 digits", ""), "", false))
|
|
||||||
require.Equal(t, "envoy__rule_engine_zlib_buf_error", BuildMetricName(createGauge("envoy__rule_engine_zlib_buf_error", ""), "", false))
|
|
||||||
require.Equal(t, ":foo::bar", BuildMetricName(createGauge(":foo::bar", ""), "", false))
|
|
||||||
require.Equal(t, ":foo::bar", BuildMetricName(createCounter(":foo::bar", ""), "", false))
|
|
||||||
// Gauges with unit 1 are considered ratios.
|
|
||||||
require.Equal(t, "foo.bar", BuildMetricName(createGauge("foo.bar", "1"), "", false))
|
|
||||||
require.Equal(t, "metric_with_字符_foreign_characters", BuildMetricName(createCounter("metric_with_字符_foreign_characters", ""), "", false))
|
|
||||||
require.Equal(t, "system_io_seconds", BuildMetricName(createGauge("system_io_seconds", "s"), "", false))
|
|
||||||
require.Equal(t, "system_io_total", BuildMetricName(createCounter("system_io_total", ""), "", false))
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
// Copyright 2024 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.
|
|
||||||
// Provenance-includes-location: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/95e8f8fdc2a9dc87230406c9a3cf02be4fd68bea/pkg/translator/prometheus/normalize_label.go
|
|
||||||
// Provenance-includes-license: Apache-2.0
|
|
||||||
// Provenance-includes-copyright: Copyright The OpenTelemetry Authors.
|
|
||||||
|
|
||||||
package prometheus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/prometheus/prometheus/util/strutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Normalizes the specified label to follow Prometheus label names standard.
|
|
||||||
//
|
|
||||||
// See rules at https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels.
|
|
||||||
//
|
|
||||||
// Labels that start with non-letter rune will be prefixed with "key_".
|
|
||||||
// An exception is made for double-underscores which are allowed.
|
|
||||||
func NormalizeLabel(label string) string {
|
|
||||||
// Trivial case.
|
|
||||||
if len(label) == 0 {
|
|
||||||
return label
|
|
||||||
}
|
|
||||||
|
|
||||||
label = strutil.SanitizeLabelName(label)
|
|
||||||
|
|
||||||
// If label starts with a number, prepend with "key_".
|
|
||||||
if unicode.IsDigit(rune(label[0])) {
|
|
||||||
label = "key_" + label
|
|
||||||
} else if strings.HasPrefix(label, "_") && !strings.HasPrefix(label, "__") {
|
|
||||||
label = "key" + label
|
|
||||||
}
|
|
||||||
|
|
||||||
return label
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
// Copyright 2024 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 prometheus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNormalizeLabel(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
label string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{"", ""},
|
|
||||||
{"label:with:colons", "label_with_colons"},
|
|
||||||
{"LabelWithCapitalLetters", "LabelWithCapitalLetters"},
|
|
||||||
{"label!with&special$chars)", "label_with_special_chars_"},
|
|
||||||
{"label_with_foreign_characters_字符", "label_with_foreign_characters___"},
|
|
||||||
{"label.with.dots", "label_with_dots"},
|
|
||||||
{"123label", "key_123label"},
|
|
||||||
{"_label_starting_with_underscore", "key_label_starting_with_underscore"},
|
|
||||||
{"__label_starting_with_2underscores", "__label_starting_with_2underscores"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
t.Run(fmt.Sprintf("test_%d", i), func(t *testing.T) {
|
|
||||||
result := NormalizeLabel(test.label)
|
|
||||||
require.Equal(t, test.expected, result)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
// Copyright 2024 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.
|
|
||||||
// Provenance-includes-location: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/95e8f8fdc2a9dc87230406c9a3cf02be4fd68bea/pkg/translator/prometheus/testutils_test.go
|
|
||||||
// Provenance-includes-license: Apache-2.0
|
|
||||||
// Provenance-includes-copyright: Copyright The OpenTelemetry Authors.
|
|
||||||
|
|
||||||
package prometheus
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go.opentelemetry.io/collector/pdata/pmetric"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ilm pmetric.ScopeMetrics
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
|
|
||||||
metrics := pmetric.NewMetrics()
|
|
||||||
resourceMetrics := metrics.ResourceMetrics().AppendEmpty()
|
|
||||||
ilm = resourceMetrics.ScopeMetrics().AppendEmpty()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a new Metric of type "Gauge" with specified name and unit
|
|
||||||
func createGauge(name string, unit string) pmetric.Metric {
|
|
||||||
gauge := ilm.Metrics().AppendEmpty()
|
|
||||||
gauge.SetName(name)
|
|
||||||
gauge.SetUnit(unit)
|
|
||||||
gauge.SetEmptyGauge()
|
|
||||||
return gauge
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a new Metric of type Monotonic Sum with specified name and unit
|
|
||||||
func createCounter(name string, unit string) pmetric.Metric {
|
|
||||||
counter := ilm.Metrics().AppendEmpty()
|
|
||||||
counter.SetEmptySum().SetIsMonotonic(true)
|
|
||||||
counter.SetName(name)
|
|
||||||
counter.SetUnit(unit)
|
|
||||||
return counter
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
// Copyright 2024 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.
|
|
||||||
// Provenance-includes-location: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/95e8f8fdc2a9dc87230406c9a3cf02be4fd68bea/pkg/translator/prometheus/unit_to_ucum.go
|
|
||||||
// Provenance-includes-license: Apache-2.0
|
|
||||||
// Provenance-includes-copyright: Copyright The OpenTelemetry Authors.
|
|
||||||
|
|
||||||
package prometheus
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
var wordToUCUM = map[string]string{
|
|
||||||
// Time
|
|
||||||
"days": "d",
|
|
||||||
"hours": "h",
|
|
||||||
"minutes": "min",
|
|
||||||
"seconds": "s",
|
|
||||||
"milliseconds": "ms",
|
|
||||||
"microseconds": "us",
|
|
||||||
"nanoseconds": "ns",
|
|
||||||
|
|
||||||
// Bytes
|
|
||||||
"bytes": "By",
|
|
||||||
"kibibytes": "KiBy",
|
|
||||||
"mebibytes": "MiBy",
|
|
||||||
"gibibytes": "GiBy",
|
|
||||||
"tibibytes": "TiBy",
|
|
||||||
"kilobytes": "KBy",
|
|
||||||
"megabytes": "MBy",
|
|
||||||
"gigabytes": "GBy",
|
|
||||||
"terabytes": "TBy",
|
|
||||||
|
|
||||||
// SI
|
|
||||||
"meters": "m",
|
|
||||||
"volts": "V",
|
|
||||||
"amperes": "A",
|
|
||||||
"joules": "J",
|
|
||||||
"watts": "W",
|
|
||||||
"grams": "g",
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
"celsius": "Cel",
|
|
||||||
"hertz": "Hz",
|
|
||||||
"ratio": "1",
|
|
||||||
"percent": "%",
|
|
||||||
}
|
|
||||||
|
|
||||||
// The map that translates the "per" unit
|
|
||||||
// Example: per_second (singular) => /s
|
|
||||||
var perWordToUCUM = map[string]string{
|
|
||||||
"second": "s",
|
|
||||||
"minute": "m",
|
|
||||||
"hour": "h",
|
|
||||||
"day": "d",
|
|
||||||
"week": "w",
|
|
||||||
"month": "mo",
|
|
||||||
"year": "y",
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnitWordToUCUM converts english unit words to UCUM units:
|
|
||||||
// https://ucum.org/ucum#section-Alphabetic-Index-By-Symbol
|
|
||||||
// It also handles rates, such as meters_per_second, by translating the first
|
|
||||||
// word to UCUM, and the "per" word to UCUM. It joins them with a "/" between.
|
|
||||||
func UnitWordToUCUM(unit string) string {
|
|
||||||
unitTokens := strings.SplitN(unit, "_per_", 2)
|
|
||||||
if len(unitTokens) == 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
ucumUnit := wordToUCUMOrDefault(unitTokens[0])
|
|
||||||
if len(unitTokens) > 1 && unitTokens[1] != "" {
|
|
||||||
ucumUnit += "/" + perWordToUCUMOrDefault(unitTokens[1])
|
|
||||||
}
|
|
||||||
return ucumUnit
|
|
||||||
}
|
|
||||||
|
|
||||||
// wordToUCUMOrDefault retrieves the Prometheus "basic" unit corresponding to
|
|
||||||
// the specified "basic" unit. Returns the specified unit if not found in
|
|
||||||
// wordToUCUM.
|
|
||||||
func wordToUCUMOrDefault(unit string) string {
|
|
||||||
if promUnit, ok := wordToUCUM[unit]; ok {
|
|
||||||
return promUnit
|
|
||||||
}
|
|
||||||
return unit
|
|
||||||
}
|
|
||||||
|
|
||||||
// perWordToUCUMOrDefault retrieve the Prometheus "per" unit corresponding to
|
|
||||||
// the specified "per" unit. Returns the specified unit if not found in perWordToUCUM.
|
|
||||||
func perWordToUCUMOrDefault(perUnit string) string {
|
|
||||||
if promPerUnit, ok := perWordToUCUM[perUnit]; ok {
|
|
||||||
return promPerUnit
|
|
||||||
}
|
|
||||||
return perUnit
|
|
||||||
}
|
|
@ -29,6 +29,7 @@ import (
|
|||||||
|
|
||||||
"github.com/cespare/xxhash/v2"
|
"github.com/cespare/xxhash/v2"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
"github.com/prometheus/otlptranslator"
|
||||||
"go.opentelemetry.io/collector/pdata/pcommon"
|
"go.opentelemetry.io/collector/pdata/pcommon"
|
||||||
"go.opentelemetry.io/collector/pdata/pmetric"
|
"go.opentelemetry.io/collector/pdata/pmetric"
|
||||||
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
|
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
|
||||||
@ -36,8 +37,6 @@ import (
|
|||||||
"github.com/prometheus/prometheus/model/timestamp"
|
"github.com/prometheus/prometheus/model/timestamp"
|
||||||
"github.com/prometheus/prometheus/model/value"
|
"github.com/prometheus/prometheus/model/value"
|
||||||
"github.com/prometheus/prometheus/prompb"
|
"github.com/prometheus/prometheus/prompb"
|
||||||
|
|
||||||
prometheustranslator "github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -159,7 +158,7 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, setting
|
|||||||
for _, label := range labels {
|
for _, label := range labels {
|
||||||
finalKey := label.Name
|
finalKey := label.Name
|
||||||
if !settings.AllowUTF8 {
|
if !settings.AllowUTF8 {
|
||||||
finalKey = prometheustranslator.NormalizeLabel(finalKey)
|
finalKey = otlptranslator.NormalizeLabel(finalKey)
|
||||||
}
|
}
|
||||||
if existingValue, alreadyExists := l[finalKey]; alreadyExists {
|
if existingValue, alreadyExists := l[finalKey]; alreadyExists {
|
||||||
l[finalKey] = existingValue + ";" + label.Value
|
l[finalKey] = existingValue + ";" + label.Value
|
||||||
@ -171,7 +170,7 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, setting
|
|||||||
for _, lbl := range promotedAttrs {
|
for _, lbl := range promotedAttrs {
|
||||||
normalized := lbl.Name
|
normalized := lbl.Name
|
||||||
if !settings.AllowUTF8 {
|
if !settings.AllowUTF8 {
|
||||||
normalized = prometheustranslator.NormalizeLabel(normalized)
|
normalized = otlptranslator.NormalizeLabel(normalized)
|
||||||
}
|
}
|
||||||
if _, exists := l[normalized]; !exists {
|
if _, exists := l[normalized]; !exists {
|
||||||
l[normalized] = lbl.Value
|
l[normalized] = lbl.Value
|
||||||
@ -211,7 +210,7 @@ func createAttributes(resource pcommon.Resource, attributes pcommon.Map, setting
|
|||||||
}
|
}
|
||||||
// internal labels should be maintained
|
// internal labels should be maintained
|
||||||
if !settings.AllowUTF8 && !(len(name) > 4 && name[:2] == "__" && name[len(name)-2:] == "__") {
|
if !settings.AllowUTF8 && !(len(name) > 4 && name[:2] == "__" && name[len(name)-2:] == "__") {
|
||||||
name = prometheustranslator.NormalizeLabel(name)
|
name = otlptranslator.NormalizeLabel(name)
|
||||||
}
|
}
|
||||||
l[name] = extras[i+1]
|
l[name] = extras[i+1]
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
"github.com/prometheus/otlptranslator"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"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"
|
||||||
|
|
||||||
"github.com/prometheus/prometheus/prompb"
|
"github.com/prometheus/prometheus/prompb"
|
||||||
|
|
||||||
prometheustranslator "github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type expectedBucketLayout struct {
|
type expectedBucketLayout struct {
|
||||||
@ -762,7 +761,7 @@ func TestPrometheusConverter_addExponentialHistogramDataPoints(t *testing.T) {
|
|||||||
Settings{
|
Settings{
|
||||||
ExportCreatedMetric: true,
|
ExportCreatedMetric: true,
|
||||||
},
|
},
|
||||||
prometheustranslator.BuildCompliantMetricName(metric, "", true),
|
otlptranslator.BuildCompliantMetricName(metric, "", true),
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Empty(t, annots)
|
require.Empty(t, annots)
|
||||||
|
@ -22,12 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/prometheus/otlptranslator"
|
||||||
"go.opentelemetry.io/collector/pdata/pcommon"
|
"go.opentelemetry.io/collector/pdata/pcommon"
|
||||||
"go.opentelemetry.io/collector/pdata/pmetric"
|
"go.opentelemetry.io/collector/pdata/pmetric"
|
||||||
"go.uber.org/multierr"
|
"go.uber.org/multierr"
|
||||||
|
|
||||||
"github.com/prometheus/prometheus/prompb"
|
"github.com/prometheus/prometheus/prompb"
|
||||||
prometheustranslator "github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus"
|
|
||||||
"github.com/prometheus/prometheus/util/annotations"
|
"github.com/prometheus/prometheus/util/annotations"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -98,9 +98,9 @@ func (c *PrometheusConverter) FromMetrics(ctx context.Context, md pmetric.Metric
|
|||||||
|
|
||||||
var promName string
|
var promName string
|
||||||
if settings.AllowUTF8 {
|
if settings.AllowUTF8 {
|
||||||
promName = prometheustranslator.BuildMetricName(metric, settings.Namespace, settings.AddMetricSuffixes)
|
promName = otlptranslator.BuildMetricName(metric, settings.Namespace, settings.AddMetricSuffixes)
|
||||||
} else {
|
} else {
|
||||||
promName = prometheustranslator.BuildCompliantMetricName(metric, settings.Namespace, settings.AddMetricSuffixes)
|
promName = otlptranslator.BuildCompliantMetricName(metric, settings.Namespace, settings.AddMetricSuffixes)
|
||||||
}
|
}
|
||||||
c.metadata = append(c.metadata, prompb.MetricMetadata{
|
c.metadata = append(c.metadata, prompb.MetricMetadata{
|
||||||
Type: otelMetricTypeToPromMetricType(metric),
|
Type: otelMetricTypeToPromMetricType(metric),
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"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"
|
||||||
@ -30,7 +31,6 @@ import (
|
|||||||
|
|
||||||
"github.com/prometheus/prometheus/model/labels"
|
"github.com/prometheus/prometheus/model/labels"
|
||||||
"github.com/prometheus/prometheus/prompb"
|
"github.com/prometheus/prometheus/prompb"
|
||||||
prometheustranslator "github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFromMetrics(t *testing.T) {
|
func TestFromMetrics(t *testing.T) {
|
||||||
@ -46,7 +46,7 @@ func TestFromMetrics(t *testing.T) {
|
|||||||
metricSlice := scopeMetricsSlice.At(j).Metrics()
|
metricSlice := scopeMetricsSlice.At(j).Metrics()
|
||||||
for k := 0; k < metricSlice.Len(); k++ {
|
for k := 0; k < metricSlice.Len(); k++ {
|
||||||
metric := metricSlice.At(k)
|
metric := metricSlice.At(k)
|
||||||
promName := prometheustranslator.BuildCompliantMetricName(metric, "", false)
|
promName := otlptranslator.BuildCompliantMetricName(metric, "", false)
|
||||||
expMetadata = append(expMetadata, prompb.MetricMetadata{
|
expMetadata = append(expMetadata, prompb.MetricMetadata{
|
||||||
Type: otelMetricTypeToPromMetricType(metric),
|
Type: otelMetricTypeToPromMetricType(metric),
|
||||||
MetricFamilyName: promName,
|
MetricFamilyName: promName,
|
||||||
|
Loading…
Reference in New Issue
Block a user