diff options
Diffstat (limited to 'vendor/go.opentelemetry.io')
3 files changed, 128 insertions, 128 deletions
diff --git a/vendor/go.opentelemetry.io/otel/exporters/prometheus/LICENSE b/vendor/go.opentelemetry.io/otel/exporters/prometheus/LICENSE index 261eeb9e9..f1aee0f11 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/prometheus/LICENSE +++ b/vendor/go.opentelemetry.io/otel/exporters/prometheus/LICENSE @@ -199,3 +199,33 @@ 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. + +-------------------------------------------------------------------------------- + +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file diff --git a/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go b/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go index 521838840..4757b793d 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go +++ b/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go @@ -4,11 +4,9 @@ package prometheus // import "go.opentelemetry.io/otel/exporters/prometheus" import ( - "strings" "sync" "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/common/model" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/internal/global" @@ -139,17 +137,6 @@ func WithoutScopeInfo() Option { // have special behavior based on their name. func WithNamespace(ns string) Option { return optionFunc(func(cfg config) config { - if model.NameValidationScheme != model.UTF8Validation { // nolint:staticcheck // We need this check to keep supporting the legacy scheme. - logDeprecatedLegacyScheme() - // Only sanitize if prometheus does not support UTF-8. - ns = model.EscapeName(ns, model.NameEscapingScheme) - } - if !strings.HasSuffix(ns, "_") { - // namespace and metric names should be separated with an underscore, - // adds a trailing underscore if there is not one already. - ns = ns + "_" - } - cfg.namespace = ns return cfg }) diff --git a/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go b/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go index 7b44c12c5..9f3e5414a 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go +++ b/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go @@ -16,6 +16,7 @@ import ( "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/model" + "github.com/prometheus/otlptranslator" "google.golang.org/protobuf/proto" "go.opentelemetry.io/otel" @@ -27,16 +28,12 @@ import ( ) const ( - targetInfoMetricName = "target_info" targetInfoDescription = "Target metadata" scopeLabelPrefix = "otel_scope_" scopeNameLabel = scopeLabelPrefix + "name" scopeVersionLabel = scopeLabelPrefix + "version" scopeSchemaLabel = scopeLabelPrefix + "schema_url" - - traceIDExemplarKey = "trace_id" - spanIDExemplarKey = "span_id" ) var metricsPool = sync.Pool{ @@ -93,12 +90,11 @@ type collector struct { targetInfo prometheus.Metric metricFamilies map[string]*dto.MetricFamily resourceKeyVals keyVals + metricNamer otlptranslator.MetricNamer + labelNamer otlptranslator.LabelNamer + unitNamer otlptranslator.UnitNamer } -// prometheus counters MUST have a _total suffix by default: -// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/compatibility/prometheus_and_openmetrics.md -const counterSuffix = "total" - // New returns a Prometheus Exporter. func New(opts ...Option) (*Exporter, error) { cfg := newConfig(opts...) @@ -108,6 +104,12 @@ func New(opts ...Option) (*Exporter, error) { // TODO (#3244): Enable some way to configure the reader, but not change temporality. reader := metric.NewManualReader(cfg.readerOpts...) + utf8Allowed := model.NameValidationScheme == model.UTF8Validation // nolint:staticcheck // We need this check to keep supporting the legacy scheme. + if !utf8Allowed { + // Only sanitize if prometheus does not support UTF-8. + logDeprecatedLegacyScheme() + } + labelNamer := otlptranslator.LabelNamer{UTF8Allowed: utf8Allowed} collector := &collector{ reader: reader, disableTargetInfo: cfg.disableTargetInfo, @@ -115,8 +117,18 @@ func New(opts ...Option) (*Exporter, error) { withoutCounterSuffixes: cfg.withoutCounterSuffixes, disableScopeInfo: cfg.disableScopeInfo, metricFamilies: make(map[string]*dto.MetricFamily), - namespace: cfg.namespace, + namespace: labelNamer.Build(cfg.namespace), resourceAttributesFilter: cfg.resourceAttributesFilter, + metricNamer: otlptranslator.MetricNamer{ + Namespace: cfg.namespace, + // We decide whether to pass type and unit to the netricNamer based + // on whether units or counter suffixes are enabled, and keep this + // always enabled. + WithMetricSuffixes: true, + UTF8Allowed: utf8Allowed, + }, + unitNamer: otlptranslator.UnitNamer{UTF8Allowed: utf8Allowed}, + labelNamer: labelNamer, } if err := cfg.registerer.Register(collector); err != nil { @@ -164,7 +176,11 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { defer c.mu.Unlock() if c.targetInfo == nil && !c.disableTargetInfo { - targetInfo, err := createInfoMetric(targetInfoMetricName, targetInfoDescription, metrics.Resource) + targetInfo, err := c.createInfoMetric( + otlptranslator.TargetInfoMetricName, + targetInfoDescription, + metrics.Resource, + ) if err != nil { // If the target info metric is invalid, disable sending it. c.disableTargetInfo = true @@ -195,7 +211,7 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { kv.keys = append(kv.keys, scopeNameLabel, scopeVersionLabel, scopeSchemaLabel) kv.vals = append(kv.vals, scopeMetrics.Scope.Name, scopeMetrics.Scope.Version, scopeMetrics.Scope.SchemaURL) - attrKeys, attrVals := getAttrs(scopeMetrics.Scope.Attributes) + attrKeys, attrVals := getAttrs(scopeMetrics.Scope.Attributes, c.labelNamer) for i := range attrKeys { attrKeys[i] = scopeLabelPrefix + attrKeys[i] } @@ -211,7 +227,7 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { if typ == nil { continue } - name := c.getName(m, typ) + name := c.getName(m) drop, help := c.validateMetrics(name, m.Description, typ) if drop { @@ -224,21 +240,21 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) { switch v := m.Data.(type) { case metricdata.Histogram[int64]: - addHistogramMetric(ch, v, m, name, kv) + addHistogramMetric(ch, v, m, name, kv, c.labelNamer) case metricdata.Histogram[float64]: - addHistogramMetric(ch, v, m, name, kv) + addHistogramMetric(ch, v, m, name, kv, c.labelNamer) case metricdata.ExponentialHistogram[int64]: - addExponentialHistogramMetric(ch, v, m, name, kv) + addExponentialHistogramMetric(ch, v, m, name, kv, c.labelNamer) case metricdata.ExponentialHistogram[float64]: - addExponentialHistogramMetric(ch, v, m, name, kv) + addExponentialHistogramMetric(ch, v, m, name, kv, c.labelNamer) case metricdata.Sum[int64]: - addSumMetric(ch, v, m, name, kv) + addSumMetric(ch, v, m, name, kv, c.labelNamer) case metricdata.Sum[float64]: - addSumMetric(ch, v, m, name, kv) + addSumMetric(ch, v, m, name, kv, c.labelNamer) case metricdata.Gauge[int64]: - addGaugeMetric(ch, v, m, name, kv) + addGaugeMetric(ch, v, m, name, kv, c.labelNamer) case metricdata.Gauge[float64]: - addGaugeMetric(ch, v, m, name, kv) + addGaugeMetric(ch, v, m, name, kv, c.labelNamer) } } } @@ -303,9 +319,10 @@ func addExponentialHistogramMetric[N int64 | float64]( m metricdata.Metrics, name string, kv keyVals, + labelNamer otlptranslator.LabelNamer, ) { for _, dp := range histogram.DataPoints { - keys, values := getAttrs(dp.Attributes) + keys, values := getAttrs(dp.Attributes, labelNamer) keys = append(keys, kv.keys...) values = append(values, kv.vals...) @@ -377,9 +394,10 @@ func addHistogramMetric[N int64 | float64]( m metricdata.Metrics, name string, kv keyVals, + labelNamer otlptranslator.LabelNamer, ) { for _, dp := range histogram.DataPoints { - keys, values := getAttrs(dp.Attributes) + keys, values := getAttrs(dp.Attributes, labelNamer) keys = append(keys, kv.keys...) values = append(values, kv.vals...) @@ -396,7 +414,7 @@ func addHistogramMetric[N int64 | float64]( otel.Handle(err) continue } - m = addExemplars(m, dp.Exemplars) + m = addExemplars(m, dp.Exemplars, labelNamer) ch <- m } } @@ -407,6 +425,7 @@ func addSumMetric[N int64 | float64]( m metricdata.Metrics, name string, kv keyVals, + labelNamer otlptranslator.LabelNamer, ) { valueType := prometheus.CounterValue if !sum.IsMonotonic { @@ -414,7 +433,7 @@ func addSumMetric[N int64 | float64]( } for _, dp := range sum.DataPoints { - keys, values := getAttrs(dp.Attributes) + keys, values := getAttrs(dp.Attributes, labelNamer) keys = append(keys, kv.keys...) values = append(values, kv.vals...) @@ -427,7 +446,7 @@ func addSumMetric[N int64 | float64]( // GaugeValues don't support Exemplars at this time // https://github.com/prometheus/client_golang/blob/aef8aedb4b6e1fb8ac1c90790645169125594096/prometheus/metric.go#L199 if valueType != prometheus.GaugeValue { - m = addExemplars(m, dp.Exemplars) + m = addExemplars(m, dp.Exemplars, labelNamer) } ch <- m } @@ -439,9 +458,10 @@ func addGaugeMetric[N int64 | float64]( m metricdata.Metrics, name string, kv keyVals, + labelNamer otlptranslator.LabelNamer, ) { for _, dp := range gauge.DataPoints { - keys, values := getAttrs(dp.Attributes) + keys, values := getAttrs(dp.Attributes, labelNamer) keys = append(keys, kv.keys...) values = append(values, kv.vals...) @@ -457,12 +477,12 @@ func addGaugeMetric[N int64 | float64]( // getAttrs converts the attribute.Set to two lists of matching Prometheus-style // keys and values. -func getAttrs(attrs attribute.Set) ([]string, []string) { +func getAttrs(attrs attribute.Set, labelNamer otlptranslator.LabelNamer) ([]string, []string) { keys := make([]string, 0, attrs.Len()) values := make([]string, 0, attrs.Len()) itr := attrs.Iter() - if model.NameValidationScheme == model.UTF8Validation { // nolint:staticcheck // We need this check to keep supporting the legacy scheme. + if labelNamer.UTF8Allowed { // Do not perform sanitization if prometheus supports UTF-8. for itr.Next() { kv := itr.Attribute() @@ -475,7 +495,7 @@ func getAttrs(attrs attribute.Set) ([]string, []string) { keysMap := make(map[string][]string) for itr.Next() { kv := itr.Attribute() - key := model.EscapeName(string(kv.Key), model.NameEscapingScheme) + key := labelNamer.Build(string(kv.Key)) if _, ok := keysMap[key]; !ok { keysMap[key] = []string{kv.Value.Emit()} } else { @@ -492,91 +512,22 @@ func getAttrs(attrs attribute.Set) ([]string, []string) { return keys, values } -func createInfoMetric(name, description string, res *resource.Resource) (prometheus.Metric, error) { - keys, values := getAttrs(*res.Set()) +func (c *collector) createInfoMetric(name, description string, res *resource.Resource) (prometheus.Metric, error) { + keys, values := getAttrs(*res.Set(), c.labelNamer) desc := prometheus.NewDesc(name, description, keys, nil) return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), values...) } -func unitMapGetOrDefault(unit string) string { - if promUnit, ok := unitSuffixes[unit]; ok { - return promUnit - } - return unit -} - -var unitSuffixes = 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": "ratio", - "%": "percent", -} - // getName returns the sanitized name, prefixed with the namespace and suffixed with unit. -func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string { - name := m.Name - if model.NameValidationScheme != model.UTF8Validation { // nolint:staticcheck // We need this check to keep supporting the legacy scheme. - // Only sanitize if prometheus does not support UTF-8. - logDeprecatedLegacyScheme() - name = model.EscapeName(name, model.NameEscapingScheme) - } - addCounterSuffix := !c.withoutCounterSuffixes && *typ == dto.MetricType_COUNTER - if addCounterSuffix { - // Remove the _total suffix here, as we will re-add the total suffix - // later, and it needs to come after the unit suffix. - name = strings.TrimSuffix(name, counterSuffix) - // If the last character is an underscore, or would be converted to an underscore, trim it from the name. - // an underscore will be added back in later. - if convertsToUnderscore(rune(name[len(name)-1])) { - name = name[:len(name)-1] - } - } - if c.namespace != "" { - name = c.namespace + name +func (c *collector) getName(m metricdata.Metrics) string { + translatorMetric := otlptranslator.Metric{ + Name: m.Name, + Type: c.namingMetricType(m), } - if suffix := unitMapGetOrDefault(m.Unit); suffix != "" && !c.withoutUnits && !strings.HasSuffix(name, suffix) { - name += "_" + suffix + if !c.withoutUnits { + translatorMetric.Unit = m.Unit } - if addCounterSuffix { - name += "_" + counterSuffix - } - return name -} - -// convertsToUnderscore returns true if the character would be converted to an -// underscore when the escaping scheme is underscore escaping. This is meant to -// capture any character that should be considered a "delimiter". -func convertsToUnderscore(b rune) bool { - return (b < 'a' || b > 'z') && (b < 'A' || b > 'Z') && b != ':' && (b < '0' || b > '9') + return c.metricNamer.Build(translatorMetric) } func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType { @@ -601,12 +552,41 @@ func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType { return nil } +// namingMetricType provides the metric type for naming purposes. +func (c *collector) namingMetricType(m metricdata.Metrics) otlptranslator.MetricType { + switch v := m.Data.(type) { + case metricdata.ExponentialHistogram[int64], metricdata.ExponentialHistogram[float64]: + return otlptranslator.MetricTypeHistogram + case metricdata.Histogram[int64], metricdata.Histogram[float64]: + return otlptranslator.MetricTypeHistogram + case metricdata.Sum[float64]: + // If counter suffixes are disabled, treat them like non-monotonic + // suffixes for the purposes of naming. + if v.IsMonotonic && !c.withoutCounterSuffixes { + return otlptranslator.MetricTypeMonotonicCounter + } + return otlptranslator.MetricTypeNonMonotonicCounter + case metricdata.Sum[int64]: + // If counter suffixes are disabled, treat them like non-monotonic + // suffixes for the purposes of naming. + if v.IsMonotonic && !c.withoutCounterSuffixes { + return otlptranslator.MetricTypeMonotonicCounter + } + return otlptranslator.MetricTypeNonMonotonicCounter + case metricdata.Gauge[int64], metricdata.Gauge[float64]: + return otlptranslator.MetricTypeGauge + case metricdata.Summary: + return otlptranslator.MetricTypeSummary + } + return otlptranslator.MetricTypeUnknown +} + func (c *collector) createResourceAttributes(res *resource.Resource) { c.mu.Lock() defer c.mu.Unlock() resourceAttrs, _ := res.Set().Filter(c.resourceAttributesFilter) - resourceKeys, resourceValues := getAttrs(resourceAttrs) + resourceKeys, resourceValues := getAttrs(resourceAttrs, c.labelNamer) c.resourceKeyVals = keyVals{keys: resourceKeys, vals: resourceValues} } @@ -648,16 +628,20 @@ func (c *collector) validateMetrics(name, description string, metricType *dto.Me return false, "" } -func addExemplars[N int64 | float64](m prometheus.Metric, exemplars []metricdata.Exemplar[N]) prometheus.Metric { +func addExemplars[N int64 | float64]( + m prometheus.Metric, + exemplars []metricdata.Exemplar[N], + labelNamer otlptranslator.LabelNamer, +) prometheus.Metric { if len(exemplars) == 0 { return m } promExemplars := make([]prometheus.Exemplar, len(exemplars)) for i, exemplar := range exemplars { - labels := attributesToLabels(exemplar.FilteredAttributes) + labels := attributesToLabels(exemplar.FilteredAttributes, labelNamer) // Overwrite any existing trace ID or span ID attributes - labels[traceIDExemplarKey] = hex.EncodeToString(exemplar.TraceID[:]) - labels[spanIDExemplarKey] = hex.EncodeToString(exemplar.SpanID[:]) + labels[otlptranslator.ExemplarTraceIDKey] = hex.EncodeToString(exemplar.TraceID[:]) + labels[otlptranslator.ExemplarSpanIDKey] = hex.EncodeToString(exemplar.SpanID[:]) promExemplars[i] = prometheus.Exemplar{ Value: float64(exemplar.Value), Timestamp: exemplar.Time, @@ -674,11 +658,10 @@ func addExemplars[N int64 | float64](m prometheus.Metric, exemplars []metricdata return metricWithExemplar } -func attributesToLabels(attrs []attribute.KeyValue) prometheus.Labels { +func attributesToLabels(attrs []attribute.KeyValue, labelNamer otlptranslator.LabelNamer) prometheus.Labels { labels := make(map[string]string) for _, attr := range attrs { - key := model.EscapeName(string(attr.Key), model.NameEscapingScheme) - labels[key] = attr.Value.Emit() + labels[labelNamer.Build(string(attr.Key))] = attr.Value.Emit() } return labels } |
