Path: blob/main/component/otelcol/receiver/prometheus/internal/util.go
5393 views
// Copyright The OpenTelemetry Authors1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver/internal"1516import (17"errors"18"sort"19"strconv"20"strings"2122"github.com/prometheus/common/model"23"github.com/prometheus/prometheus/model/labels"24"github.com/prometheus/prometheus/model/textparse"25"go.opentelemetry.io/collector/pdata/pcommon"26"go.opentelemetry.io/collector/pdata/pmetric"27)2829const (30metricsSuffixCount = "_count"31metricsSuffixBucket = "_bucket"32metricsSuffixSum = "_sum"33metricSuffixTotal = "_total"34metricSuffixInfo = "_info"35startTimeMetricName = "process_start_time_seconds"36scrapeUpMetricName = "up"3738transport = "http"39dataformat = "prometheus"40)4142var (43trimmableSuffixes = []string{metricsSuffixBucket, metricsSuffixCount, metricsSuffixSum, metricSuffixTotal, metricSuffixInfo}44errNoDataToBuild = errors.New("there's no data to build")45errNoBoundaryLabel = errors.New("given metricType has no 'le' or 'quantile' label")46errEmptyQuantileLabel = errors.New("'quantile' label on summary metric missing is empty")47errEmptyLeLabel = errors.New("'le' label on histogram metric id missing or empty")48errMetricNameNotFound = errors.New("metricName not found from labels")49errTransactionAborted = errors.New("transaction aborted")50errNoJobInstance = errors.New("job or instance cannot be found from labels")5152notUsefulLabelsHistogram = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel, model.BucketLabel})53notUsefulLabelsSummary = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel, model.QuantileLabel})54notUsefulLabelsOther = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel})55)5657func sortString(strs []string) []string {58sort.Strings(strs)59return strs60}6162func getSortedNotUsefulLabels(mType pmetric.MetricType) []string {63switch mType {64case pmetric.MetricTypeHistogram:65return notUsefulLabelsHistogram66case pmetric.MetricTypeSummary:67return notUsefulLabelsSummary68default:69return notUsefulLabelsOther70}71}7273func timestampFromFloat64(ts float64) pcommon.Timestamp {74secs := int64(ts)75nanos := int64((ts - float64(secs)) * 1e9)76return pcommon.Timestamp(secs*1e9 + nanos)77}7879func timestampFromMs(timeAtMs int64) pcommon.Timestamp {80return pcommon.Timestamp(timeAtMs * 1e6)81}8283func getBoundary(metricType pmetric.MetricType, labels labels.Labels) (float64, error) {84val := ""85switch metricType {86case pmetric.MetricTypeHistogram:87val = labels.Get(model.BucketLabel)88if val == "" {89return 0, errEmptyLeLabel90}91case pmetric.MetricTypeSummary:92val = labels.Get(model.QuantileLabel)93if val == "" {94return 0, errEmptyQuantileLabel95}96default:97return 0, errNoBoundaryLabel98}99100return strconv.ParseFloat(val, 64)101}102103// convToMetricType returns the data type and if it is monotonic104func convToMetricType(metricType textparse.MetricType) (pmetric.MetricType, bool) {105switch metricType {106case textparse.MetricTypeCounter:107// always use float64, as it's the internal data type used in prometheus108return pmetric.MetricTypeSum, true109// textparse.MetricTypeUnknown is converted to gauge by default to prevent Prometheus untyped metrics from being dropped110case textparse.MetricTypeGauge, textparse.MetricTypeUnknown:111return pmetric.MetricTypeGauge, false112case textparse.MetricTypeHistogram:113return pmetric.MetricTypeHistogram, true114// dropping support for gaugehistogram for now until we have an official spec of its implementation115// a draft can be found in: https://docs.google.com/document/d/1KwV0mAXwwbvvifBvDKH_LU1YjyXE_wxCkHNoCGq1GX0/edit#heading=h.1cvzqd4ksd23116// case textparse.MetricTypeGaugeHistogram:117// return <pdata gauge histogram type>118case textparse.MetricTypeSummary:119return pmetric.MetricTypeSummary, true120case textparse.MetricTypeInfo, textparse.MetricTypeStateset:121return pmetric.MetricTypeSum, false122default:123// including: textparse.MetricTypeGaugeHistogram124return pmetric.MetricTypeEmpty, false125}126}127128func normalizeMetricName(name string) string {129for _, s := range trimmableSuffixes {130if strings.HasSuffix(name, s) && name != s {131return strings.TrimSuffix(name, s)132}133}134return name135}136137138