792b4dba2c
* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3 * github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0 * github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2 * github.com/go-chi/cors v1.1.1 -> v1.2.0 * github.com/go-git/go-billy v5.0.0 -> v5.1.0 * github.com/go-git/go-git v5.2.0 -> v5.3.0 * github.com/go-ldap/ldap v3.2.4 -> v3.3.0 * github.com/go-redis/redis v8.6.0 -> v8.8.2 * github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0 * github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0 * github.com/lib/pq v1.9.0 -> v1.10.1 * github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7 * github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0 * github.com/issue9/identicon v1.0.1 -> v1.2.0 * github.com/klauspost/compress v1.11.8 -> v1.12.1 * github.com/mgechev/revive v1.0.3 -> v1.0.6 * github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8 * github.com/niklasfasching/go-org v1.4.0 -> v1.5.0 * github.com/olivere/elastic v7.0.22 -> v7.0.24 * github.com/pelletier/go-toml v1.8.1 -> v1.9.0 * github.com/prometheus/client_golang v1.9.0 -> v1.10.0 * github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0 * github.com/yuin/goldmark v1.3.3 -> v1.3.5 * github.com/6543/go-version v1.2.4 -> v1.3.1 * do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
213 lines
6.6 KiB
Go
Vendored
213 lines
6.6 KiB
Go
Vendored
// Copyright 2014 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"
|
|
"sort"
|
|
"time"
|
|
"unicode/utf8"
|
|
|
|
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/golang/protobuf/ptypes"
|
|
|
|
dto "github.com/prometheus/client_model/go"
|
|
)
|
|
|
|
// ValueType is an enumeration of metric types that represent a simple value.
|
|
type ValueType int
|
|
|
|
// Possible values for the ValueType enum. Use UntypedValue to mark a metric
|
|
// with an unknown type.
|
|
const (
|
|
_ ValueType = iota
|
|
CounterValue
|
|
GaugeValue
|
|
UntypedValue
|
|
)
|
|
|
|
// valueFunc is a generic metric for simple values retrieved on collect time
|
|
// from a function. It implements Metric and Collector. Its effective type is
|
|
// determined by ValueType. This is a low-level building block used by the
|
|
// library to back the implementations of CounterFunc, GaugeFunc, and
|
|
// UntypedFunc.
|
|
type valueFunc struct {
|
|
selfCollector
|
|
|
|
desc *Desc
|
|
valType ValueType
|
|
function func() float64
|
|
labelPairs []*dto.LabelPair
|
|
}
|
|
|
|
// newValueFunc returns a newly allocated valueFunc with the given Desc and
|
|
// ValueType. The value reported is determined by calling the given function
|
|
// from within the Write method. Take into account that metric collection may
|
|
// happen concurrently. If that results in concurrent calls to Write, like in
|
|
// the case where a valueFunc is directly registered with Prometheus, the
|
|
// provided function must be concurrency-safe.
|
|
func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *valueFunc {
|
|
result := &valueFunc{
|
|
desc: desc,
|
|
valType: valueType,
|
|
function: function,
|
|
labelPairs: MakeLabelPairs(desc, nil),
|
|
}
|
|
result.init(result)
|
|
return result
|
|
}
|
|
|
|
func (v *valueFunc) Desc() *Desc {
|
|
return v.desc
|
|
}
|
|
|
|
func (v *valueFunc) Write(out *dto.Metric) error {
|
|
return populateMetric(v.valType, v.function(), v.labelPairs, nil, out)
|
|
}
|
|
|
|
// NewConstMetric returns a metric with one fixed value that cannot be
|
|
// changed. Users of this package will not have much use for it in regular
|
|
// operations. However, when implementing custom Collectors, it is useful as a
|
|
// throw-away metric that is generated on the fly to send it to Prometheus in
|
|
// the Collect method. NewConstMetric returns an error if the length of
|
|
// labelValues is not consistent with the variable labels in Desc or if Desc is
|
|
// invalid.
|
|
func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) {
|
|
if desc.err != nil {
|
|
return nil, desc.err
|
|
}
|
|
if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
|
|
return nil, err
|
|
}
|
|
return &constMetric{
|
|
desc: desc,
|
|
valType: valueType,
|
|
val: value,
|
|
labelPairs: MakeLabelPairs(desc, labelValues),
|
|
}, nil
|
|
}
|
|
|
|
// MustNewConstMetric is a version of NewConstMetric that panics where
|
|
// NewConstMetric would have returned an error.
|
|
func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric {
|
|
m, err := NewConstMetric(desc, valueType, value, labelValues...)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return m
|
|
}
|
|
|
|
type constMetric struct {
|
|
desc *Desc
|
|
valType ValueType
|
|
val float64
|
|
labelPairs []*dto.LabelPair
|
|
}
|
|
|
|
func (m *constMetric) Desc() *Desc {
|
|
return m.desc
|
|
}
|
|
|
|
func (m *constMetric) Write(out *dto.Metric) error {
|
|
return populateMetric(m.valType, m.val, m.labelPairs, nil, out)
|
|
}
|
|
|
|
func populateMetric(
|
|
t ValueType,
|
|
v float64,
|
|
labelPairs []*dto.LabelPair,
|
|
e *dto.Exemplar,
|
|
m *dto.Metric,
|
|
) error {
|
|
m.Label = labelPairs
|
|
switch t {
|
|
case CounterValue:
|
|
m.Counter = &dto.Counter{Value: proto.Float64(v), Exemplar: e}
|
|
case GaugeValue:
|
|
m.Gauge = &dto.Gauge{Value: proto.Float64(v)}
|
|
case UntypedValue:
|
|
m.Untyped = &dto.Untyped{Value: proto.Float64(v)}
|
|
default:
|
|
return fmt.Errorf("encountered unknown type %v", t)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MakeLabelPairs is a helper function to create protobuf LabelPairs from the
|
|
// variable and constant labels in the provided Desc. The values for the
|
|
// variable labels are defined by the labelValues slice, which must be in the
|
|
// same order as the corresponding variable labels in the Desc.
|
|
//
|
|
// This function is only needed for custom Metric implementations. See MetricVec
|
|
// example.
|
|
func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
|
|
totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
|
|
if totalLen == 0 {
|
|
// Super fast path.
|
|
return nil
|
|
}
|
|
if len(desc.variableLabels) == 0 {
|
|
// Moderately fast path.
|
|
return desc.constLabelPairs
|
|
}
|
|
labelPairs := make([]*dto.LabelPair, 0, totalLen)
|
|
for i, n := range desc.variableLabels {
|
|
labelPairs = append(labelPairs, &dto.LabelPair{
|
|
Name: proto.String(n),
|
|
Value: proto.String(labelValues[i]),
|
|
})
|
|
}
|
|
labelPairs = append(labelPairs, desc.constLabelPairs...)
|
|
sort.Sort(labelPairSorter(labelPairs))
|
|
return labelPairs
|
|
}
|
|
|
|
// ExemplarMaxRunes is the max total number of runes allowed in exemplar labels.
|
|
const ExemplarMaxRunes = 64
|
|
|
|
// newExemplar creates a new dto.Exemplar from the provided values. An error is
|
|
// returned if any of the label names or values are invalid or if the total
|
|
// number of runes in the label names and values exceeds ExemplarMaxRunes.
|
|
func newExemplar(value float64, ts time.Time, l Labels) (*dto.Exemplar, error) {
|
|
e := &dto.Exemplar{}
|
|
e.Value = proto.Float64(value)
|
|
tsProto, err := ptypes.TimestampProto(ts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
e.Timestamp = tsProto
|
|
labelPairs := make([]*dto.LabelPair, 0, len(l))
|
|
var runes int
|
|
for name, value := range l {
|
|
if !checkLabelName(name) {
|
|
return nil, fmt.Errorf("exemplar label name %q is invalid", name)
|
|
}
|
|
runes += utf8.RuneCountInString(name)
|
|
if !utf8.ValidString(value) {
|
|
return nil, fmt.Errorf("exemplar label value %q is not valid UTF-8", value)
|
|
}
|
|
runes += utf8.RuneCountInString(value)
|
|
labelPairs = append(labelPairs, &dto.LabelPair{
|
|
Name: proto.String(name),
|
|
Value: proto.String(value),
|
|
})
|
|
}
|
|
if runes > ExemplarMaxRunes {
|
|
return nil, fmt.Errorf("exemplar labels have %d runes, exceeding the limit of %d", runes, ExemplarMaxRunes)
|
|
}
|
|
e.Label = labelPairs
|
|
return e, nil
|
|
}
|