rollback prometheus/client_golang to 0.7.0
This commit is contained in:
5
vendor/github.com/prometheus/client_golang/NOTICE
generated
vendored
5
vendor/github.com/prometheus/client_golang/NOTICE
generated
vendored
@ -7,6 +7,11 @@ SoundCloud Ltd. (http://soundcloud.com/).
|
|||||||
|
|
||||||
The following components are included in this product:
|
The following components are included in this product:
|
||||||
|
|
||||||
|
goautoneg
|
||||||
|
http://bitbucket.org/ww/goautoneg
|
||||||
|
Copyright 2011, Open Knowledge Foundation Ltd.
|
||||||
|
See README.txt for license details.
|
||||||
|
|
||||||
perks - a fork of https://github.com/bmizerany/perks
|
perks - a fork of https://github.com/bmizerany/perks
|
||||||
https://github.com/beorn7/perks
|
https://github.com/beorn7/perks
|
||||||
Copyright 2013-2015 Blake Mizerany, Björn Rabenstein
|
Copyright 2013-2015 Blake Mizerany, Björn Rabenstein
|
||||||
|
110
vendor/github.com/prometheus/client_golang/model/fingerprinting.go
generated
vendored
Normal file
110
vendor/github.com/prometheus/client_golang/model/fingerprinting.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fingerprint provides a hash-capable representation of a Metric.
|
||||||
|
// For our purposes, FNV-1A 64-bit is used.
|
||||||
|
type Fingerprint uint64
|
||||||
|
|
||||||
|
func (f Fingerprint) String() string {
|
||||||
|
return fmt.Sprintf("%016x", uint64(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less implements sort.Interface.
|
||||||
|
func (f Fingerprint) Less(o Fingerprint) bool {
|
||||||
|
return f < o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal implements sort.Interface.
|
||||||
|
func (f Fingerprint) Equal(o Fingerprint) bool {
|
||||||
|
return f == o
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadFromString transforms a string representation into a Fingerprint.
|
||||||
|
func (f *Fingerprint) LoadFromString(s string) error {
|
||||||
|
num, err := strconv.ParseUint(s, 16, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*f = Fingerprint(num)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fingerprints represents a collection of Fingerprint subject to a given
|
||||||
|
// natural sorting scheme. It implements sort.Interface.
|
||||||
|
type Fingerprints []Fingerprint
|
||||||
|
|
||||||
|
// Len implements sort.Interface.
|
||||||
|
func (f Fingerprints) Len() int {
|
||||||
|
return len(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less implements sort.Interface.
|
||||||
|
func (f Fingerprints) Less(i, j int) bool {
|
||||||
|
return f[i] < f[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap implements sort.Interface.
|
||||||
|
func (f Fingerprints) Swap(i, j int) {
|
||||||
|
f[i], f[j] = f[j], f[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// FingerprintSet is a set of Fingerprints.
|
||||||
|
type FingerprintSet map[Fingerprint]struct{}
|
||||||
|
|
||||||
|
// Equal returns true if both sets contain the same elements (and not more).
|
||||||
|
func (s FingerprintSet) Equal(o FingerprintSet) bool {
|
||||||
|
if len(s) != len(o) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for k := range s {
|
||||||
|
if _, ok := o[k]; !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection returns the elements contained in both sets.
|
||||||
|
func (s FingerprintSet) Intersection(o FingerprintSet) FingerprintSet {
|
||||||
|
myLength, otherLength := len(s), len(o)
|
||||||
|
if myLength == 0 || otherLength == 0 {
|
||||||
|
return FingerprintSet{}
|
||||||
|
}
|
||||||
|
|
||||||
|
subSet := s
|
||||||
|
superSet := o
|
||||||
|
|
||||||
|
if otherLength < myLength {
|
||||||
|
subSet = o
|
||||||
|
superSet = s
|
||||||
|
}
|
||||||
|
|
||||||
|
out := FingerprintSet{}
|
||||||
|
|
||||||
|
for k := range subSet {
|
||||||
|
if _, ok := superSet[k]; ok {
|
||||||
|
out[k] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
119
vendor/github.com/prometheus/client_golang/model/labelname.go
generated
vendored
Normal file
119
vendor/github.com/prometheus/client_golang/model/labelname.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ExportedLabelPrefix is the prefix to prepend to the label names present in
|
||||||
|
// exported metrics if a label of the same name is added by the server.
|
||||||
|
ExportedLabelPrefix LabelName = "exported_"
|
||||||
|
|
||||||
|
// MetricNameLabel is the label name indicating the metric name of a
|
||||||
|
// timeseries.
|
||||||
|
MetricNameLabel LabelName = "__name__"
|
||||||
|
|
||||||
|
// AddressLabel is the name of the label that holds the address of
|
||||||
|
// a scrape target.
|
||||||
|
AddressLabel LabelName = "__address__"
|
||||||
|
|
||||||
|
// MetricsPathLabel is the name of the label that holds the path on which to
|
||||||
|
// scrape a target.
|
||||||
|
MetricsPathLabel LabelName = "__metrics_path__"
|
||||||
|
|
||||||
|
// ReservedLabelPrefix is a prefix which is not legal in user-supplied
|
||||||
|
// label names.
|
||||||
|
ReservedLabelPrefix = "__"
|
||||||
|
|
||||||
|
// MetaLabelPrefix is a prefix for labels that provide meta information.
|
||||||
|
// Labels with this prefix are used for intermediate label processing and
|
||||||
|
// will not be attached to time series.
|
||||||
|
MetaLabelPrefix = "__meta_"
|
||||||
|
|
||||||
|
// JobLabel is the label name indicating the job from which a timeseries
|
||||||
|
// was scraped.
|
||||||
|
JobLabel LabelName = "job"
|
||||||
|
|
||||||
|
// InstanceLabel is the label name used for the instance label.
|
||||||
|
InstanceLabel LabelName = "instance"
|
||||||
|
|
||||||
|
// BucketLabel is used for the label that defines the upper bound of a
|
||||||
|
// bucket of a histogram ("le" -> "less or equal").
|
||||||
|
BucketLabel = "le"
|
||||||
|
|
||||||
|
// QuantileLabel is used for the label that defines the quantile in a
|
||||||
|
// summary.
|
||||||
|
QuantileLabel = "quantile"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LabelNameRE is a regular expression matching valid label names.
|
||||||
|
var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
|
||||||
|
|
||||||
|
// A LabelName is a key for a LabelSet or Metric. It has a value associated
|
||||||
|
// therewith.
|
||||||
|
type LabelName string
|
||||||
|
|
||||||
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||||
|
func (ln *LabelName) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var s string
|
||||||
|
if err := unmarshal(&s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !LabelNameRE.MatchString(s) {
|
||||||
|
return fmt.Errorf("%q is not a valid label name", s)
|
||||||
|
}
|
||||||
|
*ln = LabelName(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
|
func (ln *LabelName) UnmarshalJSON(b []byte) error {
|
||||||
|
var s string
|
||||||
|
if err := json.Unmarshal(b, &s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !LabelNameRE.MatchString(s) {
|
||||||
|
return fmt.Errorf("%q is not a valid label name", s)
|
||||||
|
}
|
||||||
|
*ln = LabelName(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabelNames is a sortable LabelName slice. In implements sort.Interface.
|
||||||
|
type LabelNames []LabelName
|
||||||
|
|
||||||
|
func (l LabelNames) Len() int {
|
||||||
|
return len(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l LabelNames) Less(i, j int) bool {
|
||||||
|
return l[i] < l[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l LabelNames) Swap(i, j int) {
|
||||||
|
l[i], l[j] = l[j], l[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l LabelNames) String() string {
|
||||||
|
labelStrings := make([]string, 0, len(l))
|
||||||
|
for _, label := range l {
|
||||||
|
labelStrings = append(labelStrings, string(label))
|
||||||
|
}
|
||||||
|
return strings.Join(labelStrings, ", ")
|
||||||
|
}
|
83
vendor/github.com/prometheus/client_golang/model/labelset.go
generated
vendored
Normal file
83
vendor/github.com/prometheus/client_golang/model/labelset.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet
|
||||||
|
// may be fully-qualified down to the point where it may resolve to a single
|
||||||
|
// Metric in the data store or not. All operations that occur within the realm
|
||||||
|
// of a LabelSet can emit a vector of Metric entities to which the LabelSet may
|
||||||
|
// match.
|
||||||
|
type LabelSet map[LabelName]LabelValue
|
||||||
|
|
||||||
|
// Merge is a helper function to non-destructively merge two label sets.
|
||||||
|
func (l LabelSet) Merge(other LabelSet) LabelSet {
|
||||||
|
result := make(LabelSet, len(l))
|
||||||
|
|
||||||
|
for k, v := range l {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range other {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l LabelSet) String() string {
|
||||||
|
labelStrings := make([]string, 0, len(l))
|
||||||
|
for label, value := range l {
|
||||||
|
labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch len(labelStrings) {
|
||||||
|
case 0:
|
||||||
|
return ""
|
||||||
|
default:
|
||||||
|
sort.Strings(labelStrings)
|
||||||
|
return fmt.Sprintf("{%s}", strings.Join(labelStrings, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeFromMetric merges Metric into this LabelSet.
|
||||||
|
func (l LabelSet) MergeFromMetric(m Metric) {
|
||||||
|
for k, v := range m {
|
||||||
|
l[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
|
func (l *LabelSet) UnmarshalJSON(b []byte) error {
|
||||||
|
var m map[LabelName]LabelValue
|
||||||
|
if err := json.Unmarshal(b, &m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// encoding/json only unmarshals maps of the form map[string]T. It treats
|
||||||
|
// LabelName as a string and does not call its UnmarshalJSON method.
|
||||||
|
// Thus, we have to replicate the behavior here.
|
||||||
|
for ln := range m {
|
||||||
|
if !LabelNameRE.MatchString(string(ln)) {
|
||||||
|
return fmt.Errorf("%q is not a valid label name", ln)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*l = LabelSet(m)
|
||||||
|
return nil
|
||||||
|
}
|
36
vendor/github.com/prometheus/client_golang/model/labelvalue.go
generated
vendored
Normal file
36
vendor/github.com/prometheus/client_golang/model/labelvalue.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A LabelValue is an associated value for a LabelName.
|
||||||
|
type LabelValue string
|
||||||
|
|
||||||
|
// LabelValues is a sortable LabelValue slice. It implements sort.Interface.
|
||||||
|
type LabelValues []LabelValue
|
||||||
|
|
||||||
|
func (l LabelValues) Len() int {
|
||||||
|
return len(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l LabelValues) Less(i, j int) bool {
|
||||||
|
return sort.StringsAreSorted([]string{string(l[i]), string(l[j])})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l LabelValues) Swap(i, j int) {
|
||||||
|
l[i], l[j] = l[j], l[i]
|
||||||
|
}
|
192
vendor/github.com/prometheus/client_golang/model/metric.go
generated
vendored
Normal file
192
vendor/github.com/prometheus/client_golang/model/metric.go
generated
vendored
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var separator = []byte{0}
|
||||||
|
|
||||||
|
// A Metric is similar to a LabelSet, but the key difference is that a Metric is
|
||||||
|
// a singleton and refers to one and only one stream of samples.
|
||||||
|
type Metric map[LabelName]LabelValue
|
||||||
|
|
||||||
|
// Equal compares the metrics.
|
||||||
|
func (m Metric) Equal(o Metric) bool {
|
||||||
|
if len(m) != len(o) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for ln, lv := range m {
|
||||||
|
olv, ok := o[ln]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if olv != lv {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before compares the metrics, using the following criteria:
|
||||||
|
//
|
||||||
|
// If m has fewer labels than o, it is before o. If it has more, it is not.
|
||||||
|
//
|
||||||
|
// If the number of labels is the same, the superset of all label names is
|
||||||
|
// sorted alphanumerically. The first differing label pair found in that order
|
||||||
|
// determines the outcome: If the label does not exist at all in m, then m is
|
||||||
|
// before o, and vice versa. Otherwise the label value is compared
|
||||||
|
// alphanumerically.
|
||||||
|
//
|
||||||
|
// If m and o are equal, the method returns false.
|
||||||
|
func (m Metric) Before(o Metric) bool {
|
||||||
|
if len(m) < len(o) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if len(m) > len(o) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
lns := make(LabelNames, 0, len(m)+len(o))
|
||||||
|
for ln := range m {
|
||||||
|
lns = append(lns, ln)
|
||||||
|
}
|
||||||
|
for ln := range o {
|
||||||
|
lns = append(lns, ln)
|
||||||
|
}
|
||||||
|
// It's probably not worth it to de-dup lns.
|
||||||
|
sort.Sort(lns)
|
||||||
|
for _, ln := range lns {
|
||||||
|
mlv, ok := m[ln]
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
olv, ok := o[ln]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if mlv < olv {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if mlv > olv {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements Stringer.
|
||||||
|
func (m Metric) String() string {
|
||||||
|
metricName, hasName := m[MetricNameLabel]
|
||||||
|
numLabels := len(m) - 1
|
||||||
|
if !hasName {
|
||||||
|
numLabels = len(m)
|
||||||
|
}
|
||||||
|
labelStrings := make([]string, 0, numLabels)
|
||||||
|
for label, value := range m {
|
||||||
|
if label != MetricNameLabel {
|
||||||
|
labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch numLabels {
|
||||||
|
case 0:
|
||||||
|
if hasName {
|
||||||
|
return string(metricName)
|
||||||
|
}
|
||||||
|
return "{}"
|
||||||
|
default:
|
||||||
|
sort.Strings(labelStrings)
|
||||||
|
return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fingerprint returns a Metric's Fingerprint.
|
||||||
|
func (m Metric) Fingerprint() Fingerprint {
|
||||||
|
return metricToFingerprint(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FastFingerprint returns a Metric's Fingerprint calculated by a faster hashing
|
||||||
|
// algorithm, which is, however, more susceptible to hash collisions.
|
||||||
|
func (m Metric) FastFingerprint() Fingerprint {
|
||||||
|
return metricToFastFingerprint(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone returns a copy of the Metric.
|
||||||
|
func (m Metric) Clone() Metric {
|
||||||
|
clone := Metric{}
|
||||||
|
for k, v := range m {
|
||||||
|
clone[k] = v
|
||||||
|
}
|
||||||
|
return clone
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeFromLabelSet merges a label set into this Metric, prefixing a collision
|
||||||
|
// prefix to the label names merged from the label set where required.
|
||||||
|
func (m Metric) MergeFromLabelSet(labels LabelSet, collisionPrefix LabelName) {
|
||||||
|
for k, v := range labels {
|
||||||
|
if collisionPrefix != "" {
|
||||||
|
for {
|
||||||
|
if _, exists := m[k]; !exists {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
k = collisionPrefix + k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// COWMetric wraps a Metric to enable copy-on-write access patterns.
|
||||||
|
type COWMetric struct {
|
||||||
|
Copied bool
|
||||||
|
Metric Metric
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets a label name in the wrapped Metric to a given value and copies the
|
||||||
|
// Metric initially, if it is not already a copy.
|
||||||
|
func (m *COWMetric) Set(ln LabelName, lv LabelValue) {
|
||||||
|
m.doCOW()
|
||||||
|
m.Metric[ln] = lv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete deletes a given label name from the wrapped Metric and copies the
|
||||||
|
// Metric initially, if it is not already a copy.
|
||||||
|
func (m *COWMetric) Delete(ln LabelName) {
|
||||||
|
m.doCOW()
|
||||||
|
delete(m.Metric, ln)
|
||||||
|
}
|
||||||
|
|
||||||
|
// doCOW copies the underlying Metric if it is not already a copy.
|
||||||
|
func (m *COWMetric) doCOW() {
|
||||||
|
if !m.Copied {
|
||||||
|
m.Metric = m.Metric.Clone()
|
||||||
|
m.Copied = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements fmt.Stringer.
|
||||||
|
func (m COWMetric) String() string {
|
||||||
|
return m.Metric.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler.
|
||||||
|
func (m COWMetric) MarshalJSON() ([]byte, error) {
|
||||||
|
return json.Marshal(m.Metric)
|
||||||
|
}
|
15
vendor/github.com/prometheus/client_golang/model/model.go
generated
vendored
Normal file
15
vendor/github.com/prometheus/client_golang/model/model.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2013 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 model contains core representation of Prometheus client primitives.
|
||||||
|
package model
|
79
vendor/github.com/prometheus/client_golang/model/sample.go
generated
vendored
Normal file
79
vendor/github.com/prometheus/client_golang/model/sample.go
generated
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
// Sample is a sample value with a timestamp and a metric.
|
||||||
|
type Sample struct {
|
||||||
|
Metric Metric
|
||||||
|
Value SampleValue
|
||||||
|
Timestamp Timestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal compares first the metrics, then the timestamp, then the value.
|
||||||
|
func (s *Sample) Equal(o *Sample) bool {
|
||||||
|
if s == o {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.Metric.Equal(o.Metric) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !s.Timestamp.Equal(o.Timestamp) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !s.Value.Equal(o.Value) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Samples is a sortable Sample slice. It implements sort.Interface.
|
||||||
|
type Samples []*Sample
|
||||||
|
|
||||||
|
func (s Samples) Len() int {
|
||||||
|
return len(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less compares first the metrics, then the timestamp.
|
||||||
|
func (s Samples) Less(i, j int) bool {
|
||||||
|
switch {
|
||||||
|
case s[i].Metric.Before(s[j].Metric):
|
||||||
|
return true
|
||||||
|
case s[j].Metric.Before(s[i].Metric):
|
||||||
|
return false
|
||||||
|
case s[i].Timestamp.Before(s[j].Timestamp):
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Samples) Swap(i, j int) {
|
||||||
|
s[i], s[j] = s[j], s[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal compares two sets of samples and returns true if they are equal.
|
||||||
|
func (s Samples) Equal(o Samples) bool {
|
||||||
|
if len(s) != len(o) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, sample := range s {
|
||||||
|
if !sample.Equal(o[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
37
vendor/github.com/prometheus/client_golang/model/samplevalue.go
generated
vendored
Normal file
37
vendor/github.com/prometheus/client_golang/model/samplevalue.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A SampleValue is a representation of a value for a given sample at a given
|
||||||
|
// time.
|
||||||
|
type SampleValue float64
|
||||||
|
|
||||||
|
// Equal does a straight v==o.
|
||||||
|
func (v SampleValue) Equal(o SampleValue) bool {
|
||||||
|
return v == o
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements json.Marshaler.
|
||||||
|
func (v SampleValue) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(fmt.Sprintf(`"%s"`, v)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v SampleValue) String() string {
|
||||||
|
return strconv.FormatFloat(float64(v), 'f', -1, 64)
|
||||||
|
}
|
190
vendor/github.com/prometheus/client_golang/model/signature.go
generated
vendored
Normal file
190
vendor/github.com/prometheus/client_golang/model/signature.go
generated
vendored
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
// 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"hash"
|
||||||
|
"hash/fnv"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SeparatorByte is a byte that cannot occur in valid UTF-8 sequences and is
|
||||||
|
// used to separate label names, label values, and other strings from each other
|
||||||
|
// when calculating their combined hash value (aka signature aka fingerprint).
|
||||||
|
const SeparatorByte byte = 255
|
||||||
|
|
||||||
|
var (
|
||||||
|
// cache the signature of an empty label set.
|
||||||
|
emptyLabelSignature = fnv.New64a().Sum64()
|
||||||
|
|
||||||
|
hashAndBufPool sync.Pool
|
||||||
|
)
|
||||||
|
|
||||||
|
type hashAndBuf struct {
|
||||||
|
h hash.Hash64
|
||||||
|
b bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHashAndBuf() *hashAndBuf {
|
||||||
|
hb := hashAndBufPool.Get()
|
||||||
|
if hb == nil {
|
||||||
|
return &hashAndBuf{h: fnv.New64a()}
|
||||||
|
}
|
||||||
|
return hb.(*hashAndBuf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func putHashAndBuf(hb *hashAndBuf) {
|
||||||
|
hb.h.Reset()
|
||||||
|
hb.b.Reset()
|
||||||
|
hashAndBufPool.Put(hb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
|
||||||
|
// given label set. (Collisions are possible but unlikely if the number of label
|
||||||
|
// sets the function is applied to is small.)
|
||||||
|
func LabelsToSignature(labels map[string]string) uint64 {
|
||||||
|
if len(labels) == 0 {
|
||||||
|
return emptyLabelSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
labelNames := make([]string, 0, len(labels))
|
||||||
|
for labelName := range labels {
|
||||||
|
labelNames = append(labelNames, labelName)
|
||||||
|
}
|
||||||
|
sort.Strings(labelNames)
|
||||||
|
|
||||||
|
hb := getHashAndBuf()
|
||||||
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
|
for _, labelName := range labelNames {
|
||||||
|
hb.b.WriteString(labelName)
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(labels[labelName])
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.h.Write(hb.b.Bytes())
|
||||||
|
hb.b.Reset()
|
||||||
|
}
|
||||||
|
return hb.h.Sum64()
|
||||||
|
}
|
||||||
|
|
||||||
|
// metricToFingerprint works exactly as LabelsToSignature but takes a Metric as
|
||||||
|
// parameter (rather than a label map) and returns a Fingerprint.
|
||||||
|
func metricToFingerprint(m Metric) Fingerprint {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return Fingerprint(emptyLabelSignature)
|
||||||
|
}
|
||||||
|
|
||||||
|
labelNames := make(LabelNames, 0, len(m))
|
||||||
|
for labelName := range m {
|
||||||
|
labelNames = append(labelNames, labelName)
|
||||||
|
}
|
||||||
|
sort.Sort(labelNames)
|
||||||
|
|
||||||
|
hb := getHashAndBuf()
|
||||||
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
|
for _, labelName := range labelNames {
|
||||||
|
hb.b.WriteString(string(labelName))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(string(m[labelName]))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.h.Write(hb.b.Bytes())
|
||||||
|
hb.b.Reset()
|
||||||
|
}
|
||||||
|
return Fingerprint(hb.h.Sum64())
|
||||||
|
}
|
||||||
|
|
||||||
|
// metricToFastFingerprint works similar to metricToFingerprint but uses a
|
||||||
|
// faster and less allocation-heavy hash function, which is more susceptible to
|
||||||
|
// create hash collisions. Therefore, collision detection should be applied.
|
||||||
|
func metricToFastFingerprint(m Metric) Fingerprint {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return Fingerprint(emptyLabelSignature)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result uint64
|
||||||
|
hb := getHashAndBuf()
|
||||||
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
|
for labelName, labelValue := range m {
|
||||||
|
hb.b.WriteString(string(labelName))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(string(labelValue))
|
||||||
|
hb.h.Write(hb.b.Bytes())
|
||||||
|
result ^= hb.h.Sum64()
|
||||||
|
hb.h.Reset()
|
||||||
|
hb.b.Reset()
|
||||||
|
}
|
||||||
|
return Fingerprint(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignatureForLabels works like LabelsToSignature but takes a Metric as
|
||||||
|
// parameter (rather than a label map) and only includes the labels with the
|
||||||
|
// specified LabelNames into the signature calculation. The labels passed in
|
||||||
|
// will be sorted by this function.
|
||||||
|
func SignatureForLabels(m Metric, labels LabelNames) uint64 {
|
||||||
|
if len(m) == 0 || len(labels) == 0 {
|
||||||
|
return emptyLabelSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(labels)
|
||||||
|
|
||||||
|
hb := getHashAndBuf()
|
||||||
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
|
for _, label := range labels {
|
||||||
|
hb.b.WriteString(string(label))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(string(m[label]))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.h.Write(hb.b.Bytes())
|
||||||
|
hb.b.Reset()
|
||||||
|
}
|
||||||
|
return hb.h.Sum64()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignatureWithoutLabels works like LabelsToSignature but takes a Metric as
|
||||||
|
// parameter (rather than a label map) and excludes the labels with any of the
|
||||||
|
// specified LabelNames from the signature calculation.
|
||||||
|
func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return emptyLabelSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
labelNames := make(LabelNames, 0, len(m))
|
||||||
|
for labelName := range m {
|
||||||
|
if _, exclude := labels[labelName]; !exclude {
|
||||||
|
labelNames = append(labelNames, labelName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(labelNames) == 0 {
|
||||||
|
return emptyLabelSignature
|
||||||
|
}
|
||||||
|
sort.Sort(labelNames)
|
||||||
|
|
||||||
|
hb := getHashAndBuf()
|
||||||
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
|
for _, labelName := range labelNames {
|
||||||
|
hb.b.WriteString(string(labelName))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(string(m[labelName]))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.h.Write(hb.b.Bytes())
|
||||||
|
hb.b.Reset()
|
||||||
|
}
|
||||||
|
return hb.h.Sum64()
|
||||||
|
}
|
116
vendor/github.com/prometheus/client_golang/model/timestamp.go
generated
vendored
Normal file
116
vendor/github.com/prometheus/client_golang/model/timestamp.go
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// Copyright 2013 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 model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
native_time "time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Timestamp is the number of milliseconds since the epoch
|
||||||
|
// (1970-01-01 00:00 UTC) excluding leap seconds.
|
||||||
|
type Timestamp int64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MinimumTick is the minimum supported time resolution. This has to be
|
||||||
|
// at least native_time.Second in order for the code below to work.
|
||||||
|
MinimumTick = native_time.Millisecond
|
||||||
|
// second is the timestamp duration equivalent to one second.
|
||||||
|
second = int64(native_time.Second / MinimumTick)
|
||||||
|
// The number of nanoseconds per minimum tick.
|
||||||
|
nanosPerTick = int64(MinimumTick / native_time.Nanosecond)
|
||||||
|
|
||||||
|
// Earliest is the earliest timestamp representable. Handy for
|
||||||
|
// initializing a high watermark.
|
||||||
|
Earliest = Timestamp(math.MinInt64)
|
||||||
|
// Latest is the latest timestamp representable. Handy for initializing
|
||||||
|
// a low watermark.
|
||||||
|
Latest = Timestamp(math.MaxInt64)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Equal reports whether two timestamps represent the same instant.
|
||||||
|
func (t Timestamp) Equal(o Timestamp) bool {
|
||||||
|
return t == o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before reports whether the timestamp t is before o.
|
||||||
|
func (t Timestamp) Before(o Timestamp) bool {
|
||||||
|
return t < o
|
||||||
|
}
|
||||||
|
|
||||||
|
// After reports whether the timestamp t is after o.
|
||||||
|
func (t Timestamp) After(o Timestamp) bool {
|
||||||
|
return t > o
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add returns the Timestamp t + d.
|
||||||
|
func (t Timestamp) Add(d native_time.Duration) Timestamp {
|
||||||
|
return t + Timestamp(d/MinimumTick)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub returns the Duration t - o.
|
||||||
|
func (t Timestamp) Sub(o Timestamp) native_time.Duration {
|
||||||
|
return native_time.Duration(t-o) * MinimumTick
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time returns the time.Time representation of t.
|
||||||
|
func (t Timestamp) Time() native_time.Time {
|
||||||
|
return native_time.Unix(int64(t)/second, (int64(t)%second)*nanosPerTick)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unix returns t as a Unix time, the number of seconds elapsed
|
||||||
|
// since January 1, 1970 UTC.
|
||||||
|
func (t Timestamp) Unix() int64 {
|
||||||
|
return int64(t) / second
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
|
||||||
|
// since January 1, 1970 UTC.
|
||||||
|
func (t Timestamp) UnixNano() int64 {
|
||||||
|
return int64(t) * nanosPerTick
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the timestamp.
|
||||||
|
func (t Timestamp) String() string {
|
||||||
|
return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
|
func (t Timestamp) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(t.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now returns the current time as a Timestamp.
|
||||||
|
func Now() Timestamp {
|
||||||
|
return TimestampFromTime(native_time.Now())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampFromTime returns the Timestamp equivalent to the time.Time t.
|
||||||
|
func TimestampFromTime(t native_time.Time) Timestamp {
|
||||||
|
return TimestampFromUnixNano(t.UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampFromUnix returns the Timestamp equivalent to the Unix timestamp t
|
||||||
|
// provided in seconds.
|
||||||
|
func TimestampFromUnix(t int64) Timestamp {
|
||||||
|
return Timestamp(t * second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampFromUnixNano returns the Timestamp equivalent to the Unix timestamp
|
||||||
|
// t provided in nanoseconds.
|
||||||
|
func TimestampFromUnixNano(t int64) Timestamp {
|
||||||
|
return Timestamp(t / nanosPerTick)
|
||||||
|
}
|
54
vendor/github.com/prometheus/client_golang/prometheus/README.md
generated
vendored
54
vendor/github.com/prometheus/client_golang/prometheus/README.md
generated
vendored
@ -1 +1,53 @@
|
|||||||
See [](https://godoc.org/github.com/prometheus/client_golang/prometheus).
|
# Overview
|
||||||
|
This is the [Prometheus](http://www.prometheus.io) telemetric
|
||||||
|
instrumentation client [Go](http://golang.org) client library. It
|
||||||
|
enable authors to define process-space metrics for their servers and
|
||||||
|
expose them through a web service interface for extraction,
|
||||||
|
aggregation, and a whole slew of other post processing techniques.
|
||||||
|
|
||||||
|
# Installing
|
||||||
|
$ go get github.com/prometheus/client_golang/prometheus
|
||||||
|
|
||||||
|
# Example
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
indexed = prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
|
Namespace: "my_company",
|
||||||
|
Subsystem: "indexer",
|
||||||
|
Name: "documents_indexed",
|
||||||
|
Help: "The number of documents indexed.",
|
||||||
|
})
|
||||||
|
size = prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Namespace: "my_company",
|
||||||
|
Subsystem: "storage",
|
||||||
|
Name: "documents_total_size_bytes",
|
||||||
|
Help: "The total size of all documents in the storage.",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.Handle("/metrics", prometheus.Handler())
|
||||||
|
|
||||||
|
indexed.Inc()
|
||||||
|
size.Set(5)
|
||||||
|
|
||||||
|
http.ListenAndServe(":8080", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
prometheus.MustRegister(indexed)
|
||||||
|
prometheus.MustRegister(size)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
|
[](https://godoc.org/github.com/prometheus/client_golang)
|
||||||
|
52
vendor/github.com/prometheus/client_golang/prometheus/collector.go
generated
vendored
52
vendor/github.com/prometheus/client_golang/prometheus/collector.go
generated
vendored
@ -15,15 +15,15 @@ package prometheus
|
|||||||
|
|
||||||
// Collector is the interface implemented by anything that can be used by
|
// Collector is the interface implemented by anything that can be used by
|
||||||
// Prometheus to collect metrics. A Collector has to be registered for
|
// Prometheus to collect metrics. A Collector has to be registered for
|
||||||
// collection. See Registerer.Register.
|
// collection. See Register, MustRegister, RegisterOrGet, and MustRegisterOrGet.
|
||||||
//
|
//
|
||||||
// The stock metrics provided by this package (Gauge, Counter, Summary,
|
// The stock metrics provided by this package (like Gauge, Counter, Summary) are
|
||||||
// Histogram, Untyped) are also Collectors (which only ever collect one metric,
|
// also Collectors (which only ever collect one metric, namely itself). An
|
||||||
// namely itself). An implementer of Collector may, however, collect multiple
|
// implementer of Collector may, however, collect multiple metrics in a
|
||||||
// metrics in a coordinated fashion and/or create metrics on the fly. Examples
|
// coordinated fashion and/or create metrics on the fly. Examples for collectors
|
||||||
// for collectors already implemented in this library are the metric vectors
|
// already implemented in this library are the metric vectors (i.e. collection
|
||||||
// (i.e. collection of multiple instances of the same Metric but with different
|
// of multiple instances of the same Metric but with different label values)
|
||||||
// label values) like GaugeVec or SummaryVec, and the ExpvarCollector.
|
// like GaugeVec or SummaryVec, and the ExpvarCollector.
|
||||||
type Collector interface {
|
type Collector interface {
|
||||||
// Describe sends the super-set of all possible descriptors of metrics
|
// Describe sends the super-set of all possible descriptors of metrics
|
||||||
// collected by this Collector to the provided channel and returns once
|
// collected by this Collector to the provided channel and returns once
|
||||||
@ -37,39 +37,39 @@ type Collector interface {
|
|||||||
// executing this method, it must send an invalid descriptor (created
|
// executing this method, it must send an invalid descriptor (created
|
||||||
// with NewInvalidDesc) to signal the error to the registry.
|
// with NewInvalidDesc) to signal the error to the registry.
|
||||||
Describe(chan<- *Desc)
|
Describe(chan<- *Desc)
|
||||||
// Collect is called by the Prometheus registry when collecting
|
// Collect is called by Prometheus when collecting metrics. The
|
||||||
// metrics. The implementation sends each collected metric via the
|
// implementation sends each collected metric via the provided channel
|
||||||
// provided channel and returns once the last metric has been sent. The
|
// and returns once the last metric has been sent. The descriptor of
|
||||||
// descriptor of each sent metric is one of those returned by
|
// each sent metric is one of those returned by Describe. Returned
|
||||||
// Describe. Returned metrics that share the same descriptor must differ
|
// metrics that share the same descriptor must differ in their variable
|
||||||
// in their variable label values. This method may be called
|
// label values. This method may be called concurrently and must
|
||||||
// concurrently and must therefore be implemented in a concurrency safe
|
// therefore be implemented in a concurrency safe way. Blocking occurs
|
||||||
// way. Blocking occurs at the expense of total performance of rendering
|
// at the expense of total performance of rendering all registered
|
||||||
// all registered metrics. Ideally, Collector implementations support
|
// metrics. Ideally, Collector implementations support concurrent
|
||||||
// concurrent readers.
|
// readers.
|
||||||
Collect(chan<- Metric)
|
Collect(chan<- Metric)
|
||||||
}
|
}
|
||||||
|
|
||||||
// selfCollector implements Collector for a single Metric so that the Metric
|
// SelfCollector implements Collector for a single Metric so that that the
|
||||||
// collects itself. Add it as an anonymous field to a struct that implements
|
// Metric collects itself. Add it as an anonymous field to a struct that
|
||||||
// Metric, and call init with the Metric itself as an argument.
|
// implements Metric, and call Init with the Metric itself as an argument.
|
||||||
type selfCollector struct {
|
type SelfCollector struct {
|
||||||
self Metric
|
self Metric
|
||||||
}
|
}
|
||||||
|
|
||||||
// init provides the selfCollector with a reference to the metric it is supposed
|
// Init provides the SelfCollector with a reference to the metric it is supposed
|
||||||
// to collect. It is usually called within the factory function to create a
|
// to collect. It is usually called within the factory function to create a
|
||||||
// metric. See example.
|
// metric. See example.
|
||||||
func (c *selfCollector) init(self Metric) {
|
func (c *SelfCollector) Init(self Metric) {
|
||||||
c.self = self
|
c.self = self
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe implements Collector.
|
// Describe implements Collector.
|
||||||
func (c *selfCollector) Describe(ch chan<- *Desc) {
|
func (c *SelfCollector) Describe(ch chan<- *Desc) {
|
||||||
ch <- c.self.Desc()
|
ch <- c.self.Desc()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect implements Collector.
|
// Collect implements Collector.
|
||||||
func (c *selfCollector) Collect(ch chan<- Metric) {
|
func (c *SelfCollector) Collect(ch chan<- Metric) {
|
||||||
ch <- c.self
|
ch <- c.self
|
||||||
}
|
}
|
||||||
|
31
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
31
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
@ -15,6 +15,7 @@ package prometheus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"hash/fnv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Counter is a Metric that represents a single numerical value that only ever
|
// Counter is a Metric that represents a single numerical value that only ever
|
||||||
@ -35,9 +36,6 @@ type Counter interface {
|
|||||||
// Prometheus metric. Do not use it for regular handling of a
|
// Prometheus metric. Do not use it for regular handling of a
|
||||||
// Prometheus counter (as it can be used to break the contract of
|
// Prometheus counter (as it can be used to break the contract of
|
||||||
// monotonically increasing values).
|
// monotonically increasing values).
|
||||||
//
|
|
||||||
// Deprecated: Use NewConstMetric to create a counter for an external
|
|
||||||
// value. A Counter should never be set.
|
|
||||||
Set(float64)
|
Set(float64)
|
||||||
// Inc increments the counter by 1.
|
// Inc increments the counter by 1.
|
||||||
Inc()
|
Inc()
|
||||||
@ -58,7 +56,7 @@ func NewCounter(opts CounterOpts) Counter {
|
|||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
result := &counter{value: value{desc: desc, valType: CounterValue, labelPairs: desc.constLabelPairs}}
|
result := &counter{value: value{desc: desc, valType: CounterValue, labelPairs: desc.constLabelPairs}}
|
||||||
result.init(result) // Init self-collection.
|
result.Init(result) // Init self-collection.
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +80,7 @@ func (c *counter) Add(v float64) {
|
|||||||
// CounterVec embeds MetricVec. See there for a full list of methods with
|
// CounterVec embeds MetricVec. See there for a full list of methods with
|
||||||
// detailed documentation.
|
// detailed documentation.
|
||||||
type CounterVec struct {
|
type CounterVec struct {
|
||||||
*MetricVec
|
MetricVec
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
|
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
|
||||||
@ -96,15 +94,20 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
|||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &CounterVec{
|
return &CounterVec{
|
||||||
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
MetricVec: MetricVec{
|
||||||
result := &counter{value: value{
|
children: map[uint64]Metric{},
|
||||||
desc: desc,
|
desc: desc,
|
||||||
valType: CounterValue,
|
hash: fnv.New64a(),
|
||||||
labelPairs: makeLabelPairs(desc, lvs),
|
newMetric: func(lvs ...string) Metric {
|
||||||
}}
|
result := &counter{value: value{
|
||||||
result.init(result) // Init self-collection.
|
desc: desc,
|
||||||
return result
|
valType: CounterValue,
|
||||||
}),
|
labelPairs: makeLabelPairs(desc, lvs),
|
||||||
|
}}
|
||||||
|
result.Init(result) // Init self-collection.
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
55
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
@ -1,21 +1,10 @@
|
|||||||
// Copyright 2016 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
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -23,17 +12,14 @@ import (
|
|||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
metricNameRE = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_:]*$`)
|
metricNameRE = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_:]*$`)
|
||||||
labelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// reservedLabelPrefix is a prefix which is not legal in user-supplied
|
|
||||||
// label names.
|
|
||||||
const reservedLabelPrefix = "__"
|
|
||||||
|
|
||||||
// Labels represents a collection of label name -> value mappings. This type is
|
// Labels represents a collection of label name -> value mappings. This type is
|
||||||
// commonly used with the With(Labels) and GetMetricWith(Labels) methods of
|
// commonly used with the With(Labels) and GetMetricWith(Labels) methods of
|
||||||
// metric vector Collectors, e.g.:
|
// metric vector Collectors, e.g.:
|
||||||
@ -78,7 +64,7 @@ type Desc struct {
|
|||||||
// Help string. Each Desc with the same fqName must have the same
|
// Help string. Each Desc with the same fqName must have the same
|
||||||
// dimHash.
|
// dimHash.
|
||||||
dimHash uint64
|
dimHash uint64
|
||||||
// err is an error that occurred during construction. It is reported on
|
// err is an error that occured during construction. It is reported on
|
||||||
// registration time.
|
// registration time.
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
@ -142,24 +128,31 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
|||||||
d.err = errors.New("duplicate label names")
|
d.err = errors.New("duplicate label names")
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
vh := hashNew()
|
h := fnv.New64a()
|
||||||
|
var b bytes.Buffer // To copy string contents into, avoiding []byte allocations.
|
||||||
for _, val := range labelValues {
|
for _, val := range labelValues {
|
||||||
vh = hashAdd(vh, val)
|
b.Reset()
|
||||||
vh = hashAddByte(vh, separatorByte)
|
b.WriteString(val)
|
||||||
|
b.WriteByte(model.SeparatorByte)
|
||||||
|
h.Write(b.Bytes())
|
||||||
}
|
}
|
||||||
d.id = vh
|
d.id = h.Sum64()
|
||||||
// Sort labelNames so that order doesn't matter for the hash.
|
// Sort labelNames so that order doesn't matter for the hash.
|
||||||
sort.Strings(labelNames)
|
sort.Strings(labelNames)
|
||||||
// Now hash together (in this order) the help string and the sorted
|
// Now hash together (in this order) the help string and the sorted
|
||||||
// label names.
|
// label names.
|
||||||
lh := hashNew()
|
h.Reset()
|
||||||
lh = hashAdd(lh, help)
|
b.Reset()
|
||||||
lh = hashAddByte(lh, separatorByte)
|
b.WriteString(help)
|
||||||
|
b.WriteByte(model.SeparatorByte)
|
||||||
|
h.Write(b.Bytes())
|
||||||
for _, labelName := range labelNames {
|
for _, labelName := range labelNames {
|
||||||
lh = hashAdd(lh, labelName)
|
b.Reset()
|
||||||
lh = hashAddByte(lh, separatorByte)
|
b.WriteString(labelName)
|
||||||
|
b.WriteByte(model.SeparatorByte)
|
||||||
|
h.Write(b.Bytes())
|
||||||
}
|
}
|
||||||
d.dimHash = lh
|
d.dimHash = h.Sum64()
|
||||||
|
|
||||||
d.constLabelPairs = make([]*dto.LabelPair, 0, len(constLabels))
|
d.constLabelPairs = make([]*dto.LabelPair, 0, len(constLabels))
|
||||||
for n, v := range constLabels {
|
for n, v := range constLabels {
|
||||||
@ -200,6 +193,6 @@ func (d *Desc) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkLabelName(l string) bool {
|
func checkLabelName(l string) bool {
|
||||||
return labelNameRE.MatchString(l) &&
|
return model.LabelNameRE.MatchString(l) &&
|
||||||
!strings.HasPrefix(l, reservedLabelPrefix)
|
!strings.HasPrefix(l, model.ReservedLabelPrefix)
|
||||||
}
|
}
|
||||||
|
178
vendor/github.com/prometheus/client_golang/prometheus/doc.go
generated
vendored
178
vendor/github.com/prometheus/client_golang/prometheus/doc.go
generated
vendored
@ -11,17 +11,18 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Package prometheus provides metrics primitives to instrument code for
|
// Package prometheus provides embeddable metric primitives for servers and
|
||||||
// monitoring. It also offers a registry for metrics. Sub-packages allow to
|
// standardized exposition of telemetry through a web services interface.
|
||||||
// expose the registered metrics via HTTP (package promhttp) or push them to a
|
|
||||||
// Pushgateway (package push).
|
|
||||||
//
|
//
|
||||||
// All exported functions and methods are safe to be used concurrently unless
|
// All exported functions and methods are safe to be used concurrently unless
|
||||||
//specified otherwise.
|
// specified otherwise.
|
||||||
//
|
//
|
||||||
// A Basic Example
|
// To expose metrics registered with the Prometheus registry, an HTTP server
|
||||||
|
// needs to know about the Prometheus handler. The usual endpoint is "/metrics".
|
||||||
//
|
//
|
||||||
// As a starting point, a very basic usage example:
|
// http.Handle("/metrics", prometheus.Handler())
|
||||||
|
//
|
||||||
|
// As a starting point a very basic usage example:
|
||||||
//
|
//
|
||||||
// package main
|
// package main
|
||||||
//
|
//
|
||||||
@ -29,7 +30,6 @@
|
|||||||
// "net/http"
|
// "net/http"
|
||||||
//
|
//
|
||||||
// "github.com/prometheus/client_golang/prometheus"
|
// "github.com/prometheus/client_golang/prometheus"
|
||||||
// "github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// var (
|
// var (
|
||||||
@ -37,145 +37,73 @@
|
|||||||
// Name: "cpu_temperature_celsius",
|
// Name: "cpu_temperature_celsius",
|
||||||
// Help: "Current temperature of the CPU.",
|
// Help: "Current temperature of the CPU.",
|
||||||
// })
|
// })
|
||||||
// hdFailures = prometheus.NewCounterVec(
|
// hdFailures = prometheus.NewCounter(prometheus.CounterOpts{
|
||||||
// prometheus.CounterOpts{
|
// Name: "hd_errors_total",
|
||||||
// Name: "hd_errors_total",
|
// Help: "Number of hard-disk errors.",
|
||||||
// Help: "Number of hard-disk errors.",
|
// })
|
||||||
// },
|
|
||||||
// []string{"device"},
|
|
||||||
// )
|
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// // Metrics have to be registered to be exposed:
|
|
||||||
// prometheus.MustRegister(cpuTemp)
|
// prometheus.MustRegister(cpuTemp)
|
||||||
// prometheus.MustRegister(hdFailures)
|
// prometheus.MustRegister(hdFailures)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// func main() {
|
// func main() {
|
||||||
// cpuTemp.Set(65.3)
|
// cpuTemp.Set(65.3)
|
||||||
// hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc()
|
// hdFailures.Inc()
|
||||||
//
|
//
|
||||||
// // The Handler function provides a default handler to expose metrics
|
// http.Handle("/metrics", prometheus.Handler())
|
||||||
// // via an HTTP server. "/metrics" is the usual endpoint for that.
|
|
||||||
// http.Handle("/metrics", promhttp.Handler())
|
|
||||||
// http.ListenAndServe(":8080", nil)
|
// http.ListenAndServe(":8080", nil)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// This is a complete program that exports two metrics, a Gauge and a Counter,
|
// This is a complete program that exports two metrics, a Gauge and a Counter.
|
||||||
// the latter with a label attached to turn it into a (one-dimensional) vector.
|
// It also exports some stats about the HTTP usage of the /metrics
|
||||||
|
// endpoint. (See the Handler function for more detail.)
|
||||||
//
|
//
|
||||||
// Metrics
|
// Two more advanced metric types are the Summary and Histogram.
|
||||||
//
|
//
|
||||||
// The number of exported identifiers in this package might appear a bit
|
// In addition to the fundamental metric types Gauge, Counter, Summary, and
|
||||||
// overwhelming. Hovever, in addition to the basic plumbing shown in the example
|
// Histogram, a very important part of the Prometheus data model is the
|
||||||
// above, you only need to understand the different metric types and their
|
// partitioning of samples along dimensions called labels, which results in
|
||||||
// vector versions for basic usage.
|
|
||||||
//
|
|
||||||
// Above, you have already touched the Counter and the Gauge. There are two more
|
|
||||||
// advanced metric types: the Summary and Histogram. A more thorough description
|
|
||||||
// of those four metric types can be found in the Prometheus docs:
|
|
||||||
// https://prometheus.io/docs/concepts/metric_types/
|
|
||||||
//
|
|
||||||
// A fifth "type" of metric is Untyped. It behaves like a Gauge, but signals the
|
|
||||||
// Prometheus server not to assume anything about its type.
|
|
||||||
//
|
|
||||||
// In addition to the fundamental metric types Gauge, Counter, Summary,
|
|
||||||
// Histogram, and Untyped, a very important part of the Prometheus data model is
|
|
||||||
// the partitioning of samples along dimensions called labels, which results in
|
|
||||||
// metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec,
|
// metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec,
|
||||||
// HistogramVec, and UntypedVec.
|
// and HistogramVec.
|
||||||
//
|
//
|
||||||
// While only the fundamental metric types implement the Metric interface, both
|
// Those are all the parts needed for basic usage. Detailed documentation and
|
||||||
// the metrics and their vector versions implement the Collector interface. A
|
// examples are provided below.
|
||||||
// Collector manages the collection of a number of Metrics, but for convenience,
|
|
||||||
// a Metric can also “collect itself”. Note that Gauge, Counter, Summary,
|
|
||||||
// Histogram, and Untyped are interfaces themselves while GaugeVec, CounterVec,
|
|
||||||
// SummaryVec, HistogramVec, and UntypedVec are not.
|
|
||||||
//
|
//
|
||||||
// To create instances of Metrics and their vector versions, you need a suitable
|
// Everything else this package offers is essentially for "power users" only. A
|
||||||
// …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts,
|
// few pointers to "power user features":
|
||||||
// HistogramOpts, or UntypedOpts.
|
|
||||||
//
|
//
|
||||||
// Custom Collectors and constant Metrics
|
// All the various ...Opts structs have a ConstLabels field for labels that
|
||||||
|
// never change their value (which is only useful under special circumstances,
|
||||||
|
// see documentation of the Opts type).
|
||||||
//
|
//
|
||||||
// While you could create your own implementations of Metric, most likely you
|
// The Untyped metric behaves like a Gauge, but signals the Prometheus server
|
||||||
// will only ever implement the Collector interface on your own. At a first
|
// not to assume anything about its type.
|
||||||
// glance, a custom Collector seems handy to bundle Metrics for common
|
|
||||||
// registration (with the prime example of the different metric vectors above,
|
|
||||||
// which bundle all the metrics of the same name but with different labels).
|
|
||||||
//
|
//
|
||||||
// There is a more involved use case, too: If you already have metrics
|
// Functions to fine-tune how the metric registry works: EnableCollectChecks,
|
||||||
// available, created outside of the Prometheus context, you don't need the
|
// PanicOnCollectError, Register, Unregister, SetMetricFamilyInjectionHook.
|
||||||
// interface of the various Metric types. You essentially want to mirror the
|
|
||||||
// existing numbers into Prometheus Metrics during collection. An own
|
|
||||||
// implementation of the Collector interface is perfect for that. You can create
|
|
||||||
// Metric instances “on the fly” using NewConstMetric, NewConstHistogram, and
|
|
||||||
// NewConstSummary (and their respective Must… versions). That will happen in
|
|
||||||
// the Collect method. The Describe method has to return separate Desc
|
|
||||||
// instances, representative of the “throw-away” metrics to be created
|
|
||||||
// later. NewDesc comes in handy to create those Desc instances.
|
|
||||||
//
|
//
|
||||||
// The Collector example illustrates the use case. You can also look at the
|
// For custom metric collection, there are two entry points: Custom Metric
|
||||||
// source code of the processCollector (mirroring process metrics), the
|
// implementations and custom Collector implementations. A Metric is the
|
||||||
// goCollector (mirroring Go metrics), or the expvarCollector (mirroring expvar
|
// fundamental unit in the Prometheus data model: a sample at a point in time
|
||||||
// metrics) as examples that are used in this package itself.
|
// together with its meta-data (like its fully-qualified name and any number of
|
||||||
|
// pairs of label name and label value) that knows how to marshal itself into a
|
||||||
|
// data transfer object (aka DTO, implemented as a protocol buffer). A Collector
|
||||||
|
// gets registered with the Prometheus registry and manages the collection of
|
||||||
|
// one or more Metrics. Many parts of this package are building blocks for
|
||||||
|
// Metrics and Collectors. Desc is the metric descriptor, actually used by all
|
||||||
|
// metrics under the hood, and by Collectors to describe the Metrics to be
|
||||||
|
// collected, but only to be dealt with by users if they implement their own
|
||||||
|
// Metrics or Collectors. To create a Desc, the BuildFQName function will come
|
||||||
|
// in handy. Other useful components for Metric and Collector implementation
|
||||||
|
// include: LabelPairSorter to sort the DTO version of label pairs,
|
||||||
|
// NewConstMetric and MustNewConstMetric to create "throw away" Metrics at
|
||||||
|
// collection time, MetricVec to bundle custom Metrics into a metric vector
|
||||||
|
// Collector, SelfCollector to make a custom Metric collect itself.
|
||||||
//
|
//
|
||||||
// If you just need to call a function to get a single float value to collect as
|
// A good example for a custom Collector is the ExpVarCollector included in this
|
||||||
// a metric, GaugeFunc, CounterFunc, or UntypedFunc might be interesting
|
// package, which exports variables exported via the "expvar" package as
|
||||||
// shortcuts.
|
// Prometheus metrics.
|
||||||
//
|
|
||||||
// Advanced Uses of the Registry
|
|
||||||
//
|
|
||||||
// While MustRegister is the by far most common way of registering a Collector,
|
|
||||||
// sometimes you might want to handle the errors the registration might
|
|
||||||
// cause. As suggested by the name, MustRegister panics if an error occurs. With
|
|
||||||
// the Register function, the error is returned and can be handled.
|
|
||||||
//
|
|
||||||
// An error is returned if the registered Collector is incompatible or
|
|
||||||
// inconsistent with already registered metrics. The registry aims for
|
|
||||||
// consistency of the collected metrics according to the Prometheus data
|
|
||||||
// model. Inconsistencies are ideally detected at registration time, not at
|
|
||||||
// collect time. The former will usually be detected at start-up time of a
|
|
||||||
// program, while the latter will only happen at scrape time, possibly not even
|
|
||||||
// on the first scrape if the inconsistency only becomes relevant later. That is
|
|
||||||
// the main reason why a Collector and a Metric have to describe themselves to
|
|
||||||
// the registry.
|
|
||||||
//
|
|
||||||
// So far, everything we did operated on the so-called default registry, as it
|
|
||||||
// can be found in the global DefaultRegistry variable. With NewRegistry, you
|
|
||||||
// can create a custom registry, or you can even implement the Registerer or
|
|
||||||
// Gatherer interfaces yourself. The methods Register and Unregister work in
|
|
||||||
// the same way on a custom registry as the global functions Register and
|
|
||||||
// Unregister on the default registry.
|
|
||||||
//
|
|
||||||
// There are a number of uses for custom registries: You can use registries
|
|
||||||
// with special properties, see NewPedanticRegistry. You can avoid global state,
|
|
||||||
// as it is imposed by the DefaultRegistry. You can use multiple registries at
|
|
||||||
// the same time to expose different metrics in different ways. You can use
|
|
||||||
// separate registries for testing purposes.
|
|
||||||
//
|
|
||||||
// Also note that the DefaultRegistry comes registered with a Collector for Go
|
|
||||||
// runtime metrics (via NewGoCollector) and a Collector for process metrics (via
|
|
||||||
// NewProcessCollector). With a custom registry, you are in control and decide
|
|
||||||
// yourself about the Collectors to register.
|
|
||||||
//
|
|
||||||
// HTTP Exposition
|
|
||||||
//
|
|
||||||
// The Registry implements the Gatherer interface. The caller of the Gather
|
|
||||||
// method can then expose the gathered metrics in some way. Usually, the metrics
|
|
||||||
// are served via HTTP on the /metrics endpoint. That's happening in the example
|
|
||||||
// above. The tools to expose metrics via HTTP are in the promhttp
|
|
||||||
// sub-package. (The top-level functions in the prometheus package are
|
|
||||||
// deprecated.)
|
|
||||||
//
|
|
||||||
// Pushing to the Pushgateway
|
|
||||||
//
|
|
||||||
// Function for pushing to the Pushgateway can be found in the push sub-package.
|
|
||||||
//
|
|
||||||
// Other Means of Exposition
|
|
||||||
//
|
|
||||||
// More ways of exposing metrics can easily be added. Sending metrics to
|
|
||||||
// Graphite would be an example that will soon be implemented.
|
|
||||||
package prometheus
|
package prometheus
|
||||||
|
@ -18,21 +18,21 @@ import (
|
|||||||
"expvar"
|
"expvar"
|
||||||
)
|
)
|
||||||
|
|
||||||
type expvarCollector struct {
|
// ExpvarCollector collects metrics from the expvar interface. It provides a
|
||||||
|
// quick way to expose numeric values that are already exported via expvar as
|
||||||
|
// Prometheus metrics. Note that the data models of expvar and Prometheus are
|
||||||
|
// fundamentally different, and that the ExpvarCollector is inherently
|
||||||
|
// slow. Thus, the ExpvarCollector is probably great for experiments and
|
||||||
|
// prototying, but you should seriously consider a more direct implementation of
|
||||||
|
// Prometheus metrics for monitoring production systems.
|
||||||
|
//
|
||||||
|
// Use NewExpvarCollector to create new instances.
|
||||||
|
type ExpvarCollector struct {
|
||||||
exports map[string]*Desc
|
exports map[string]*Desc
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExpvarCollector returns a newly allocated expvar Collector that still has
|
// NewExpvarCollector returns a newly allocated ExpvarCollector that still has
|
||||||
// to be registered with a Prometheus registry.
|
// to be registered with the Prometheus registry.
|
||||||
//
|
|
||||||
// An expvar Collector collects metrics from the expvar interface. It provides a
|
|
||||||
// quick way to expose numeric values that are already exported via expvar as
|
|
||||||
// Prometheus metrics. Note that the data models of expvar and Prometheus are
|
|
||||||
// fundamentally different, and that the expvar Collector is inherently slower
|
|
||||||
// than native Prometheus metrics. Thus, the expvar Collector is probably great
|
|
||||||
// for experiments and prototying, but you should seriously consider a more
|
|
||||||
// direct implementation of Prometheus metrics for monitoring production
|
|
||||||
// systems.
|
|
||||||
//
|
//
|
||||||
// The exports map has the following meaning:
|
// The exports map has the following meaning:
|
||||||
//
|
//
|
||||||
@ -59,21 +59,21 @@ type expvarCollector struct {
|
|||||||
// sample values.
|
// sample values.
|
||||||
//
|
//
|
||||||
// Anything that does not fit into the scheme above is silently ignored.
|
// Anything that does not fit into the scheme above is silently ignored.
|
||||||
func NewExpvarCollector(exports map[string]*Desc) Collector {
|
func NewExpvarCollector(exports map[string]*Desc) *ExpvarCollector {
|
||||||
return &expvarCollector{
|
return &ExpvarCollector{
|
||||||
exports: exports,
|
exports: exports,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe implements Collector.
|
// Describe implements Collector.
|
||||||
func (e *expvarCollector) Describe(ch chan<- *Desc) {
|
func (e *ExpvarCollector) Describe(ch chan<- *Desc) {
|
||||||
for _, desc := range e.exports {
|
for _, desc := range e.exports {
|
||||||
ch <- desc
|
ch <- desc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect implements Collector.
|
// Collect implements Collector.
|
||||||
func (e *expvarCollector) Collect(ch chan<- Metric) {
|
func (e *ExpvarCollector) Collect(ch chan<- Metric) {
|
||||||
for name, desc := range e.exports {
|
for name, desc := range e.exports {
|
||||||
var m Metric
|
var m Metric
|
||||||
expVar := expvar.Get(name)
|
expVar := expvar.Get(name)
|
29
vendor/github.com/prometheus/client_golang/prometheus/fnv.go
generated
vendored
29
vendor/github.com/prometheus/client_golang/prometheus/fnv.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
package prometheus
|
|
||||||
|
|
||||||
// Inline and byte-free variant of hash/fnv's fnv64a.
|
|
||||||
|
|
||||||
const (
|
|
||||||
offset64 = 14695981039346656037
|
|
||||||
prime64 = 1099511628211
|
|
||||||
)
|
|
||||||
|
|
||||||
// hashNew initializies a new fnv64a hash value.
|
|
||||||
func hashNew() uint64 {
|
|
||||||
return offset64
|
|
||||||
}
|
|
||||||
|
|
||||||
// hashAdd adds a string to a fnv64a hash value, returning the updated hash.
|
|
||||||
func hashAdd(h uint64, s string) uint64 {
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
h ^= uint64(s[i])
|
|
||||||
h *= prime64
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash.
|
|
||||||
func hashAddByte(h uint64, b byte) uint64 {
|
|
||||||
h ^= uint64(b)
|
|
||||||
h *= prime64
|
|
||||||
return h
|
|
||||||
}
|
|
15
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
15
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
|
import "hash/fnv"
|
||||||
|
|
||||||
// Gauge is a Metric that represents a single numerical value that can
|
// Gauge is a Metric that represents a single numerical value that can
|
||||||
// arbitrarily go up and down.
|
// arbitrarily go up and down.
|
||||||
//
|
//
|
||||||
@ -58,7 +60,7 @@ func NewGauge(opts GaugeOpts) Gauge {
|
|||||||
// (e.g. number of operations queued, partitioned by user and operation
|
// (e.g. number of operations queued, partitioned by user and operation
|
||||||
// type). Create instances with NewGaugeVec.
|
// type). Create instances with NewGaugeVec.
|
||||||
type GaugeVec struct {
|
type GaugeVec struct {
|
||||||
*MetricVec
|
MetricVec
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
|
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
|
||||||
@ -72,9 +74,14 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
|||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &GaugeVec{
|
return &GaugeVec{
|
||||||
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
MetricVec: MetricVec{
|
||||||
return newValue(desc, GaugeValue, 0, lvs...)
|
children: map[uint64]Metric{},
|
||||||
}),
|
desc: desc,
|
||||||
|
hash: fnv.New64a(),
|
||||||
|
newMetric: func(lvs ...string) Metric {
|
||||||
|
return newValue(desc, GaugeValue, 0, lvs...)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
219
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
219
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
@ -1,7 +1,6 @@
|
|||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
@ -10,226 +9,27 @@ import (
|
|||||||
type goCollector struct {
|
type goCollector struct {
|
||||||
goroutines Gauge
|
goroutines Gauge
|
||||||
gcDesc *Desc
|
gcDesc *Desc
|
||||||
|
|
||||||
// metrics to describe and collect
|
|
||||||
metrics memStatsMetrics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGoCollector returns a collector which exports metrics about the current
|
// NewGoCollector returns a collector which exports metrics about the current
|
||||||
// go process.
|
// go process.
|
||||||
func NewGoCollector() Collector {
|
func NewGoCollector() *goCollector {
|
||||||
return &goCollector{
|
return &goCollector{
|
||||||
goroutines: NewGauge(GaugeOpts{
|
goroutines: NewGauge(GaugeOpts{
|
||||||
Namespace: "go",
|
Name: "go_goroutines",
|
||||||
Name: "goroutines",
|
Help: "Number of goroutines that currently exist.",
|
||||||
Help: "Number of goroutines that currently exist.",
|
|
||||||
}),
|
}),
|
||||||
gcDesc: NewDesc(
|
gcDesc: NewDesc(
|
||||||
"go_gc_duration_seconds",
|
"go_gc_duration_seconds",
|
||||||
"A summary of the GC invocation durations.",
|
"A summary of the GC invocation durations.",
|
||||||
nil, nil),
|
nil, nil),
|
||||||
metrics: memStatsMetrics{
|
|
||||||
{
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("alloc_bytes"),
|
|
||||||
"Number of bytes allocated and still in use.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Alloc) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("alloc_bytes_total"),
|
|
||||||
"Total number of bytes allocated, even if freed.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.TotalAlloc) },
|
|
||||||
valType: CounterValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("sys_bytes"),
|
|
||||||
"Number of bytes obtained by system. Sum of all system allocations.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Sys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("lookups_total"),
|
|
||||||
"Total number of pointer lookups.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Lookups) },
|
|
||||||
valType: CounterValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("mallocs_total"),
|
|
||||||
"Total number of mallocs.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Mallocs) },
|
|
||||||
valType: CounterValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("frees_total"),
|
|
||||||
"Total number of frees.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.Frees) },
|
|
||||||
valType: CounterValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("heap_alloc_bytes"),
|
|
||||||
"Number of heap bytes allocated and still in use.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapAlloc) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("heap_sys_bytes"),
|
|
||||||
"Number of heap bytes obtained from system.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("heap_idle_bytes"),
|
|
||||||
"Number of heap bytes waiting to be used.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapIdle) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("heap_inuse_bytes"),
|
|
||||||
"Number of heap bytes that are in use.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapInuse) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("heap_released_bytes_total"),
|
|
||||||
"Total number of heap bytes released to OS.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapReleased) },
|
|
||||||
valType: CounterValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("heap_objects"),
|
|
||||||
"Number of allocated objects.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.HeapObjects) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("stack_inuse_bytes"),
|
|
||||||
"Number of bytes in use by the stack allocator.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackInuse) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("stack_sys_bytes"),
|
|
||||||
"Number of bytes obtained from system for stack allocator.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.StackSys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("mspan_inuse_bytes"),
|
|
||||||
"Number of bytes in use by mspan structures.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanInuse) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("mspan_sys_bytes"),
|
|
||||||
"Number of bytes used for mspan structures obtained from system.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MSpanSys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("mcache_inuse_bytes"),
|
|
||||||
"Number of bytes in use by mcache structures.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheInuse) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("mcache_sys_bytes"),
|
|
||||||
"Number of bytes used for mcache structures obtained from system.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.MCacheSys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("buck_hash_sys_bytes"),
|
|
||||||
"Number of bytes used by the profiling bucket hash table.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.BuckHashSys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("gc_sys_bytes"),
|
|
||||||
"Number of bytes used for garbage collection system metadata.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.GCSys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("other_sys_bytes"),
|
|
||||||
"Number of bytes used for other system allocations.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.OtherSys) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("next_gc_bytes"),
|
|
||||||
"Number of heap bytes when next garbage collection will take place.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.NextGC) },
|
|
||||||
valType: GaugeValue,
|
|
||||||
}, {
|
|
||||||
desc: NewDesc(
|
|
||||||
memstatNamespace("last_gc_time_seconds"),
|
|
||||||
"Number of seconds since 1970 of last garbage collection.",
|
|
||||||
nil, nil,
|
|
||||||
),
|
|
||||||
eval: func(ms *runtime.MemStats) float64 { return float64(ms.LastGC) / 1e9 },
|
|
||||||
valType: GaugeValue,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func memstatNamespace(s string) string {
|
|
||||||
return fmt.Sprintf("go_memstats_%s", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Describe returns all descriptions of the collector.
|
// Describe returns all descriptions of the collector.
|
||||||
func (c *goCollector) Describe(ch chan<- *Desc) {
|
func (c *goCollector) Describe(ch chan<- *Desc) {
|
||||||
ch <- c.goroutines.Desc()
|
ch <- c.goroutines.Desc()
|
||||||
ch <- c.gcDesc
|
ch <- c.gcDesc
|
||||||
|
|
||||||
for _, i := range c.metrics {
|
|
||||||
ch <- i.desc
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect returns the current state of all metrics of the collector.
|
// Collect returns the current state of all metrics of the collector.
|
||||||
@ -247,17 +47,4 @@ func (c *goCollector) Collect(ch chan<- Metric) {
|
|||||||
}
|
}
|
||||||
quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
|
quantiles[0.0] = stats.PauseQuantiles[0].Seconds()
|
||||||
ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles)
|
ch <- MustNewConstSummary(c.gcDesc, uint64(stats.NumGC), float64(stats.PauseTotal.Seconds()), quantiles)
|
||||||
|
|
||||||
ms := &runtime.MemStats{}
|
|
||||||
runtime.ReadMemStats(ms)
|
|
||||||
for _, i := range c.metrics {
|
|
||||||
ch <- MustNewConstMetric(i.desc, i.valType, i.eval(ms))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// memStatsMetrics provide description, value, and value type for memstat metrics.
|
|
||||||
type memStatsMetrics []struct {
|
|
||||||
desc *Desc
|
|
||||||
eval func(*runtime.MemStats) float64
|
|
||||||
valType ValueType
|
|
||||||
}
|
}
|
||||||
|
37
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
37
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
@ -15,12 +15,14 @@ package prometheus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/model"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,19 +49,15 @@ type Histogram interface {
|
|||||||
Observe(float64)
|
Observe(float64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// bucketLabel is used for the label that defines the upper bound of a
|
|
||||||
// bucket of a histogram ("le" -> "less or equal").
|
|
||||||
const bucketLabel = "le"
|
|
||||||
|
|
||||||
// DefBuckets are the default Histogram buckets. The default buckets are
|
|
||||||
// tailored to broadly measure the response time (in seconds) of a network
|
|
||||||
// service. Most likely, however, you will be required to define buckets
|
|
||||||
// customized to your use case.
|
|
||||||
var (
|
var (
|
||||||
|
// DefBuckets are the default Histogram buckets. The default buckets are
|
||||||
|
// tailored to broadly measure the response time (in seconds) of a
|
||||||
|
// network service. Most likely, however, you will be required to define
|
||||||
|
// buckets customized to your use case.
|
||||||
DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
|
DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10}
|
||||||
|
|
||||||
errBucketLabelNotAllowed = fmt.Errorf(
|
errBucketLabelNotAllowed = fmt.Errorf(
|
||||||
"%q is not allowed as label name in histograms", bucketLabel,
|
"%q is not allowed as label name in histograms", model.BucketLabel,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -173,12 +171,12 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range desc.variableLabels {
|
for _, n := range desc.variableLabels {
|
||||||
if n == bucketLabel {
|
if n == model.BucketLabel {
|
||||||
panic(errBucketLabelNotAllowed)
|
panic(errBucketLabelNotAllowed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, lp := range desc.constLabelPairs {
|
for _, lp := range desc.constLabelPairs {
|
||||||
if lp.GetName() == bucketLabel {
|
if lp.GetName() == model.BucketLabel {
|
||||||
panic(errBucketLabelNotAllowed)
|
panic(errBucketLabelNotAllowed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,7 +208,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
|||||||
// Finally we know the final length of h.upperBounds and can make counts.
|
// Finally we know the final length of h.upperBounds and can make counts.
|
||||||
h.counts = make([]uint64, len(h.upperBounds))
|
h.counts = make([]uint64, len(h.upperBounds))
|
||||||
|
|
||||||
h.init(h) // Init self-collection.
|
h.Init(h) // Init self-collection.
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +220,7 @@ type histogram struct {
|
|||||||
sumBits uint64
|
sumBits uint64
|
||||||
count uint64
|
count uint64
|
||||||
|
|
||||||
selfCollector
|
SelfCollector
|
||||||
// Note that there is no mutex required.
|
// Note that there is no mutex required.
|
||||||
|
|
||||||
desc *Desc
|
desc *Desc
|
||||||
@ -287,7 +285,7 @@ func (h *histogram) Write(out *dto.Metric) error {
|
|||||||
// (e.g. HTTP request latencies, partitioned by status code and method). Create
|
// (e.g. HTTP request latencies, partitioned by status code and method). Create
|
||||||
// instances with NewHistogramVec.
|
// instances with NewHistogramVec.
|
||||||
type HistogramVec struct {
|
type HistogramVec struct {
|
||||||
*MetricVec
|
MetricVec
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
|
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
|
||||||
@ -301,9 +299,14 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
|||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &HistogramVec{
|
return &HistogramVec{
|
||||||
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
MetricVec: MetricVec{
|
||||||
return newHistogram(desc, opts, lvs...)
|
children: map[uint64]Metric{},
|
||||||
}),
|
desc: desc,
|
||||||
|
hash: fnv.New64a(),
|
||||||
|
newMetric: func(lvs ...string) Metric {
|
||||||
|
return newHistogram(desc, opts, lvs...)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
200
vendor/github.com/prometheus/client_golang/prometheus/http.go
generated
vendored
200
vendor/github.com/prometheus/client_golang/prometheus/http.go
generated
vendored
@ -15,114 +15,14 @@ package prometheus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"compress/gzip"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/common/expfmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(beorn7): Remove this whole file. It is a partial mirror of
|
|
||||||
// promhttp/http.go (to avoid circular import chains) where everything HTTP
|
|
||||||
// related should live. The functions here are just for avoiding
|
|
||||||
// breakage. Everything is deprecated.
|
|
||||||
|
|
||||||
const (
|
|
||||||
contentTypeHeader = "Content-Type"
|
|
||||||
contentLengthHeader = "Content-Length"
|
|
||||||
contentEncodingHeader = "Content-Encoding"
|
|
||||||
acceptEncodingHeader = "Accept-Encoding"
|
|
||||||
)
|
|
||||||
|
|
||||||
var bufPool sync.Pool
|
|
||||||
|
|
||||||
func getBuf() *bytes.Buffer {
|
|
||||||
buf := bufPool.Get()
|
|
||||||
if buf == nil {
|
|
||||||
return &bytes.Buffer{}
|
|
||||||
}
|
|
||||||
return buf.(*bytes.Buffer)
|
|
||||||
}
|
|
||||||
|
|
||||||
func giveBuf(buf *bytes.Buffer) {
|
|
||||||
buf.Reset()
|
|
||||||
bufPool.Put(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handler returns an HTTP handler for the DefaultGatherer. It is
|
|
||||||
// already instrumented with InstrumentHandler (using "prometheus" as handler
|
|
||||||
// name).
|
|
||||||
//
|
|
||||||
// Deprecated: Please note the issues described in the doc comment of
|
|
||||||
// InstrumentHandler. You might want to consider using promhttp.Handler instead
|
|
||||||
// (which is non instrumented).
|
|
||||||
func Handler() http.Handler {
|
|
||||||
return InstrumentHandler("prometheus", UninstrumentedHandler())
|
|
||||||
}
|
|
||||||
|
|
||||||
// UninstrumentedHandler returns an HTTP handler for the DefaultGatherer.
|
|
||||||
//
|
|
||||||
// Deprecated: Use promhttp.Handler instead. See there for further documentation.
|
|
||||||
func UninstrumentedHandler() http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
mfs, err := DefaultGatherer.Gather()
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, "An error has occurred during metrics collection:\n\n"+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
contentType := expfmt.Negotiate(req.Header)
|
|
||||||
buf := getBuf()
|
|
||||||
defer giveBuf(buf)
|
|
||||||
writer, encoding := decorateWriter(req, buf)
|
|
||||||
enc := expfmt.NewEncoder(writer, contentType)
|
|
||||||
var lastErr error
|
|
||||||
for _, mf := range mfs {
|
|
||||||
if err := enc.Encode(mf); err != nil {
|
|
||||||
lastErr = err
|
|
||||||
http.Error(w, "An error has occurred during metrics encoding:\n\n"+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if closer, ok := writer.(io.Closer); ok {
|
|
||||||
closer.Close()
|
|
||||||
}
|
|
||||||
if lastErr != nil && buf.Len() == 0 {
|
|
||||||
http.Error(w, "No metrics encoded, last error:\n\n"+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
header := w.Header()
|
|
||||||
header.Set(contentTypeHeader, string(contentType))
|
|
||||||
header.Set(contentLengthHeader, fmt.Sprint(buf.Len()))
|
|
||||||
if encoding != "" {
|
|
||||||
header.Set(contentEncodingHeader, encoding)
|
|
||||||
}
|
|
||||||
w.Write(buf.Bytes())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// decorateWriter wraps a writer to handle gzip compression if requested. It
|
|
||||||
// returns the decorated writer and the appropriate "Content-Encoding" header
|
|
||||||
// (which is empty if no compression is enabled).
|
|
||||||
func decorateWriter(request *http.Request, writer io.Writer) (io.Writer, string) {
|
|
||||||
header := request.Header.Get(acceptEncodingHeader)
|
|
||||||
parts := strings.Split(header, ",")
|
|
||||||
for _, part := range parts {
|
|
||||||
part := strings.TrimSpace(part)
|
|
||||||
if part == "gzip" || strings.HasPrefix(part, "gzip;") {
|
|
||||||
return gzip.NewWriter(writer), "gzip"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return writer, ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var instLabels = []string{"method", "code"}
|
var instLabels = []string{"method", "code"}
|
||||||
|
|
||||||
type nower interface {
|
type nower interface {
|
||||||
@ -157,34 +57,12 @@ func nowSeries(t ...time.Time) nower {
|
|||||||
// has a constant label named "handler" with the provided handlerName as
|
// has a constant label named "handler" with the provided handlerName as
|
||||||
// value. http_requests_total is a metric vector partitioned by HTTP method
|
// value. http_requests_total is a metric vector partitioned by HTTP method
|
||||||
// (label name "method") and HTTP status code (label name "code").
|
// (label name "method") and HTTP status code (label name "code").
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandler has several issues:
|
|
||||||
//
|
|
||||||
// - It uses Summaries rather than Histograms. Summaries are not useful if
|
|
||||||
// aggregation across multiple instances is required.
|
|
||||||
//
|
|
||||||
// - It uses microseconds as unit, which is deprecated and should be replaced by
|
|
||||||
// seconds.
|
|
||||||
//
|
|
||||||
// - The size of the request is calculated in a separate goroutine. Since this
|
|
||||||
// calculator requires access to the request header, it creates a race with
|
|
||||||
// any writes to the header performed during request handling.
|
|
||||||
// httputil.ReverseProxy is a prominent example for a handler
|
|
||||||
// performing such writes.
|
|
||||||
//
|
|
||||||
// Upcoming versions of this package will provide ways of instrumenting HTTP
|
|
||||||
// handlers that are more flexible and have fewer issues. Please prefer direct
|
|
||||||
// instrumentation in the meantime.
|
|
||||||
func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc {
|
func InstrumentHandler(handlerName string, handler http.Handler) http.HandlerFunc {
|
||||||
return InstrumentHandlerFunc(handlerName, handler.ServeHTTP)
|
return InstrumentHandlerFunc(handlerName, handler.ServeHTTP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstrumentHandlerFunc wraps the given function for instrumentation. It
|
// InstrumentHandlerFunc wraps the given function for instrumentation. It
|
||||||
// otherwise works in the same way as InstrumentHandler (and shares the same
|
// otherwise works in the same way as InstrumentHandler.
|
||||||
// issues).
|
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandlerFunc is deprecated for the same reasons as
|
|
||||||
// InstrumentHandler is.
|
|
||||||
func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||||
return InstrumentHandlerFuncWithOpts(
|
return InstrumentHandlerFuncWithOpts(
|
||||||
SummaryOpts{
|
SummaryOpts{
|
||||||
@ -195,13 +73,13 @@ func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWri
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstrumentHandlerWithOpts works like InstrumentHandler (and shares the same
|
// InstrumentHandlerWithOpts works like InstrumentHandler but provides more
|
||||||
// issues) but provides more flexibility (at the cost of a more complex call
|
// flexibility (at the cost of a more complex call syntax). As
|
||||||
// syntax). As InstrumentHandler, this function registers four metric
|
// InstrumentHandler, this function registers four metric collectors, but it
|
||||||
// collectors, but it uses the provided SummaryOpts to create them. However, the
|
// uses the provided SummaryOpts to create them. However, the fields "Name" and
|
||||||
// fields "Name" and "Help" in the SummaryOpts are ignored. "Name" is replaced
|
// "Help" in the SummaryOpts are ignored. "Name" is replaced by
|
||||||
// by "requests_total", "request_duration_microseconds", "request_size_bytes",
|
// "requests_total", "request_duration_microseconds", "request_size_bytes", and
|
||||||
// and "response_size_bytes", respectively. "Help" is replaced by an appropriate
|
// "response_size_bytes", respectively. "Help" is replaced by an appropriate
|
||||||
// help string. The names of the variable labels of the http_requests_total
|
// help string. The names of the variable labels of the http_requests_total
|
||||||
// CounterVec are "method" (get, post, etc.), and "code" (HTTP status code).
|
// CounterVec are "method" (get, post, etc.), and "code" (HTTP status code).
|
||||||
//
|
//
|
||||||
@ -220,20 +98,13 @@ func InstrumentHandlerFunc(handlerName string, handlerFunc func(http.ResponseWri
|
|||||||
// cannot use SummaryOpts. Instead, a CounterOpts struct is created internally,
|
// cannot use SummaryOpts. Instead, a CounterOpts struct is created internally,
|
||||||
// and all its fields are set to the equally named fields in the provided
|
// and all its fields are set to the equally named fields in the provided
|
||||||
// SummaryOpts.
|
// SummaryOpts.
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandlerWithOpts is deprecated for the same reasons as
|
|
||||||
// InstrumentHandler is.
|
|
||||||
func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc {
|
func InstrumentHandlerWithOpts(opts SummaryOpts, handler http.Handler) http.HandlerFunc {
|
||||||
return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP)
|
return InstrumentHandlerFuncWithOpts(opts, handler.ServeHTTP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc (and shares
|
// InstrumentHandlerFuncWithOpts works like InstrumentHandlerFunc but provides
|
||||||
// the same issues) but provides more flexibility (at the cost of a more complex
|
// more flexibility (at the cost of a more complex call syntax). See
|
||||||
// call syntax). See InstrumentHandlerWithOpts for details how the provided
|
// InstrumentHandlerWithOpts for details how the provided SummaryOpts are used.
|
||||||
// SummaryOpts are used.
|
|
||||||
//
|
|
||||||
// Deprecated: InstrumentHandlerFuncWithOpts is deprecated for the same reasons
|
|
||||||
// as InstrumentHandler is.
|
|
||||||
func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
|
||||||
reqCnt := NewCounterVec(
|
reqCnt := NewCounterVec(
|
||||||
CounterOpts{
|
CounterOpts{
|
||||||
@ -267,7 +138,12 @@ func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.Respo
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
delegate := &responseWriterDelegator{ResponseWriter: w}
|
delegate := &responseWriterDelegator{ResponseWriter: w}
|
||||||
out := computeApproximateRequestSize(r)
|
out := make(chan int)
|
||||||
|
urlLen := 0
|
||||||
|
if r.URL != nil {
|
||||||
|
urlLen = len(r.URL.String())
|
||||||
|
}
|
||||||
|
go computeApproximateRequestSize(r, out, urlLen)
|
||||||
|
|
||||||
_, cn := w.(http.CloseNotifier)
|
_, cn := w.(http.CloseNotifier)
|
||||||
_, fl := w.(http.Flusher)
|
_, fl := w.(http.Flusher)
|
||||||
@ -292,37 +168,23 @@ func InstrumentHandlerFuncWithOpts(opts SummaryOpts, handlerFunc func(http.Respo
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func computeApproximateRequestSize(r *http.Request) <-chan int {
|
func computeApproximateRequestSize(r *http.Request, out chan int, s int) {
|
||||||
// Get URL length in current go routine for avoiding a race condition.
|
s += len(r.Method)
|
||||||
// HandlerFunc that runs in parallel may modify the URL.
|
s += len(r.Proto)
|
||||||
s := 0
|
for name, values := range r.Header {
|
||||||
if r.URL != nil {
|
s += len(name)
|
||||||
s += len(r.URL.String())
|
for _, value := range values {
|
||||||
|
s += len(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
s += len(r.Host)
|
||||||
|
|
||||||
out := make(chan int, 1)
|
// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
|
||||||
|
|
||||||
go func() {
|
if r.ContentLength != -1 {
|
||||||
s += len(r.Method)
|
s += int(r.ContentLength)
|
||||||
s += len(r.Proto)
|
}
|
||||||
for name, values := range r.Header {
|
out <- s
|
||||||
s += len(name)
|
|
||||||
for _, value := range values {
|
|
||||||
s += len(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s += len(r.Host)
|
|
||||||
|
|
||||||
// N.B. r.Form and r.MultipartForm are assumed to be included in r.URL.
|
|
||||||
|
|
||||||
if r.ContentLength != -1 {
|
|
||||||
s += int(r.ContentLength)
|
|
||||||
}
|
|
||||||
out <- s
|
|
||||||
close(out)
|
|
||||||
}()
|
|
||||||
|
|
||||||
return out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseWriterDelegator struct {
|
type responseWriterDelegator struct {
|
||||||
|
36
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
36
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
@ -19,11 +19,11 @@ import (
|
|||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const separatorByte byte = 255
|
|
||||||
|
|
||||||
// A Metric models a single sample value with its meta data being exported to
|
// A Metric models a single sample value with its meta data being exported to
|
||||||
// Prometheus. Implementations of Metric in this package are Gauge, Counter,
|
// Prometheus. Implementers of Metric in this package inclued Gauge, Counter,
|
||||||
// Histogram, Summary, and Untyped.
|
// Untyped, and Summary. Users can implement their own Metric types, but that
|
||||||
|
// should be rarely needed. See the example for SelfCollector, which is also an
|
||||||
|
// example for a user-implemented Metric.
|
||||||
type Metric interface {
|
type Metric interface {
|
||||||
// Desc returns the descriptor for the Metric. This method idempotently
|
// Desc returns the descriptor for the Metric. This method idempotently
|
||||||
// returns the same descriptor throughout the lifetime of the
|
// returns the same descriptor throughout the lifetime of the
|
||||||
@ -34,23 +34,21 @@ type Metric interface {
|
|||||||
// Write encodes the Metric into a "Metric" Protocol Buffer data
|
// Write encodes the Metric into a "Metric" Protocol Buffer data
|
||||||
// transmission object.
|
// transmission object.
|
||||||
//
|
//
|
||||||
// Metric implementations must observe concurrency safety as reads of
|
// Implementers of custom Metric types must observe concurrency safety
|
||||||
// this metric may occur at any time, and any blocking occurs at the
|
// as reads of this metric may occur at any time, and any blocking
|
||||||
// expense of total performance of rendering all registered
|
// occurs at the expense of total performance of rendering all
|
||||||
// metrics. Ideally, Metric implementations should support concurrent
|
// registered metrics. Ideally Metric implementations should support
|
||||||
// readers.
|
// concurrent readers.
|
||||||
//
|
//
|
||||||
// While populating dto.Metric, it is the responsibility of the
|
// The Prometheus client library attempts to minimize memory allocations
|
||||||
// implementation to ensure validity of the Metric protobuf (like valid
|
// and will provide a pre-existing reset dto.Metric pointer. Prometheus
|
||||||
// UTF-8 strings or syntactically valid metric and label names). It is
|
// may recycle the dto.Metric proto message, so Metric implementations
|
||||||
// recommended to sort labels lexicographically. (Implementers may find
|
// should just populate the provided dto.Metric and then should not keep
|
||||||
// LabelPairSorter useful for that.) Callers of Write should still make
|
// any reference to it.
|
||||||
// sure of sorting if they depend on it.
|
//
|
||||||
|
// While populating dto.Metric, labels must be sorted lexicographically.
|
||||||
|
// (Implementers may find LabelPairSorter useful for that.)
|
||||||
Write(*dto.Metric) error
|
Write(*dto.Metric) error
|
||||||
// TODO(beorn7): The original rationale of passing in a pre-allocated
|
|
||||||
// dto.Metric protobuf to save allocations has disappeared. The
|
|
||||||
// signature of this method should be changed to "Write() (*dto.Metric,
|
|
||||||
// error)".
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opts bundles the options for creating most Metric types. Each metric
|
// Opts bundles the options for creating most Metric types. Each metric
|
||||||
|
4
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
4
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
@ -28,7 +28,7 @@ type processCollector struct {
|
|||||||
// NewProcessCollector returns a collector which exports the current state of
|
// NewProcessCollector returns a collector which exports the current state of
|
||||||
// process metrics including cpu, memory and file descriptor usage as well as
|
// process metrics including cpu, memory and file descriptor usage as well as
|
||||||
// the process start time for the given process id under the given namespace.
|
// the process start time for the given process id under the given namespace.
|
||||||
func NewProcessCollector(pid int, namespace string) Collector {
|
func NewProcessCollector(pid int, namespace string) *processCollector {
|
||||||
return NewProcessCollectorPIDFn(
|
return NewProcessCollectorPIDFn(
|
||||||
func() (int, error) { return pid, nil },
|
func() (int, error) { return pid, nil },
|
||||||
namespace,
|
namespace,
|
||||||
@ -43,7 +43,7 @@ func NewProcessCollector(pid int, namespace string) Collector {
|
|||||||
func NewProcessCollectorPIDFn(
|
func NewProcessCollectorPIDFn(
|
||||||
pidFn func() (int, error),
|
pidFn func() (int, error),
|
||||||
namespace string,
|
namespace string,
|
||||||
) Collector {
|
) *processCollector {
|
||||||
c := processCollector{
|
c := processCollector{
|
||||||
pidFn: pidFn,
|
pidFn: pidFn,
|
||||||
collectFn: func(chan<- Metric) {},
|
collectFn: func(chan<- Metric) {},
|
||||||
|
65
vendor/github.com/prometheus/client_golang/prometheus/push.go
generated
vendored
Normal file
65
vendor/github.com/prometheus/client_golang/prometheus/push.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// Copyright (c) 2013, The Prometheus Authors
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be found
|
||||||
|
// in the LICENSE file.
|
||||||
|
|
||||||
|
package prometheus
|
||||||
|
|
||||||
|
// Push triggers a metric collection by the default registry and pushes all
|
||||||
|
// collected metrics to the Pushgateway specified by addr. See the Pushgateway
|
||||||
|
// documentation for detailed implications of the job and instance
|
||||||
|
// parameter. instance can be left empty. You can use just host:port or ip:port
|
||||||
|
// as url, in which case 'http://' is added automatically. You can also include
|
||||||
|
// the schema in the URL. However, do not include the '/metrics/jobs/...' part.
|
||||||
|
//
|
||||||
|
// Note that all previously pushed metrics with the same job and instance will
|
||||||
|
// be replaced with the metrics pushed by this call. (It uses HTTP method 'PUT'
|
||||||
|
// to push to the Pushgateway.)
|
||||||
|
func Push(job, instance, url string) error {
|
||||||
|
return defRegistry.Push(job, instance, url, "PUT")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushAdd works like Push, but only previously pushed metrics with the same
|
||||||
|
// name (and the same job and instance) will be replaced. (It uses HTTP method
|
||||||
|
// 'POST' to push to the Pushgateway.)
|
||||||
|
func PushAdd(job, instance, url string) error {
|
||||||
|
return defRegistry.Push(job, instance, url, "POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushCollectors works like Push, but it does not collect from the default
|
||||||
|
// registry. Instead, it collects from the provided collectors. It is a
|
||||||
|
// convenient way to push only a few metrics.
|
||||||
|
func PushCollectors(job, instance, url string, collectors ...Collector) error {
|
||||||
|
return pushCollectors(job, instance, url, "PUT", collectors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushAddCollectors works like PushAdd, but it does not collect from the
|
||||||
|
// default registry. Instead, it collects from the provided collectors. It is a
|
||||||
|
// convenient way to push only a few metrics.
|
||||||
|
func PushAddCollectors(job, instance, url string, collectors ...Collector) error {
|
||||||
|
return pushCollectors(job, instance, url, "POST", collectors...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushCollectors(job, instance, url, method string, collectors ...Collector) error {
|
||||||
|
r := newRegistry()
|
||||||
|
for _, collector := range collectors {
|
||||||
|
if _, err := r.Register(collector); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r.Push(job, instance, url, method)
|
||||||
|
}
|
1014
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
1014
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
File diff suppressed because it is too large
Load Diff
46
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
46
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
@ -15,6 +15,7 @@ package prometheus
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
@ -24,11 +25,9 @@ import (
|
|||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
|
||||||
|
|
||||||
// quantileLabel is used for the label that defines the quantile in a
|
"github.com/prometheus/client_golang/model"
|
||||||
// summary.
|
)
|
||||||
const quantileLabel = "quantile"
|
|
||||||
|
|
||||||
// A Summary captures individual observations from an event or sample stream and
|
// A Summary captures individual observations from an event or sample stream and
|
||||||
// summarizes them in a manner similar to traditional summary statistics: 1. sum
|
// summarizes them in a manner similar to traditional summary statistics: 1. sum
|
||||||
@ -53,12 +52,12 @@ type Summary interface {
|
|||||||
Observe(float64)
|
Observe(float64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefObjectives are the default Summary quantile values.
|
|
||||||
var (
|
var (
|
||||||
|
// DefObjectives are the default Summary quantile values.
|
||||||
DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
|
DefObjectives = map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}
|
||||||
|
|
||||||
errQuantileLabelNotAllowed = fmt.Errorf(
|
errQuantileLabelNotAllowed = fmt.Errorf(
|
||||||
"%q is not allowed as label name in summaries", quantileLabel,
|
"%q is not allowed as label name in summaries", model.QuantileLabel,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -113,9 +112,7 @@ type SummaryOpts struct {
|
|||||||
ConstLabels Labels
|
ConstLabels Labels
|
||||||
|
|
||||||
// Objectives defines the quantile rank estimates with their respective
|
// Objectives defines the quantile rank estimates with their respective
|
||||||
// absolute error. If Objectives[q] = e, then the value reported
|
// absolute error. The default value is DefObjectives.
|
||||||
// for q will be the φ-quantile value for some φ between q-e and q+e.
|
|
||||||
// The default value is DefObjectives.
|
|
||||||
Objectives map[float64]float64
|
Objectives map[float64]float64
|
||||||
|
|
||||||
// MaxAge defines the duration for which an observation stays relevant
|
// MaxAge defines the duration for which an observation stays relevant
|
||||||
@ -139,11 +136,11 @@ type SummaryOpts struct {
|
|||||||
BufCap uint32
|
BufCap uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Great fuck-up with the sliding-window decay algorithm... The Merge method of
|
// TODO: Great fuck-up with the sliding-window decay algorithm... The Merge
|
||||||
// perk/quantile is actually not working as advertised - and it might be
|
// method of perk/quantile is actually not working as advertised - and it might
|
||||||
// unfixable, as the underlying algorithm is apparently not capable of merging
|
// be unfixable, as the underlying algorithm is apparently not capable of
|
||||||
// summaries in the first place. To avoid using Merge, we are currently adding
|
// merging summaries in the first place. To avoid using Merge, we are currently
|
||||||
// observations to _each_ age bucket, i.e. the effort to add a sample is
|
// adding observations to _each_ age bucket, i.e. the effort to add a sample is
|
||||||
// essentially multiplied by the number of age buckets. When rotating age
|
// essentially multiplied by the number of age buckets. When rotating age
|
||||||
// buckets, we empty the previous head stream. On scrape time, we simply take
|
// buckets, we empty the previous head stream. On scrape time, we simply take
|
||||||
// the quantiles from the head stream (no merging required). Result: More effort
|
// the quantiles from the head stream (no merging required). Result: More effort
|
||||||
@ -173,12 +170,12 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, n := range desc.variableLabels {
|
for _, n := range desc.variableLabels {
|
||||||
if n == quantileLabel {
|
if n == model.QuantileLabel {
|
||||||
panic(errQuantileLabelNotAllowed)
|
panic(errQuantileLabelNotAllowed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, lp := range desc.constLabelPairs {
|
for _, lp := range desc.constLabelPairs {
|
||||||
if lp.GetName() == quantileLabel {
|
if lp.GetName() == model.QuantileLabel {
|
||||||
panic(errQuantileLabelNotAllowed)
|
panic(errQuantileLabelNotAllowed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,12 +224,12 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
|||||||
}
|
}
|
||||||
sort.Float64s(s.sortedObjectives)
|
sort.Float64s(s.sortedObjectives)
|
||||||
|
|
||||||
s.init(s) // Init self-collection.
|
s.Init(s) // Init self-collection.
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
type summary struct {
|
type summary struct {
|
||||||
selfCollector
|
SelfCollector
|
||||||
|
|
||||||
bufMtx sync.Mutex // Protects hotBuf and hotBufExpTime.
|
bufMtx sync.Mutex // Protects hotBuf and hotBufExpTime.
|
||||||
mtx sync.Mutex // Protects every other moving part.
|
mtx sync.Mutex // Protects every other moving part.
|
||||||
@ -390,7 +387,7 @@ func (s quantSort) Less(i, j int) bool {
|
|||||||
// (e.g. HTTP request latencies, partitioned by status code and method). Create
|
// (e.g. HTTP request latencies, partitioned by status code and method). Create
|
||||||
// instances with NewSummaryVec.
|
// instances with NewSummaryVec.
|
||||||
type SummaryVec struct {
|
type SummaryVec struct {
|
||||||
*MetricVec
|
MetricVec
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
|
// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
|
||||||
@ -404,9 +401,14 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
|||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &SummaryVec{
|
return &SummaryVec{
|
||||||
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
MetricVec: MetricVec{
|
||||||
return newSummary(desc, opts, lvs...)
|
children: map[uint64]Metric{},
|
||||||
}),
|
desc: desc,
|
||||||
|
hash: fnv.New64a(),
|
||||||
|
newMetric: func(lvs ...string) Metric {
|
||||||
|
return newSummary(desc, opts, lvs...)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
vendor/github.com/prometheus/client_golang/prometheus/untyped.go
generated
vendored
15
vendor/github.com/prometheus/client_golang/prometheus/untyped.go
generated
vendored
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
|
import "hash/fnv"
|
||||||
|
|
||||||
// Untyped is a Metric that represents a single numerical value that can
|
// Untyped is a Metric that represents a single numerical value that can
|
||||||
// arbitrarily go up and down.
|
// arbitrarily go up and down.
|
||||||
//
|
//
|
||||||
@ -56,7 +58,7 @@ func NewUntyped(opts UntypedOpts) Untyped {
|
|||||||
// labels. This is used if you want to count the same thing partitioned by
|
// labels. This is used if you want to count the same thing partitioned by
|
||||||
// various dimensions. Create instances with NewUntypedVec.
|
// various dimensions. Create instances with NewUntypedVec.
|
||||||
type UntypedVec struct {
|
type UntypedVec struct {
|
||||||
*MetricVec
|
MetricVec
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUntypedVec creates a new UntypedVec based on the provided UntypedOpts and
|
// NewUntypedVec creates a new UntypedVec based on the provided UntypedOpts and
|
||||||
@ -70,9 +72,14 @@ func NewUntypedVec(opts UntypedOpts, labelNames []string) *UntypedVec {
|
|||||||
opts.ConstLabels,
|
opts.ConstLabels,
|
||||||
)
|
)
|
||||||
return &UntypedVec{
|
return &UntypedVec{
|
||||||
MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
MetricVec: MetricVec{
|
||||||
return newValue(desc, UntypedValue, 0, lvs...)
|
children: map[uint64]Metric{},
|
||||||
}),
|
desc: desc,
|
||||||
|
hash: fnv.New64a(),
|
||||||
|
newMetric: func(lvs ...string) Metric {
|
||||||
|
return newValue(desc, UntypedValue, 0, lvs...)
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
8
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
8
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
@ -48,7 +48,7 @@ type value struct {
|
|||||||
// operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
// operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
|
||||||
valBits uint64
|
valBits uint64
|
||||||
|
|
||||||
selfCollector
|
SelfCollector
|
||||||
|
|
||||||
desc *Desc
|
desc *Desc
|
||||||
valType ValueType
|
valType ValueType
|
||||||
@ -68,7 +68,7 @@ func newValue(desc *Desc, valueType ValueType, val float64, labelValues ...strin
|
|||||||
valBits: math.Float64bits(val),
|
valBits: math.Float64bits(val),
|
||||||
labelPairs: makeLabelPairs(desc, labelValues),
|
labelPairs: makeLabelPairs(desc, labelValues),
|
||||||
}
|
}
|
||||||
result.init(result)
|
result.Init(result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ func (v *value) Write(out *dto.Metric) error {
|
|||||||
// library to back the implementations of CounterFunc, GaugeFunc, and
|
// library to back the implementations of CounterFunc, GaugeFunc, and
|
||||||
// UntypedFunc.
|
// UntypedFunc.
|
||||||
type valueFunc struct {
|
type valueFunc struct {
|
||||||
selfCollector
|
SelfCollector
|
||||||
|
|
||||||
desc *Desc
|
desc *Desc
|
||||||
valType ValueType
|
valType ValueType
|
||||||
@ -134,7 +134,7 @@ func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *val
|
|||||||
function: function,
|
function: function,
|
||||||
labelPairs: makeLabelPairs(desc, nil),
|
labelPairs: makeLabelPairs(desc, nil),
|
||||||
}
|
}
|
||||||
result.init(result)
|
result.Init(result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
253
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
253
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
@ -14,10 +14,10 @@
|
|||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/prometheus/common/model"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MetricVec is a Collector to bundle metrics of the same name that
|
// MetricVec is a Collector to bundle metrics of the same name that
|
||||||
@ -26,32 +26,17 @@ import (
|
|||||||
// type. GaugeVec, CounterVec, SummaryVec, and UntypedVec are examples already
|
// type. GaugeVec, CounterVec, SummaryVec, and UntypedVec are examples already
|
||||||
// provided in this package.
|
// provided in this package.
|
||||||
type MetricVec struct {
|
type MetricVec struct {
|
||||||
mtx sync.RWMutex // Protects the children.
|
mtx sync.RWMutex // Protects not only children, but also hash and buf.
|
||||||
children map[uint64][]metricWithLabelValues
|
children map[uint64]Metric
|
||||||
desc *Desc
|
desc *Desc
|
||||||
|
|
||||||
newMetric func(labelValues ...string) Metric
|
// hash is our own hash instance to avoid repeated allocations.
|
||||||
hashAdd func(h uint64, s string) uint64 // replace hash function for testing collision handling
|
hash hash.Hash64
|
||||||
hashAddByte func(h uint64, b byte) uint64
|
// buf is used to copy string contents into it for hashing,
|
||||||
}
|
// again to avoid allocations.
|
||||||
|
buf bytes.Buffer
|
||||||
|
|
||||||
// newMetricVec returns an initialized MetricVec. The concrete value is
|
newMetric func(labelValues ...string) Metric
|
||||||
// returned for embedding into another struct.
|
|
||||||
func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
|
|
||||||
return &MetricVec{
|
|
||||||
children: map[uint64][]metricWithLabelValues{},
|
|
||||||
desc: desc,
|
|
||||||
newMetric: newMetric,
|
|
||||||
hashAdd: hashAdd,
|
|
||||||
hashAddByte: hashAddByte,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// metricWithLabelValues provides the metric and its label values for
|
|
||||||
// disambiguation on hash collision.
|
|
||||||
type metricWithLabelValues struct {
|
|
||||||
values []string
|
|
||||||
metric Metric
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Describe implements Collector. The length of the returned slice
|
// Describe implements Collector. The length of the returned slice
|
||||||
@ -65,10 +50,8 @@ func (m *MetricVec) Collect(ch chan<- Metric) {
|
|||||||
m.mtx.RLock()
|
m.mtx.RLock()
|
||||||
defer m.mtx.RUnlock()
|
defer m.mtx.RUnlock()
|
||||||
|
|
||||||
for _, metrics := range m.children {
|
for _, metric := range m.children {
|
||||||
for _, metric := range metrics {
|
ch <- metric
|
||||||
ch <- metric.metric
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,12 +80,14 @@ func (m *MetricVec) Collect(ch chan<- Metric) {
|
|||||||
// with a performance overhead (for creating and processing the Labels map).
|
// with a performance overhead (for creating and processing the Labels map).
|
||||||
// See also the GaugeVec example.
|
// See also the GaugeVec example.
|
||||||
func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
|
func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
|
||||||
|
m.mtx.Lock()
|
||||||
|
defer m.mtx.Unlock()
|
||||||
|
|
||||||
h, err := m.hashLabelValues(lvs)
|
h, err := m.hashLabelValues(lvs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return m.getOrCreateMetric(h, lvs...), nil
|
||||||
return m.getOrCreateMetricWithLabelValues(h, lvs), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMetricWith returns the Metric for the given Labels map (the label names
|
// GetMetricWith returns the Metric for the given Labels map (the label names
|
||||||
@ -118,12 +103,18 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
|
|||||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||||
// methods.
|
// methods.
|
||||||
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
|
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
|
||||||
|
m.mtx.Lock()
|
||||||
|
defer m.mtx.Unlock()
|
||||||
|
|
||||||
h, err := m.hashLabels(labels)
|
h, err := m.hashLabels(labels)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
lvs := make([]string, len(labels))
|
||||||
return m.getOrCreateMetricWithLabels(h, labels), nil
|
for i, label := range m.desc.variableLabels {
|
||||||
|
lvs[i] = labels[label]
|
||||||
|
}
|
||||||
|
return m.getOrCreateMetric(h, lvs...), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithLabelValues works as GetMetricWithLabelValues, but panics if an error
|
// WithLabelValues works as GetMetricWithLabelValues, but panics if an error
|
||||||
@ -171,7 +162,11 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return m.deleteByHashWithLabelValues(h, lvs)
|
if _, has := m.children[h]; !has {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
delete(m.children, h)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes the metric where the variable labels are the same as those
|
// Delete deletes the metric where the variable labels are the same as those
|
||||||
@ -192,50 +187,10 @@ func (m *MetricVec) Delete(labels Labels) bool {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if _, has := m.children[h]; !has {
|
||||||
return m.deleteByHashWithLabels(h, labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteByHashWithLabelValues removes the metric from the hash bucket h. If
|
|
||||||
// there are multiple matches in the bucket, use lvs to select a metric and
|
|
||||||
// remove only that metric.
|
|
||||||
func (m *MetricVec) deleteByHashWithLabelValues(h uint64, lvs []string) bool {
|
|
||||||
metrics, ok := m.children[h]
|
|
||||||
if !ok {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
delete(m.children, h)
|
||||||
i := m.findMetricWithLabelValues(metrics, lvs)
|
|
||||||
if i >= len(metrics) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(metrics) > 1 {
|
|
||||||
m.children[h] = append(metrics[:i], metrics[i+1:]...)
|
|
||||||
} else {
|
|
||||||
delete(m.children, h)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// deleteByHashWithLabels removes the metric from the hash bucket h. If there
|
|
||||||
// are multiple matches in the bucket, use lvs to select a metric and remove
|
|
||||||
// only that metric.
|
|
||||||
func (m *MetricVec) deleteByHashWithLabels(h uint64, labels Labels) bool {
|
|
||||||
metrics, ok := m.children[h]
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
i := m.findMetricWithLabels(metrics, labels)
|
|
||||||
if i >= len(metrics) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(metrics) > 1 {
|
|
||||||
m.children[h] = append(metrics[:i], metrics[i+1:]...)
|
|
||||||
} else {
|
|
||||||
delete(m.children, h)
|
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,152 +208,40 @@ func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
|
|||||||
if len(vals) != len(m.desc.variableLabels) {
|
if len(vals) != len(m.desc.variableLabels) {
|
||||||
return 0, errInconsistentCardinality
|
return 0, errInconsistentCardinality
|
||||||
}
|
}
|
||||||
h := hashNew()
|
m.hash.Reset()
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
h = m.hashAdd(h, val)
|
m.buf.Reset()
|
||||||
h = m.hashAddByte(h, model.SeparatorByte)
|
m.buf.WriteString(val)
|
||||||
|
m.hash.Write(m.buf.Bytes())
|
||||||
}
|
}
|
||||||
return h, nil
|
return m.hash.Sum64(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
|
func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
|
||||||
if len(labels) != len(m.desc.variableLabels) {
|
if len(labels) != len(m.desc.variableLabels) {
|
||||||
return 0, errInconsistentCardinality
|
return 0, errInconsistentCardinality
|
||||||
}
|
}
|
||||||
h := hashNew()
|
m.hash.Reset()
|
||||||
for _, label := range m.desc.variableLabels {
|
for _, label := range m.desc.variableLabels {
|
||||||
val, ok := labels[label]
|
val, ok := labels[label]
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, fmt.Errorf("label name %q missing in label map", label)
|
return 0, fmt.Errorf("label name %q missing in label map", label)
|
||||||
}
|
}
|
||||||
h = m.hashAdd(h, val)
|
m.buf.Reset()
|
||||||
h = m.hashAddByte(h, model.SeparatorByte)
|
m.buf.WriteString(val)
|
||||||
|
m.hash.Write(m.buf.Bytes())
|
||||||
}
|
}
|
||||||
return h, nil
|
return m.hash.Sum64(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
|
func (m *MetricVec) getOrCreateMetric(hash uint64, labelValues ...string) Metric {
|
||||||
// or creates it and returns the new one.
|
metric, ok := m.children[hash]
|
||||||
//
|
|
||||||
// This function holds the mutex.
|
|
||||||
func (m *MetricVec) getOrCreateMetricWithLabelValues(hash uint64, lvs []string) Metric {
|
|
||||||
m.mtx.RLock()
|
|
||||||
metric, ok := m.getMetricWithLabelValues(hash, lvs)
|
|
||||||
m.mtx.RUnlock()
|
|
||||||
if ok {
|
|
||||||
return metric
|
|
||||||
}
|
|
||||||
|
|
||||||
m.mtx.Lock()
|
|
||||||
defer m.mtx.Unlock()
|
|
||||||
metric, ok = m.getMetricWithLabelValues(hash, lvs)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
// Copy to avoid allocation in case wo don't go down this code path.
|
// Copy labelValues. Otherwise, they would be allocated even if we don't go
|
||||||
copiedLVs := make([]string, len(lvs))
|
// down this code path.
|
||||||
copy(copiedLVs, lvs)
|
copiedLabelValues := append(make([]string, 0, len(labelValues)), labelValues...)
|
||||||
metric = m.newMetric(copiedLVs...)
|
metric = m.newMetric(copiedLabelValues...)
|
||||||
m.children[hash] = append(m.children[hash], metricWithLabelValues{values: copiedLVs, metric: metric})
|
m.children[hash] = metric
|
||||||
}
|
}
|
||||||
return metric
|
return metric
|
||||||
}
|
}
|
||||||
|
|
||||||
// getOrCreateMetricWithLabelValues retrieves the metric by hash and label value
|
|
||||||
// or creates it and returns the new one.
|
|
||||||
//
|
|
||||||
// This function holds the mutex.
|
|
||||||
func (m *MetricVec) getOrCreateMetricWithLabels(hash uint64, labels Labels) Metric {
|
|
||||||
m.mtx.RLock()
|
|
||||||
metric, ok := m.getMetricWithLabels(hash, labels)
|
|
||||||
m.mtx.RUnlock()
|
|
||||||
if ok {
|
|
||||||
return metric
|
|
||||||
}
|
|
||||||
|
|
||||||
m.mtx.Lock()
|
|
||||||
defer m.mtx.Unlock()
|
|
||||||
metric, ok = m.getMetricWithLabels(hash, labels)
|
|
||||||
if !ok {
|
|
||||||
lvs := m.extractLabelValues(labels)
|
|
||||||
metric = m.newMetric(lvs...)
|
|
||||||
m.children[hash] = append(m.children[hash], metricWithLabelValues{values: lvs, metric: metric})
|
|
||||||
}
|
|
||||||
return metric
|
|
||||||
}
|
|
||||||
|
|
||||||
// getMetricWithLabelValues gets a metric while handling possible collisions in
|
|
||||||
// the hash space. Must be called while holding read mutex.
|
|
||||||
func (m *MetricVec) getMetricWithLabelValues(h uint64, lvs []string) (Metric, bool) {
|
|
||||||
metrics, ok := m.children[h]
|
|
||||||
if ok {
|
|
||||||
if i := m.findMetricWithLabelValues(metrics, lvs); i < len(metrics) {
|
|
||||||
return metrics[i].metric, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// getMetricWithLabels gets a metric while handling possible collisions in
|
|
||||||
// the hash space. Must be called while holding read mutex.
|
|
||||||
func (m *MetricVec) getMetricWithLabels(h uint64, labels Labels) (Metric, bool) {
|
|
||||||
metrics, ok := m.children[h]
|
|
||||||
if ok {
|
|
||||||
if i := m.findMetricWithLabels(metrics, labels); i < len(metrics) {
|
|
||||||
return metrics[i].metric, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// findMetricWithLabelValues returns the index of the matching metric or
|
|
||||||
// len(metrics) if not found.
|
|
||||||
func (m *MetricVec) findMetricWithLabelValues(metrics []metricWithLabelValues, lvs []string) int {
|
|
||||||
for i, metric := range metrics {
|
|
||||||
if m.matchLabelValues(metric.values, lvs) {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len(metrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
// findMetricWithLabels returns the index of the matching metric or len(metrics)
|
|
||||||
// if not found.
|
|
||||||
func (m *MetricVec) findMetricWithLabels(metrics []metricWithLabelValues, labels Labels) int {
|
|
||||||
for i, metric := range metrics {
|
|
||||||
if m.matchLabels(metric.values, labels) {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return len(metrics)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MetricVec) matchLabelValues(values []string, lvs []string) bool {
|
|
||||||
if len(values) != len(lvs) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, v := range values {
|
|
||||||
if v != lvs[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MetricVec) matchLabels(values []string, labels Labels) bool {
|
|
||||||
if len(labels) != len(values) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i, k := range m.desc.variableLabels {
|
|
||||||
if values[i] != labels[k] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MetricVec) extractLabelValues(labels Labels) []string {
|
|
||||||
labelValues := make([]string, len(labels))
|
|
||||||
for i, k := range m.desc.variableLabels {
|
|
||||||
labelValues[i] = labels[k]
|
|
||||||
}
|
|
||||||
return labelValues
|
|
||||||
}
|
|
||||||
|
315
vendor/github.com/prometheus/client_golang/text/create.go
generated
vendored
Normal file
315
vendor/github.com/prometheus/client_golang/text/create.go
generated
vendored
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
// 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 text contains helper functions to parse and create text-based
|
||||||
|
// exchange formats. The package currently supports (only) version 0.0.4 of the
|
||||||
|
// exchange format. Should other versions be supported in the future, some
|
||||||
|
// versioning scheme has to be applied. Possibilities include separate packages
|
||||||
|
// or separate functions. The best way depends on the nature of future changes,
|
||||||
|
// which is the reason why no versioning scheme has been applied prematurely
|
||||||
|
// here.
|
||||||
|
package text
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/model"
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MetricFamilyToText converts a MetricFamily proto message into text format and
|
||||||
|
// writes the resulting lines to 'out'. It returns the number of bytes written
|
||||||
|
// and any error encountered. This function does not perform checks on the
|
||||||
|
// content of the metric and label names, i.e. invalid metric or label names
|
||||||
|
// will result in invalid text format output.
|
||||||
|
// This method fulfills the type 'prometheus.encoder'.
|
||||||
|
func MetricFamilyToText(out io.Writer, in *dto.MetricFamily) (int, error) {
|
||||||
|
var written int
|
||||||
|
|
||||||
|
// Fail-fast checks.
|
||||||
|
if len(in.Metric) == 0 {
|
||||||
|
return written, fmt.Errorf("MetricFamily has no metrics: %s", in)
|
||||||
|
}
|
||||||
|
name := in.GetName()
|
||||||
|
if name == "" {
|
||||||
|
return written, fmt.Errorf("MetricFamily has no name: %s", in)
|
||||||
|
}
|
||||||
|
if in.Type == nil {
|
||||||
|
return written, fmt.Errorf("MetricFamily has no type: %s", in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comments, first HELP, then TYPE.
|
||||||
|
if in.Help != nil {
|
||||||
|
n, err := fmt.Fprintf(
|
||||||
|
out, "# HELP %s %s\n",
|
||||||
|
name, escapeString(*in.Help, false),
|
||||||
|
)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metricType := in.GetType()
|
||||||
|
n, err := fmt.Fprintf(
|
||||||
|
out, "# TYPE %s %s\n",
|
||||||
|
name, strings.ToLower(metricType.String()),
|
||||||
|
)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally the samples, one line for each.
|
||||||
|
for _, metric := range in.Metric {
|
||||||
|
switch metricType {
|
||||||
|
case dto.MetricType_COUNTER:
|
||||||
|
if metric.Counter == nil {
|
||||||
|
return written, fmt.Errorf(
|
||||||
|
"expected counter in metric %s %s", name, metric,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
n, err = writeSample(
|
||||||
|
name, metric, "", "",
|
||||||
|
metric.Counter.GetValue(),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
case dto.MetricType_GAUGE:
|
||||||
|
if metric.Gauge == nil {
|
||||||
|
return written, fmt.Errorf(
|
||||||
|
"expected gauge in metric %s %s", name, metric,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
n, err = writeSample(
|
||||||
|
name, metric, "", "",
|
||||||
|
metric.Gauge.GetValue(),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
case dto.MetricType_UNTYPED:
|
||||||
|
if metric.Untyped == nil {
|
||||||
|
return written, fmt.Errorf(
|
||||||
|
"expected untyped in metric %s %s", name, metric,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
n, err = writeSample(
|
||||||
|
name, metric, "", "",
|
||||||
|
metric.Untyped.GetValue(),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
case dto.MetricType_SUMMARY:
|
||||||
|
if metric.Summary == nil {
|
||||||
|
return written, fmt.Errorf(
|
||||||
|
"expected summary in metric %s %s", name, metric,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for _, q := range metric.Summary.Quantile {
|
||||||
|
n, err = writeSample(
|
||||||
|
name, metric,
|
||||||
|
model.QuantileLabel, fmt.Sprint(q.GetQuantile()),
|
||||||
|
q.GetValue(),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n, err = writeSample(
|
||||||
|
name+"_sum", metric, "", "",
|
||||||
|
metric.Summary.GetSampleSum(),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
written += n
|
||||||
|
n, err = writeSample(
|
||||||
|
name+"_count", metric, "", "",
|
||||||
|
float64(metric.Summary.GetSampleCount()),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
case dto.MetricType_HISTOGRAM:
|
||||||
|
if metric.Histogram == nil {
|
||||||
|
return written, fmt.Errorf(
|
||||||
|
"expected histogram in metric %s %s", name, metric,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
infSeen := false
|
||||||
|
for _, q := range metric.Histogram.Bucket {
|
||||||
|
n, err = writeSample(
|
||||||
|
name+"_bucket", metric,
|
||||||
|
model.BucketLabel, fmt.Sprint(q.GetUpperBound()),
|
||||||
|
float64(q.GetCumulativeCount()),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
if math.IsInf(q.GetUpperBound(), +1) {
|
||||||
|
infSeen = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !infSeen {
|
||||||
|
n, err = writeSample(
|
||||||
|
name+"_bucket", metric,
|
||||||
|
model.BucketLabel, "+Inf",
|
||||||
|
float64(metric.Histogram.GetSampleCount()),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
written += n
|
||||||
|
}
|
||||||
|
n, err = writeSample(
|
||||||
|
name+"_sum", metric, "", "",
|
||||||
|
metric.Histogram.GetSampleSum(),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
written += n
|
||||||
|
n, err = writeSample(
|
||||||
|
name+"_count", metric, "", "",
|
||||||
|
float64(metric.Histogram.GetSampleCount()),
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
return written, fmt.Errorf(
|
||||||
|
"unexpected type in metric %s %s", name, metric,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return written, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeSample writes a single sample in text format to out, given the metric
|
||||||
|
// name, the metric proto message itself, optionally an additional label name
|
||||||
|
// and value (use empty strings if not required), and the value. The function
|
||||||
|
// returns the number of bytes written and any error encountered.
|
||||||
|
func writeSample(
|
||||||
|
name string,
|
||||||
|
metric *dto.Metric,
|
||||||
|
additionalLabelName, additionalLabelValue string,
|
||||||
|
value float64,
|
||||||
|
out io.Writer,
|
||||||
|
) (int, error) {
|
||||||
|
var written int
|
||||||
|
n, err := fmt.Fprint(out, name)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
n, err = labelPairsToText(
|
||||||
|
metric.Label,
|
||||||
|
additionalLabelName, additionalLabelValue,
|
||||||
|
out,
|
||||||
|
)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
n, err = fmt.Fprintf(out, " %v", value)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
if metric.TimestampMs != nil {
|
||||||
|
n, err = fmt.Fprintf(out, " %v", *metric.TimestampMs)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n, err = out.Write([]byte{'\n'})
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
return written, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// labelPairsToText converts a slice of LabelPair proto messages plus the
|
||||||
|
// explicitly given additional label pair into text formatted as required by the
|
||||||
|
// text format and writes it to 'out'. An empty slice in combination with an
|
||||||
|
// empty string 'additionalLabelName' results in nothing being
|
||||||
|
// written. Otherwise, the label pairs are written, escaped as required by the
|
||||||
|
// text format, and enclosed in '{...}'. The function returns the number of
|
||||||
|
// bytes written and any error encountered.
|
||||||
|
func labelPairsToText(
|
||||||
|
in []*dto.LabelPair,
|
||||||
|
additionalLabelName, additionalLabelValue string,
|
||||||
|
out io.Writer,
|
||||||
|
) (int, error) {
|
||||||
|
if len(in) == 0 && additionalLabelName == "" {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
var written int
|
||||||
|
separator := '{'
|
||||||
|
for _, lp := range in {
|
||||||
|
n, err := fmt.Fprintf(
|
||||||
|
out, `%c%s="%s"`,
|
||||||
|
separator, lp.GetName(), escapeString(lp.GetValue(), true),
|
||||||
|
)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
separator = ','
|
||||||
|
}
|
||||||
|
if additionalLabelName != "" {
|
||||||
|
n, err := fmt.Fprintf(
|
||||||
|
out, `%c%s="%s"`,
|
||||||
|
separator, additionalLabelName,
|
||||||
|
escapeString(additionalLabelValue, true),
|
||||||
|
)
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n, err := out.Write([]byte{'}'})
|
||||||
|
written += n
|
||||||
|
if err != nil {
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
return written, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// escapeString replaces '\' by '\\', new line character by '\n', and - if
|
||||||
|
// includeDoubleQuote is true - '"' by '\"'.
|
||||||
|
func escapeString(v string, includeDoubleQuote bool) string {
|
||||||
|
result := bytes.NewBuffer(make([]byte, 0, len(v)))
|
||||||
|
for _, c := range v {
|
||||||
|
switch {
|
||||||
|
case c == '\\':
|
||||||
|
result.WriteString(`\\`)
|
||||||
|
case includeDoubleQuote && c == '"':
|
||||||
|
result.WriteString(`\"`)
|
||||||
|
case c == '\n':
|
||||||
|
result.WriteString(`\n`)
|
||||||
|
default:
|
||||||
|
result.WriteRune(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.String()
|
||||||
|
}
|
746
vendor/github.com/prometheus/client_golang/text/parse.go
generated
vendored
Normal file
746
vendor/github.com/prometheus/client_golang/text/parse.go
generated
vendored
Normal file
@ -0,0 +1,746 @@
|
|||||||
|
// 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 text
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/prometheus/client_golang/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A stateFn is a function that represents a state in a state machine. By
|
||||||
|
// executing it, the state is progressed to the next state. The stateFn returns
|
||||||
|
// another stateFn, which represents the new state. The end state is represented
|
||||||
|
// by nil.
|
||||||
|
type stateFn func() stateFn
|
||||||
|
|
||||||
|
// ParseError signals errors while parsing the simple and flat text-based
|
||||||
|
// exchange format.
|
||||||
|
type ParseError struct {
|
||||||
|
Line int
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements the error interface.
|
||||||
|
func (e ParseError) Error() string {
|
||||||
|
return fmt.Sprintf("text format parsing error in line %d: %s", e.Line, e.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser is used to parse the simple and flat text-based exchange format. Its
|
||||||
|
// nil value is ready to use.
|
||||||
|
type Parser struct {
|
||||||
|
metricFamiliesByName map[string]*dto.MetricFamily
|
||||||
|
buf *bufio.Reader // Where the parsed input is read through.
|
||||||
|
err error // Most recent error.
|
||||||
|
lineCount int // Tracks the line count for error messages.
|
||||||
|
currentByte byte // The most recent byte read.
|
||||||
|
currentToken bytes.Buffer // Re-used each time a token has to be gathered from multiple bytes.
|
||||||
|
currentMF *dto.MetricFamily
|
||||||
|
currentMetric *dto.Metric
|
||||||
|
currentLabelPair *dto.LabelPair
|
||||||
|
|
||||||
|
// The remaining member variables are only used for summaries/histograms.
|
||||||
|
currentLabels map[string]string // All labels including '__name__' but excluding 'quantile'/'le'
|
||||||
|
// Summary specific.
|
||||||
|
summaries map[uint64]*dto.Metric // Key is created with LabelsToSignature.
|
||||||
|
currentQuantile float64
|
||||||
|
// Histogram specific.
|
||||||
|
histograms map[uint64]*dto.Metric // Key is created with LabelsToSignature.
|
||||||
|
currentBucket float64
|
||||||
|
// These tell us if the currently processed line ends on '_count' or
|
||||||
|
// '_sum' respectively and belong to a summary/histogram, representing the sample
|
||||||
|
// count and sum of that summary/histogram.
|
||||||
|
currentIsSummaryCount, currentIsSummarySum bool
|
||||||
|
currentIsHistogramCount, currentIsHistogramSum bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
|
||||||
|
// format and creates MetricFamily proto messages. It returns the MetricFamily
|
||||||
|
// proto messages in a map where the metric names are the keys, along with any
|
||||||
|
// error encountered.
|
||||||
|
//
|
||||||
|
// If the input contains duplicate metrics (i.e. lines with the same metric name
|
||||||
|
// and exactly the same label set), the resulting MetricFamily will contain
|
||||||
|
// duplicate Metric proto messages. Similar is true for duplicate label
|
||||||
|
// names. Checks for duplicates have to be performed separately, if required.
|
||||||
|
// Also note that neither the metrics within each MetricFamily are sorted nor
|
||||||
|
// the label pairs within each Metric. Sorting is not required for the most
|
||||||
|
// frequent use of this method, which is sample ingestion in the Prometheus
|
||||||
|
// server. However, for presentation purposes, you might want to sort the
|
||||||
|
// metrics, and in some cases, you must sort the labels, e.g. for consumption by
|
||||||
|
// the metric family injection hook of the Prometheus registry.
|
||||||
|
//
|
||||||
|
// Summaries and histograms are rather special beasts. You would probably not
|
||||||
|
// use them in the simple text format anyway. This method can deal with
|
||||||
|
// summaries and histograms if they are presented in exactly the way the
|
||||||
|
// text.Create function creates them.
|
||||||
|
//
|
||||||
|
// This method must not be called concurrently. If you want to parse different
|
||||||
|
// input concurrently, instantiate a separate Parser for each goroutine.
|
||||||
|
func (p *Parser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricFamily, error) {
|
||||||
|
p.reset(in)
|
||||||
|
for nextState := p.startOfLine; nextState != nil; nextState = nextState() {
|
||||||
|
// Magic happens here...
|
||||||
|
}
|
||||||
|
// Get rid of empty metric families.
|
||||||
|
for k, mf := range p.metricFamiliesByName {
|
||||||
|
if len(mf.GetMetric()) == 0 {
|
||||||
|
delete(p.metricFamiliesByName, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.metricFamiliesByName, p.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) reset(in io.Reader) {
|
||||||
|
p.metricFamiliesByName = map[string]*dto.MetricFamily{}
|
||||||
|
if p.buf == nil {
|
||||||
|
p.buf = bufio.NewReader(in)
|
||||||
|
} else {
|
||||||
|
p.buf.Reset(in)
|
||||||
|
}
|
||||||
|
p.err = nil
|
||||||
|
p.lineCount = 0
|
||||||
|
if p.summaries == nil || len(p.summaries) > 0 {
|
||||||
|
p.summaries = map[uint64]*dto.Metric{}
|
||||||
|
}
|
||||||
|
if p.histograms == nil || len(p.histograms) > 0 {
|
||||||
|
p.histograms = map[uint64]*dto.Metric{}
|
||||||
|
}
|
||||||
|
p.currentQuantile = math.NaN()
|
||||||
|
p.currentBucket = math.NaN()
|
||||||
|
}
|
||||||
|
|
||||||
|
// startOfLine represents the state where the next byte read from p.buf is the
|
||||||
|
// start of a line (or whitespace leading up to it).
|
||||||
|
func (p *Parser) startOfLine() stateFn {
|
||||||
|
p.lineCount++
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
// End of input reached. This is the only case where
|
||||||
|
// that is not an error but a signal that we are done.
|
||||||
|
p.err = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch p.currentByte {
|
||||||
|
case '#':
|
||||||
|
return p.startComment
|
||||||
|
case '\n':
|
||||||
|
return p.startOfLine // Empty line, start the next one.
|
||||||
|
}
|
||||||
|
return p.readingMetricName
|
||||||
|
}
|
||||||
|
|
||||||
|
// startComment represents the state where the next byte read from p.buf is the
|
||||||
|
// start of a comment (or whitespace leading up to it).
|
||||||
|
func (p *Parser) startComment() stateFn {
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentByte == '\n' {
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
if p.readTokenUntilWhitespace(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
// If we have hit the end of line already, there is nothing left
|
||||||
|
// to do. This is not considered a syntax error.
|
||||||
|
if p.currentByte == '\n' {
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
keyword := p.currentToken.String()
|
||||||
|
if keyword != "HELP" && keyword != "TYPE" {
|
||||||
|
// Generic comment, ignore by fast forwarding to end of line.
|
||||||
|
for p.currentByte != '\n' {
|
||||||
|
if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
// There is something. Next has to be a metric name.
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.readTokenAsMetricName(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentByte == '\n' {
|
||||||
|
// At the end of the line already.
|
||||||
|
// Again, this is not considered a syntax error.
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
if !isBlankOrTab(p.currentByte) {
|
||||||
|
p.parseError("invalid metric name in comment")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.setOrCreateCurrentMF()
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentByte == '\n' {
|
||||||
|
// At the end of the line already.
|
||||||
|
// Again, this is not considered a syntax error.
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
switch keyword {
|
||||||
|
case "HELP":
|
||||||
|
return p.readingHelp
|
||||||
|
case "TYPE":
|
||||||
|
return p.readingType
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("code error: unexpected keyword %q", keyword))
|
||||||
|
}
|
||||||
|
|
||||||
|
// readingMetricName represents the state where the last byte read (now in
|
||||||
|
// p.currentByte) is the first byte of a metric name.
|
||||||
|
func (p *Parser) readingMetricName() stateFn {
|
||||||
|
if p.readTokenAsMetricName(); p.err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if p.currentToken.Len() == 0 {
|
||||||
|
p.parseError("invalid metric name")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.setOrCreateCurrentMF()
|
||||||
|
// Now is the time to fix the type if it hasn't happened yet.
|
||||||
|
if p.currentMF.Type == nil {
|
||||||
|
p.currentMF.Type = dto.MetricType_UNTYPED.Enum()
|
||||||
|
}
|
||||||
|
p.currentMetric = &dto.Metric{}
|
||||||
|
// Do not append the newly created currentMetric to
|
||||||
|
// currentMF.Metric right now. First wait if this is a summary,
|
||||||
|
// and the metric exists already, which we can only know after
|
||||||
|
// having read all the labels.
|
||||||
|
if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
return p.readingLabels
|
||||||
|
}
|
||||||
|
|
||||||
|
// readingLabels represents the state where the last byte read (now in
|
||||||
|
// p.currentByte) is either the first byte of the label set (i.e. a '{'), or the
|
||||||
|
// first byte of the value (otherwise).
|
||||||
|
func (p *Parser) readingLabels() stateFn {
|
||||||
|
// Summaries/histograms are special. We have to reset the
|
||||||
|
// currentLabels map, currentQuantile and currentBucket before starting to
|
||||||
|
// read labels.
|
||||||
|
if p.currentMF.GetType() == dto.MetricType_SUMMARY || p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
|
||||||
|
p.currentLabels = map[string]string{}
|
||||||
|
p.currentLabels[string(model.MetricNameLabel)] = p.currentMF.GetName()
|
||||||
|
p.currentQuantile = math.NaN()
|
||||||
|
p.currentBucket = math.NaN()
|
||||||
|
}
|
||||||
|
if p.currentByte != '{' {
|
||||||
|
return p.readingValue
|
||||||
|
}
|
||||||
|
return p.startLabelName
|
||||||
|
}
|
||||||
|
|
||||||
|
// startLabelName represents the state where the next byte read from p.buf is
|
||||||
|
// the start of a label name (or whitespace leading up to it).
|
||||||
|
func (p *Parser) startLabelName() stateFn {
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentByte == '}' {
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
return p.readingValue
|
||||||
|
}
|
||||||
|
if p.readTokenAsLabelName(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentToken.Len() == 0 {
|
||||||
|
p.parseError(fmt.Sprintf("invalid label name for metric %q", p.currentMF.GetName()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.currentLabelPair = &dto.LabelPair{Name: proto.String(p.currentToken.String())}
|
||||||
|
if p.currentLabelPair.GetName() == string(model.MetricNameLabel) {
|
||||||
|
p.parseError(fmt.Sprintf("label name %q is reserved", model.MetricNameLabel))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Special summary/histogram treatment. Don't add 'quantile' and 'le'
|
||||||
|
// labels to 'real' labels.
|
||||||
|
if !(p.currentMF.GetType() == dto.MetricType_SUMMARY && p.currentLabelPair.GetName() == model.QuantileLabel) &&
|
||||||
|
!(p.currentMF.GetType() == dto.MetricType_HISTOGRAM && p.currentLabelPair.GetName() == model.BucketLabel) {
|
||||||
|
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPair)
|
||||||
|
}
|
||||||
|
if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentByte != '=' {
|
||||||
|
p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p.startLabelValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// startLabelValue represents the state where the next byte read from p.buf is
|
||||||
|
// the start of a (quoted) label value (or whitespace leading up to it).
|
||||||
|
func (p *Parser) startLabelValue() stateFn {
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentByte != '"' {
|
||||||
|
p.parseError(fmt.Sprintf("expected '\"' at start of label value, found %q", p.currentByte))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if p.readTokenAsLabelValue(); p.err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.currentLabelPair.Value = proto.String(p.currentToken.String())
|
||||||
|
// Special treatment of summaries:
|
||||||
|
// - Quantile labels are special, will result in dto.Quantile later.
|
||||||
|
// - Other labels have to be added to currentLabels for signature calculation.
|
||||||
|
if p.currentMF.GetType() == dto.MetricType_SUMMARY {
|
||||||
|
if p.currentLabelPair.GetName() == model.QuantileLabel {
|
||||||
|
if p.currentQuantile, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil {
|
||||||
|
// Create a more helpful error message.
|
||||||
|
p.parseError(fmt.Sprintf("expected float as value for 'quantile' label, got %q", p.currentLabelPair.GetValue()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Similar special treatment of histograms.
|
||||||
|
if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
|
||||||
|
if p.currentLabelPair.GetName() == model.BucketLabel {
|
||||||
|
if p.currentBucket, p.err = strconv.ParseFloat(p.currentLabelPair.GetValue(), 64); p.err != nil {
|
||||||
|
// Create a more helpful error message.
|
||||||
|
p.parseError(fmt.Sprintf("expected float as value for 'le' label, got %q", p.currentLabelPair.GetValue()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.currentLabels[p.currentLabelPair.GetName()] = p.currentLabelPair.GetValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
switch p.currentByte {
|
||||||
|
case ',':
|
||||||
|
return p.startLabelName
|
||||||
|
|
||||||
|
case '}':
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
return p.readingValue
|
||||||
|
default:
|
||||||
|
p.parseError(fmt.Sprintf("unexpected end of label value %q", p.currentLabelPair.Value))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readingValue represents the state where the last byte read (now in
|
||||||
|
// p.currentByte) is the first byte of the sample value (i.e. a float).
|
||||||
|
func (p *Parser) readingValue() stateFn {
|
||||||
|
// When we are here, we have read all the labels, so for the
|
||||||
|
// special case of a summary/histogram, we can finally find out
|
||||||
|
// if the metric already exists.
|
||||||
|
if p.currentMF.GetType() == dto.MetricType_SUMMARY {
|
||||||
|
signature := model.LabelsToSignature(p.currentLabels)
|
||||||
|
if summary := p.summaries[signature]; summary != nil {
|
||||||
|
p.currentMetric = summary
|
||||||
|
} else {
|
||||||
|
p.summaries[signature] = p.currentMetric
|
||||||
|
p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
|
||||||
|
}
|
||||||
|
} else if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
|
||||||
|
signature := model.LabelsToSignature(p.currentLabels)
|
||||||
|
if histogram := p.histograms[signature]; histogram != nil {
|
||||||
|
p.currentMetric = histogram
|
||||||
|
} else {
|
||||||
|
p.histograms[signature] = p.currentMetric
|
||||||
|
p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.currentMF.Metric = append(p.currentMF.Metric, p.currentMetric)
|
||||||
|
}
|
||||||
|
if p.readTokenUntilWhitespace(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
value, err := strconv.ParseFloat(p.currentToken.String(), 64)
|
||||||
|
if err != nil {
|
||||||
|
// Create a more helpful error message.
|
||||||
|
p.parseError(fmt.Sprintf("expected float as value, got %q", p.currentToken.String()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch p.currentMF.GetType() {
|
||||||
|
case dto.MetricType_COUNTER:
|
||||||
|
p.currentMetric.Counter = &dto.Counter{Value: proto.Float64(value)}
|
||||||
|
case dto.MetricType_GAUGE:
|
||||||
|
p.currentMetric.Gauge = &dto.Gauge{Value: proto.Float64(value)}
|
||||||
|
case dto.MetricType_UNTYPED:
|
||||||
|
p.currentMetric.Untyped = &dto.Untyped{Value: proto.Float64(value)}
|
||||||
|
case dto.MetricType_SUMMARY:
|
||||||
|
// *sigh*
|
||||||
|
if p.currentMetric.Summary == nil {
|
||||||
|
p.currentMetric.Summary = &dto.Summary{}
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case p.currentIsSummaryCount:
|
||||||
|
p.currentMetric.Summary.SampleCount = proto.Uint64(uint64(value))
|
||||||
|
case p.currentIsSummarySum:
|
||||||
|
p.currentMetric.Summary.SampleSum = proto.Float64(value)
|
||||||
|
case !math.IsNaN(p.currentQuantile):
|
||||||
|
p.currentMetric.Summary.Quantile = append(
|
||||||
|
p.currentMetric.Summary.Quantile,
|
||||||
|
&dto.Quantile{
|
||||||
|
Quantile: proto.Float64(p.currentQuantile),
|
||||||
|
Value: proto.Float64(value),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
case dto.MetricType_HISTOGRAM:
|
||||||
|
// *sigh*
|
||||||
|
if p.currentMetric.Histogram == nil {
|
||||||
|
p.currentMetric.Histogram = &dto.Histogram{}
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case p.currentIsHistogramCount:
|
||||||
|
p.currentMetric.Histogram.SampleCount = proto.Uint64(uint64(value))
|
||||||
|
case p.currentIsHistogramSum:
|
||||||
|
p.currentMetric.Histogram.SampleSum = proto.Float64(value)
|
||||||
|
case !math.IsNaN(p.currentBucket):
|
||||||
|
p.currentMetric.Histogram.Bucket = append(
|
||||||
|
p.currentMetric.Histogram.Bucket,
|
||||||
|
&dto.Bucket{
|
||||||
|
UpperBound: proto.Float64(p.currentBucket),
|
||||||
|
CumulativeCount: proto.Uint64(uint64(value)),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
p.err = fmt.Errorf("unexpected type for metric name %q", p.currentMF.GetName())
|
||||||
|
}
|
||||||
|
if p.currentByte == '\n' {
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
return p.startTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
|
// startTimestamp represents the state where the next byte read from p.buf is
|
||||||
|
// the start of the timestamp (or whitespace leading up to it).
|
||||||
|
func (p *Parser) startTimestamp() stateFn {
|
||||||
|
if p.skipBlankTab(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.readTokenUntilWhitespace(); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
timestamp, err := strconv.ParseInt(p.currentToken.String(), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
// Create a more helpful error message.
|
||||||
|
p.parseError(fmt.Sprintf("expected integer as timestamp, got %q", p.currentToken.String()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.currentMetric.TimestampMs = proto.Int64(timestamp)
|
||||||
|
if p.readTokenUntilNewline(false); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
if p.currentToken.Len() > 0 {
|
||||||
|
p.parseError(fmt.Sprintf("spurious string after timestamp: %q", p.currentToken.String()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
|
||||||
|
// readingHelp represents the state where the last byte read (now in
|
||||||
|
// p.currentByte) is the first byte of the docstring after 'HELP'.
|
||||||
|
func (p *Parser) readingHelp() stateFn {
|
||||||
|
if p.currentMF.Help != nil {
|
||||||
|
p.parseError(fmt.Sprintf("second HELP line for metric name %q", p.currentMF.GetName()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Rest of line is the docstring.
|
||||||
|
if p.readTokenUntilNewline(true); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
p.currentMF.Help = proto.String(p.currentToken.String())
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
|
||||||
|
// readingType represents the state where the last byte read (now in
|
||||||
|
// p.currentByte) is the first byte of the type hint after 'HELP'.
|
||||||
|
func (p *Parser) readingType() stateFn {
|
||||||
|
if p.currentMF.Type != nil {
|
||||||
|
p.parseError(fmt.Sprintf("second TYPE line for metric name %q, or TYPE reported after samples", p.currentMF.GetName()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Rest of line is the type.
|
||||||
|
if p.readTokenUntilNewline(false); p.err != nil {
|
||||||
|
return nil // Unexpected end of input.
|
||||||
|
}
|
||||||
|
metricType, ok := dto.MetricType_value[strings.ToUpper(p.currentToken.String())]
|
||||||
|
if !ok {
|
||||||
|
p.parseError(fmt.Sprintf("unknown metric type %q", p.currentToken.String()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.currentMF.Type = dto.MetricType(metricType).Enum()
|
||||||
|
return p.startOfLine
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseError sets p.err to a ParseError at the current line with the given
|
||||||
|
// message.
|
||||||
|
func (p *Parser) parseError(msg string) {
|
||||||
|
p.err = ParseError{
|
||||||
|
Line: p.lineCount,
|
||||||
|
Msg: msg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipBlankTab reads (and discards) bytes from p.buf until it encounters a byte
|
||||||
|
// that is neither ' ' nor '\t'. That byte is left in p.currentByte.
|
||||||
|
func (p *Parser) skipBlankTab() {
|
||||||
|
for {
|
||||||
|
if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil || !isBlankOrTab(p.currentByte) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// skipBlankTabIfCurrentBlankTab works exactly as skipBlankTab but doesn't do
|
||||||
|
// anything if p.currentByte is neither ' ' nor '\t'.
|
||||||
|
func (p *Parser) skipBlankTabIfCurrentBlankTab() {
|
||||||
|
if isBlankOrTab(p.currentByte) {
|
||||||
|
p.skipBlankTab()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readTokenUntilWhitespace copies bytes from p.buf into p.currentToken. The
|
||||||
|
// first byte considered is the byte already read (now in p.currentByte). The
|
||||||
|
// first whitespace byte encountered is still copied into p.currentByte, but not
|
||||||
|
// into p.currentToken.
|
||||||
|
func (p *Parser) readTokenUntilWhitespace() {
|
||||||
|
p.currentToken.Reset()
|
||||||
|
for p.err == nil && !isBlankOrTab(p.currentByte) && p.currentByte != '\n' {
|
||||||
|
p.currentToken.WriteByte(p.currentByte)
|
||||||
|
p.currentByte, p.err = p.buf.ReadByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readTokenUntilNewline copies bytes from p.buf into p.currentToken. The first
|
||||||
|
// byte considered is the byte already read (now in p.currentByte). The first
|
||||||
|
// newline byte encountered is still copied into p.currentByte, but not into
|
||||||
|
// p.currentToken. If recognizeEscapeSequence is true, two escape sequences are
|
||||||
|
// recognized: '\\' tranlates into '\', and '\n' into a line-feed character. All
|
||||||
|
// other escape sequences are invalid and cause an error.
|
||||||
|
func (p *Parser) readTokenUntilNewline(recognizeEscapeSequence bool) {
|
||||||
|
p.currentToken.Reset()
|
||||||
|
escaped := false
|
||||||
|
for p.err == nil {
|
||||||
|
if recognizeEscapeSequence && escaped {
|
||||||
|
switch p.currentByte {
|
||||||
|
case '\\':
|
||||||
|
p.currentToken.WriteByte(p.currentByte)
|
||||||
|
case 'n':
|
||||||
|
p.currentToken.WriteByte('\n')
|
||||||
|
default:
|
||||||
|
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
escaped = false
|
||||||
|
} else {
|
||||||
|
switch p.currentByte {
|
||||||
|
case '\n':
|
||||||
|
return
|
||||||
|
case '\\':
|
||||||
|
escaped = true
|
||||||
|
default:
|
||||||
|
p.currentToken.WriteByte(p.currentByte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.currentByte, p.err = p.buf.ReadByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readTokenAsMetricName copies a metric name from p.buf into p.currentToken.
|
||||||
|
// The first byte considered is the byte already read (now in p.currentByte).
|
||||||
|
// The first byte not part of a metric name is still copied into p.currentByte,
|
||||||
|
// but not into p.currentToken.
|
||||||
|
func (p *Parser) readTokenAsMetricName() {
|
||||||
|
p.currentToken.Reset()
|
||||||
|
if !isValidMetricNameStart(p.currentByte) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
p.currentToken.WriteByte(p.currentByte)
|
||||||
|
p.currentByte, p.err = p.buf.ReadByte()
|
||||||
|
if p.err != nil || !isValidMetricNameContinuation(p.currentByte) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readTokenAsLabelName copies a label name from p.buf into p.currentToken.
|
||||||
|
// The first byte considered is the byte already read (now in p.currentByte).
|
||||||
|
// The first byte not part of a label name is still copied into p.currentByte,
|
||||||
|
// but not into p.currentToken.
|
||||||
|
func (p *Parser) readTokenAsLabelName() {
|
||||||
|
p.currentToken.Reset()
|
||||||
|
if !isValidLabelNameStart(p.currentByte) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
p.currentToken.WriteByte(p.currentByte)
|
||||||
|
p.currentByte, p.err = p.buf.ReadByte()
|
||||||
|
if p.err != nil || !isValidLabelNameContinuation(p.currentByte) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// readTokenAsLabelValue copies a label value from p.buf into p.currentToken.
|
||||||
|
// In contrast to the other 'readTokenAs...' functions, which start with the
|
||||||
|
// last read byte in p.currentByte, this method ignores p.currentByte and starts
|
||||||
|
// with reading a new byte from p.buf. The first byte not part of a label value
|
||||||
|
// is still copied into p.currentByte, but not into p.currentToken.
|
||||||
|
func (p *Parser) readTokenAsLabelValue() {
|
||||||
|
p.currentToken.Reset()
|
||||||
|
escaped := false
|
||||||
|
for {
|
||||||
|
if p.currentByte, p.err = p.buf.ReadByte(); p.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if escaped {
|
||||||
|
switch p.currentByte {
|
||||||
|
case '"', '\\':
|
||||||
|
p.currentToken.WriteByte(p.currentByte)
|
||||||
|
case 'n':
|
||||||
|
p.currentToken.WriteByte('\n')
|
||||||
|
default:
|
||||||
|
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
escaped = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch p.currentByte {
|
||||||
|
case '"':
|
||||||
|
return
|
||||||
|
case '\n':
|
||||||
|
p.parseError(fmt.Sprintf("label value %q contains unescaped new-line", p.currentToken.String()))
|
||||||
|
return
|
||||||
|
case '\\':
|
||||||
|
escaped = true
|
||||||
|
default:
|
||||||
|
p.currentToken.WriteByte(p.currentByte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parser) setOrCreateCurrentMF() {
|
||||||
|
p.currentIsSummaryCount = false
|
||||||
|
p.currentIsSummarySum = false
|
||||||
|
p.currentIsHistogramCount = false
|
||||||
|
p.currentIsHistogramSum = false
|
||||||
|
name := p.currentToken.String()
|
||||||
|
if p.currentMF = p.metricFamiliesByName[name]; p.currentMF != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Try out if this is a _sum or _count for a summary/histogram.
|
||||||
|
summaryName := summaryMetricName(name)
|
||||||
|
if p.currentMF = p.metricFamiliesByName[summaryName]; p.currentMF != nil {
|
||||||
|
if p.currentMF.GetType() == dto.MetricType_SUMMARY {
|
||||||
|
if isCount(name) {
|
||||||
|
p.currentIsSummaryCount = true
|
||||||
|
}
|
||||||
|
if isSum(name) {
|
||||||
|
p.currentIsSummarySum = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
histogramName := histogramMetricName(name)
|
||||||
|
if p.currentMF = p.metricFamiliesByName[histogramName]; p.currentMF != nil {
|
||||||
|
if p.currentMF.GetType() == dto.MetricType_HISTOGRAM {
|
||||||
|
if isCount(name) {
|
||||||
|
p.currentIsHistogramCount = true
|
||||||
|
}
|
||||||
|
if isSum(name) {
|
||||||
|
p.currentIsHistogramSum = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.currentMF = &dto.MetricFamily{Name: proto.String(name)}
|
||||||
|
p.metricFamiliesByName[name] = p.currentMF
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidLabelNameStart(b byte) bool {
|
||||||
|
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidLabelNameContinuation(b byte) bool {
|
||||||
|
return isValidLabelNameStart(b) || (b >= '0' && b <= '9')
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidMetricNameStart(b byte) bool {
|
||||||
|
return isValidLabelNameStart(b) || b == ':'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidMetricNameContinuation(b byte) bool {
|
||||||
|
return isValidLabelNameContinuation(b) || b == ':'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBlankOrTab(b byte) bool {
|
||||||
|
return b == ' ' || b == '\t'
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCount(name string) bool {
|
||||||
|
return len(name) > 6 && name[len(name)-6:] == "_count"
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSum(name string) bool {
|
||||||
|
return len(name) > 4 && name[len(name)-4:] == "_sum"
|
||||||
|
}
|
||||||
|
|
||||||
|
func isBucket(name string) bool {
|
||||||
|
return len(name) > 7 && name[len(name)-7:] == "_bucket"
|
||||||
|
}
|
||||||
|
|
||||||
|
func summaryMetricName(name string) string {
|
||||||
|
switch {
|
||||||
|
case isCount(name):
|
||||||
|
return name[:len(name)-6]
|
||||||
|
case isSum(name):
|
||||||
|
return name[:len(name)-4]
|
||||||
|
default:
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func histogramMetricName(name string) string {
|
||||||
|
switch {
|
||||||
|
case isCount(name):
|
||||||
|
return name[:len(name)-6]
|
||||||
|
case isSum(name):
|
||||||
|
return name[:len(name)-4]
|
||||||
|
case isBucket(name):
|
||||||
|
return name[:len(name)-7]
|
||||||
|
default:
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
}
|
43
vendor/github.com/prometheus/client_golang/text/proto.go
generated
vendored
Normal file
43
vendor/github.com/prometheus/client_golang/text/proto.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// 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 text
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/matttproud/golang_protobuf_extensions/pbutil"
|
||||||
|
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WriteProtoDelimited writes the MetricFamily to the writer in delimited
|
||||||
|
// protobuf format and returns the number of bytes written and any error
|
||||||
|
// encountered.
|
||||||
|
func WriteProtoDelimited(w io.Writer, p *dto.MetricFamily) (int, error) {
|
||||||
|
return pbutil.WriteDelimited(w, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteProtoText writes the MetricFamily to the writer in text format and
|
||||||
|
// returns the number of bytes written and any error encountered.
|
||||||
|
func WriteProtoText(w io.Writer, p *dto.MetricFamily) (int, error) {
|
||||||
|
return fmt.Fprintf(w, "%s\n", proto.MarshalTextString(p))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteProtoCompactText writes the MetricFamily to the writer in compact text
|
||||||
|
// format and returns the number of bytes written and any error encountered.
|
||||||
|
func WriteProtoCompactText(w io.Writer, p *dto.MetricFamily) (int, error) {
|
||||||
|
return fmt.Fprintf(w, "%s\n", p)
|
||||||
|
}
|
14
vendor/vendor.json
vendored
14
vendor/vendor.json
vendored
@ -21,11 +21,21 @@
|
|||||||
"revisionTime": "2016-04-24T11:30:07Z"
|
"revisionTime": "2016-04-24T11:30:07Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Ph+qmEo8RdBKBHZUhx0y5Oyk/U0=",
|
"checksumSHA1": "TpbZuXCQvnEiTzFc6jhTgFDop3M=",
|
||||||
|
"path": "github.com/prometheus/client_golang/model",
|
||||||
|
"revision": "6dbab8106ed3ed77359ac85d9cf08e30290df864"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "lmxW0tuAU0yegSQqrzdepyqPLYQ=",
|
||||||
"path": "github.com/prometheus/client_golang/prometheus",
|
"path": "github.com/prometheus/client_golang/prometheus",
|
||||||
"revision": "5636dc67ae776adf5590da7349e70fbb9559972d",
|
"revision": "6dbab8106ed3ed77359ac85d9cf08e30290df864",
|
||||||
"revisionTime": "2016-09-16T18:03:40Z"
|
"revisionTime": "2016-09-16T18:03:40Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "0fkxdi0g3zdiWGe/rQiJZKvO9Yc=",
|
||||||
|
"path": "github.com/prometheus/client_golang/text",
|
||||||
|
"revision": "6dbab8106ed3ed77359ac85d9cf08e30290df864"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=",
|
"checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=",
|
||||||
"path": "github.com/prometheus/client_model/go",
|
"path": "github.com/prometheus/client_model/go",
|
||||||
|
Reference in New Issue
Block a user