Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/component/otelcol/receiver/prometheus/internal/util.go
5393 views
1
// Copyright The OpenTelemetry Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver/internal"
16
17
import (
18
"errors"
19
"sort"
20
"strconv"
21
"strings"
22
23
"github.com/prometheus/common/model"
24
"github.com/prometheus/prometheus/model/labels"
25
"github.com/prometheus/prometheus/model/textparse"
26
"go.opentelemetry.io/collector/pdata/pcommon"
27
"go.opentelemetry.io/collector/pdata/pmetric"
28
)
29
30
const (
31
metricsSuffixCount = "_count"
32
metricsSuffixBucket = "_bucket"
33
metricsSuffixSum = "_sum"
34
metricSuffixTotal = "_total"
35
metricSuffixInfo = "_info"
36
startTimeMetricName = "process_start_time_seconds"
37
scrapeUpMetricName = "up"
38
39
transport = "http"
40
dataformat = "prometheus"
41
)
42
43
var (
44
trimmableSuffixes = []string{metricsSuffixBucket, metricsSuffixCount, metricsSuffixSum, metricSuffixTotal, metricSuffixInfo}
45
errNoDataToBuild = errors.New("there's no data to build")
46
errNoBoundaryLabel = errors.New("given metricType has no 'le' or 'quantile' label")
47
errEmptyQuantileLabel = errors.New("'quantile' label on summary metric missing is empty")
48
errEmptyLeLabel = errors.New("'le' label on histogram metric id missing or empty")
49
errMetricNameNotFound = errors.New("metricName not found from labels")
50
errTransactionAborted = errors.New("transaction aborted")
51
errNoJobInstance = errors.New("job or instance cannot be found from labels")
52
53
notUsefulLabelsHistogram = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel, model.BucketLabel})
54
notUsefulLabelsSummary = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel, model.QuantileLabel})
55
notUsefulLabelsOther = sortString([]string{model.MetricNameLabel, model.InstanceLabel, model.SchemeLabel, model.MetricsPathLabel, model.JobLabel})
56
)
57
58
func sortString(strs []string) []string {
59
sort.Strings(strs)
60
return strs
61
}
62
63
func getSortedNotUsefulLabels(mType pmetric.MetricType) []string {
64
switch mType {
65
case pmetric.MetricTypeHistogram:
66
return notUsefulLabelsHistogram
67
case pmetric.MetricTypeSummary:
68
return notUsefulLabelsSummary
69
default:
70
return notUsefulLabelsOther
71
}
72
}
73
74
func timestampFromFloat64(ts float64) pcommon.Timestamp {
75
secs := int64(ts)
76
nanos := int64((ts - float64(secs)) * 1e9)
77
return pcommon.Timestamp(secs*1e9 + nanos)
78
}
79
80
func timestampFromMs(timeAtMs int64) pcommon.Timestamp {
81
return pcommon.Timestamp(timeAtMs * 1e6)
82
}
83
84
func getBoundary(metricType pmetric.MetricType, labels labels.Labels) (float64, error) {
85
val := ""
86
switch metricType {
87
case pmetric.MetricTypeHistogram:
88
val = labels.Get(model.BucketLabel)
89
if val == "" {
90
return 0, errEmptyLeLabel
91
}
92
case pmetric.MetricTypeSummary:
93
val = labels.Get(model.QuantileLabel)
94
if val == "" {
95
return 0, errEmptyQuantileLabel
96
}
97
default:
98
return 0, errNoBoundaryLabel
99
}
100
101
return strconv.ParseFloat(val, 64)
102
}
103
104
// convToMetricType returns the data type and if it is monotonic
105
func convToMetricType(metricType textparse.MetricType) (pmetric.MetricType, bool) {
106
switch metricType {
107
case textparse.MetricTypeCounter:
108
// always use float64, as it's the internal data type used in prometheus
109
return pmetric.MetricTypeSum, true
110
// textparse.MetricTypeUnknown is converted to gauge by default to prevent Prometheus untyped metrics from being dropped
111
case textparse.MetricTypeGauge, textparse.MetricTypeUnknown:
112
return pmetric.MetricTypeGauge, false
113
case textparse.MetricTypeHistogram:
114
return pmetric.MetricTypeHistogram, true
115
// dropping support for gaugehistogram for now until we have an official spec of its implementation
116
// a draft can be found in: https://docs.google.com/document/d/1KwV0mAXwwbvvifBvDKH_LU1YjyXE_wxCkHNoCGq1GX0/edit#heading=h.1cvzqd4ksd23
117
// case textparse.MetricTypeGaugeHistogram:
118
// return <pdata gauge histogram type>
119
case textparse.MetricTypeSummary:
120
return pmetric.MetricTypeSummary, true
121
case textparse.MetricTypeInfo, textparse.MetricTypeStateset:
122
return pmetric.MetricTypeSum, false
123
default:
124
// including: textparse.MetricTypeGaugeHistogram
125
return pmetric.MetricTypeEmpty, false
126
}
127
}
128
129
func normalizeMetricName(name string) string {
130
for _, s := range trimmableSuffixes {
131
if strings.HasSuffix(name, s) && name != s {
132
return strings.TrimSuffix(name, s)
133
}
134
}
135
return name
136
}
137
138