123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver/internal"
- import (
- "errors"
- "sort"
- "strconv"
- "strings"
- "github.com/prometheus/common/model"
- "github.com/prometheus/prometheus/model/labels"
- "github.com/prometheus/prometheus/model/textparse"
- "go.opentelemetry.io/collector/pdata/pcommon"
- "go.opentelemetry.io/collector/pdata/pmetric"
- )
- const (
- metricsSuffixCount = "_count"
- metricsSuffixBucket = "_bucket"
- metricsSuffixSum = "_sum"
- metricSuffixTotal = "_total"
- metricSuffixInfo = "_info"
- metricSuffixCreated = "_created"
- startTimeMetricName = "process_start_time_seconds"
- scrapeUpMetricName = "up"
- transport = "http"
- dataformat = "prometheus"
- )
- var (
- trimmableSuffixes = []string{metricsSuffixBucket, metricsSuffixCount, metricsSuffixSum, metricSuffixTotal, metricSuffixInfo, metricSuffixCreated}
- errNoDataToBuild = errors.New("there's no data to build")
- errNoBoundaryLabel = errors.New("given metricType has no 'le' or 'quantile' label")
- errEmptyQuantileLabel = errors.New("'quantile' label on summary metric is missing or empty")
- errEmptyLeLabel = errors.New("'le' label on histogram metric is missing or empty")
- errMetricNameNotFound = errors.New("metricName not found from labels")
- errTransactionAborted = errors.New("transaction aborted")
- errNoJobInstance = errors.New("job or instance cannot be found from labels")
- notUsefulLabelsHistogram = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel, model.BucketLabel})
- notUsefulLabelsSummary = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel, model.QuantileLabel})
- notUsefulLabelsOther = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel})
- )
- func sortString(strs []string) []string {
- sort.Strings(strs)
- return strs
- }
- func getSortedNotUsefulLabels(mType pmetric.MetricType) []string {
- switch mType {
- case pmetric.MetricTypeHistogram:
- return notUsefulLabelsHistogram
- case pmetric.MetricTypeSummary:
- return notUsefulLabelsSummary
- case pmetric.MetricTypeEmpty, pmetric.MetricTypeGauge, pmetric.MetricTypeSum, pmetric.MetricTypeExponentialHistogram:
- fallthrough
- default:
- return notUsefulLabelsOther
- }
- }
- func timestampFromFloat64(ts float64) pcommon.Timestamp {
- secs := int64(ts)
- nanos := int64((ts - float64(secs)) * 1e9)
- return pcommon.Timestamp(secs*1e9 + nanos)
- }
- func timestampFromMs(timeAtMs int64) pcommon.Timestamp {
- return pcommon.Timestamp(timeAtMs * 1e6)
- }
- func getBoundary(metricType pmetric.MetricType, labels labels.Labels) (float64, error) {
- var val string
- switch metricType {
- case pmetric.MetricTypeHistogram:
- val = labels.Get(model.BucketLabel)
- if val == "" {
- return 0, errEmptyLeLabel
- }
- case pmetric.MetricTypeSummary:
- val = labels.Get(model.QuantileLabel)
- if val == "" {
- return 0, errEmptyQuantileLabel
- }
- case pmetric.MetricTypeEmpty, pmetric.MetricTypeGauge, pmetric.MetricTypeSum, pmetric.MetricTypeExponentialHistogram:
- fallthrough
- default:
- return 0, errNoBoundaryLabel
- }
- return strconv.ParseFloat(val, 64)
- }
- // convToMetricType returns the data type and if it is monotonic
- func convToMetricType(metricType textparse.MetricType) (pmetric.MetricType, bool) {
- switch metricType {
- case textparse.MetricTypeCounter:
- // always use float64, as it's the internal data type used in prometheus
- return pmetric.MetricTypeSum, true
- // textparse.MetricTypeUnknown is converted to gauge by default to prevent Prometheus untyped metrics from being dropped
- case textparse.MetricTypeGauge, textparse.MetricTypeUnknown:
- return pmetric.MetricTypeGauge, false
- case textparse.MetricTypeHistogram:
- return pmetric.MetricTypeHistogram, true
- // dropping support for gaugehistogram for now until we have an official spec of its implementation
- // a draft can be found in: https://docs.google.com/document/d/1KwV0mAXwwbvvifBvDKH_LU1YjyXE_wxCkHNoCGq1GX0/edit#heading=h.1cvzqd4ksd23
- // case textparse.MetricTypeGaugeHistogram:
- // return <pdata gauge histogram type>
- case textparse.MetricTypeSummary:
- return pmetric.MetricTypeSummary, true
- case textparse.MetricTypeInfo, textparse.MetricTypeStateset:
- return pmetric.MetricTypeSum, false
- case textparse.MetricTypeGaugeHistogram:
- fallthrough
- default:
- // including: textparse.MetricTypeGaugeHistogram
- return pmetric.MetricTypeEmpty, false
- }
- }
- func normalizeMetricName(name string) string {
- for _, s := range trimmableSuffixes {
- if strings.HasSuffix(name, s) && name != s {
- return strings.TrimSuffix(name, s)
- }
- }
- return name
- }
|