Initial refactoring. WIP.
This commit is contained in:
parent
67994f1771
commit
32b10bd039
|
@ -24,6 +24,9 @@ package prometheus
|
|||
// already implemented in this library are the metric vectors (i.e. collection
|
||||
// of multiple instances of the same Metric but with different label values)
|
||||
// like GaugeVec or SummaryVec, and the ExpvarCollector.
|
||||
//
|
||||
// (Two Collectors are considered equal if their
|
||||
// Describe method yields the same set of descriptors.)
|
||||
type Collector interface {
|
||||
// Describe sends the super-set of all possible descriptors of metrics
|
||||
// collected by this Collector to the provided channel and returns once
|
||||
|
@ -46,7 +49,9 @@ type Collector interface {
|
|||
// therefore be implemented in a concurrency safe way. Blocking occurs
|
||||
// at the expense of total performance of rendering all registered
|
||||
// metrics. Ideally, Collector implementations support concurrent
|
||||
// readers.
|
||||
// readers. If a Collector finds itself unable to collect a metric, it
|
||||
// can signal the error to the registry by sending a Metric that will
|
||||
// return the error when its Write method is called.
|
||||
Collect(chan<- Metric)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// 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.
|
||||
|
||||
// Package collectors provides collector implemntations for various purposes.
|
||||
package collectors
|
|
@ -11,13 +11,17 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
package collectors
|
||||
|
||||
import "github.com/prometheus/procfs"
|
||||
import (
|
||||
"github.com/prometheus/procfs"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/metric"
|
||||
)
|
||||
|
||||
type processCollector struct {
|
||||
pid int
|
||||
collectFn func(chan<- Metric)
|
||||
collectFn func(chan<- metric.Metric)
|
||||
pidFn func() (int, error)
|
||||
cpuTotal Counter
|
||||
openFDs, maxFDs Gauge
|
|
@ -1,4 +1,4 @@
|
|||
package prometheus
|
||||
package collectors
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
|
@ -6,6 +6,7 @@ import (
|
|||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
|
@ -30,6 +31,197 @@ const reservedLabelPrefix = "__"
|
|||
// create a Desc.
|
||||
type Labels map[string]string
|
||||
|
||||
// Desc is used to describe the meta-data of a Metric (via its Desc method) or a
|
||||
// group of metrics collected by a Collector (via its Describe method). Some of its
|
||||
// methods are only used internally and are therefore not exported, which also
|
||||
// prevents users to implement their own descriptors. Descriptor instances must
|
||||
// be created via suitable NewXXXDesc functions and will in generally only be
|
||||
// needed in custom collectors.
|
||||
//
|
||||
// Desc implementations are immutable by contract.
|
||||
//
|
||||
// A Desc that also implements the error interface is called an invalid
|
||||
// descriptor, which is solely used to communicate an error and must never be
|
||||
// processed further.
|
||||
type Desc interface {
|
||||
// String returns a string representation of the descriptor as usual. It
|
||||
// is also used as an ID that must be unique among all descriptors
|
||||
// registered by a Registry.
|
||||
String() string
|
||||
dims() string
|
||||
}
|
||||
|
||||
// NewInvalidDesc returns a descriptor that also implements the error
|
||||
// interface. It is used to communicate an error during a call of Desc (Metric
|
||||
// method) or Describe (Collector method). Create with NewInvalidDesc.
|
||||
func NewInvalidDesc(err error) Desc {
|
||||
return &invalidDesc{err: err}
|
||||
}
|
||||
|
||||
type invalidDesc struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (d *invalidDesc) Error() string {
|
||||
return d.err.Error()
|
||||
}
|
||||
|
||||
func (d *invalidDesc) String() string {
|
||||
return "[invalid] " + d.err.Error()
|
||||
}
|
||||
|
||||
func (d *invalidDesc) dims() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewPrefixDesc returns a descriptor that is used by Collectors that want to
|
||||
// reserve a whole metric name prefix for their own use. An invalid descriptor
|
||||
// is returned if the prefix is not a valid as the start of a metric
|
||||
// name. However, an empty prefix is valid and reserves all metric names.
|
||||
func NewPrefixDesc(prefix string) Desc {
|
||||
if prefix != "" && !validMetricName(prefix) {
|
||||
return NewInvalidDesc(fmt.Errorf("%q is not a valid metric name prefix", prefix))
|
||||
}
|
||||
return &prefixDesc{pfx: prefix}
|
||||
}
|
||||
|
||||
type prefixDesc struct {
|
||||
prefix string
|
||||
}
|
||||
|
||||
func (d *prefixDesc) String() string {
|
||||
return "[prefix] " + d.prefix
|
||||
}
|
||||
|
||||
func (d *prefixDesc) dims() string {
|
||||
return "" // PrefixDesc is for all dimensions.
|
||||
}
|
||||
|
||||
func (d *prefixDesc) overlapsWith(other Desc) bool {
|
||||
switch o := other.(type) {
|
||||
case *invalidDesc:
|
||||
// Invalid descs never overlap.
|
||||
return false
|
||||
case *partialDesc, *fullDesc:
|
||||
return strings.HasPrefix(o.fqName, d.prefix)
|
||||
case *prefixDesc:
|
||||
return strings.HasPrefix(o.prefix, d.prefix) || strings.HasPrefix(d.Prefix, o.prefix)
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected type of descriptor %q", o))
|
||||
}
|
||||
}
|
||||
|
||||
// NewPartialDesc returns a descriptor that is used by Collectors that want to
|
||||
// reserve a specific metric name and type with specific label dimensions of
|
||||
// which some (but not all) label values might be set already. An invalid
|
||||
// descriptor is returned in the following cases: The resulting label name
|
||||
// (assembled from namespace, subsystem, and name) is invalid, the help string
|
||||
// is empty, unsetLabels is empty or contains invalid label names,
|
||||
// setLabels (which might be empty) contains invalid label names or label
|
||||
// values, metricType is not a valid MetricType.
|
||||
func NewPartialDesc(
|
||||
namespace, subsystem, name string,
|
||||
metricType MetricType,
|
||||
help string,
|
||||
setLabels Labels,
|
||||
unsetLabels []string,
|
||||
) Desc {
|
||||
return nil // TODO
|
||||
}
|
||||
|
||||
// NewFullDesc returns a descriptor with fully specified name, type, and
|
||||
// labels. It can be used by Collectors and must be used by Metrics. An invalid
|
||||
// descriptor is returned if the resulting label name (assembled from namespace,
|
||||
// subsystem, and name) is invalid, the help string is empty, metricType has an
|
||||
// invalid value, or the labels contain invalid label names or values. The labels
|
||||
// might be empty, though.
|
||||
func NewFullDesc(
|
||||
namespace, subsystem, name string,
|
||||
metricType MetricType,
|
||||
help string,
|
||||
labels Labels,
|
||||
) Desc {
|
||||
return nil // TODO
|
||||
}
|
||||
|
||||
// FullySpecify returns a fully specified descriptor based on the provided
|
||||
// partial descriptor by setting all the unset labels to the provided values (in
|
||||
// the same order as they have been specified in the NewFullDesc or DeSpecify
|
||||
// call). An invalid desc is returned if the provided desc is not a partial
|
||||
// descriptor, the cardinality of labelValues does not fit, or labelValues
|
||||
// contains invalid label values.
|
||||
func FullySpecify(desc Desc, labelValues ...string) Desc {
|
||||
d, ok := desc.(*partialDesc)
|
||||
if !ok {
|
||||
return NewInvalidDesc(fmt.Errorf("tried to fully specify non-partial descriptor %q", desc))
|
||||
}
|
||||
return nil // TODO
|
||||
}
|
||||
|
||||
// DeSpecify creates a partial descriptor based on the provided full descriptor
|
||||
// by adding un-set labels with the provided label names. An invalid desc is
|
||||
// returned if the provided desc is not a full descriptor, or labelNames
|
||||
// contains invalid label names (or no label names at all).
|
||||
func DeSpecify(desc Desc, labelNames ...string) Desc {
|
||||
d, ok := desc.(*fullDesc)
|
||||
if !ok {
|
||||
return NewInvalidDesc(fmt.Errorf("tried to de-specify non-full descriptor %q", desc))
|
||||
}
|
||||
if len(ln) == 0 {
|
||||
return NewInvalidDesc(fmt.Errorf("no label names provided to de-specify %q", desc))
|
||||
}
|
||||
for _, ln := range labelNames {
|
||||
if !validLabelName(ln) {
|
||||
return NewInvalidDesc(fmt.Errorf("encountered invalid label name %q while de-specifying %q", ln, desc))
|
||||
}
|
||||
}
|
||||
return &partialDesc{*d, labelNames}
|
||||
}
|
||||
|
||||
type fullDesc struct {
|
||||
fqName, help string
|
||||
metricType MetricType
|
||||
setLabels []*dto.LabelPair // Sorted.
|
||||
}
|
||||
|
||||
type partialDesc struct {
|
||||
fullDesc
|
||||
unsetLabels []string // Keep in original order.
|
||||
}
|
||||
|
||||
// buildFQName joins the given three name components by "_". Empty name
|
||||
// components are ignored. If the name parameter itself is empty, an empty
|
||||
// string is returned, no matter what.
|
||||
func buildFQName(namespace, subsystem, name string) string {
|
||||
if name == "" {
|
||||
return ""
|
||||
}
|
||||
switch {
|
||||
case namespace != "" && subsystem != "":
|
||||
return namespace + "_" + subsystem + "_" + name
|
||||
case namespace != "":
|
||||
return namespace + "_" + name
|
||||
case subsystem != "":
|
||||
return subsystem + "_" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func validMetricName(n string) bool {
|
||||
return metricNameRE.MatchString(n)
|
||||
}
|
||||
|
||||
func validLabelName(l string) bool {
|
||||
return labelNameRE.MatchString(l) &&
|
||||
!strings.HasPrefix(l, reservedLabelPrefix)
|
||||
}
|
||||
|
||||
func validLabelValue(l string) bool {
|
||||
return utf8.ValidString(l)
|
||||
}
|
||||
|
||||
// OLD CODE below.
|
||||
|
||||
// Desc is the descriptor used by every Prometheus Metric. It is essentially
|
||||
// the immutable meta-data of a Metric. The normal Metric implementations
|
||||
// included in this package manage their Desc under the hood. Users only have to
|
||||
|
@ -102,7 +294,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
|||
labelNameSet := map[string]struct{}{}
|
||||
// First add only the const label names and sort them...
|
||||
for labelName := range constLabels {
|
||||
if !checkLabelName(labelName) {
|
||||
if !validLabelName(labelName) {
|
||||
d.err = fmt.Errorf("%q is not a valid label name", labelName)
|
||||
return d
|
||||
}
|
||||
|
@ -118,7 +310,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
|||
// cannot be in a regular label name. That prevents matching the label
|
||||
// dimension with a different mix between preset and variable labels.
|
||||
for _, labelName := range variableLabels {
|
||||
if !checkLabelName(labelName) {
|
||||
if !validLabelName(labelName) {
|
||||
d.err = fmt.Errorf("%q is not a valid label name", labelName)
|
||||
return d
|
||||
}
|
||||
|
@ -159,16 +351,6 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
|||
return d
|
||||
}
|
||||
|
||||
// NewInvalidDesc returns an invalid descriptor, i.e. a descriptor with the
|
||||
// provided error set. If a collector returning such a descriptor is registered,
|
||||
// registration will fail with the provided error. NewInvalidDesc can be used by
|
||||
// a Collector to signal inability to describe itself.
|
||||
func NewInvalidDesc(err error) *Desc {
|
||||
return &Desc{
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Desc) String() string {
|
||||
lpStrings := make([]string, 0, len(d.constLabelPairs))
|
||||
for _, lp := range d.constLabelPairs {
|
||||
|
@ -185,8 +367,3 @@ func (d *Desc) String() string {
|
|||
d.variableLabels,
|
||||
)
|
||||
}
|
||||
|
||||
func checkLabelName(l string) bool {
|
||||
return labelNameRE.MatchString(l) &&
|
||||
!strings.HasPrefix(l, reservedLabelPrefix)
|
||||
}
|
||||
|
|
|
@ -13,11 +13,7 @@
|
|||
|
||||
package prometheus
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
)
|
||||
import dto "github.com/prometheus/client_model/go"
|
||||
|
||||
const separatorByte byte = 255
|
||||
|
||||
|
@ -53,6 +49,42 @@ type Metric interface {
|
|||
Write(*dto.Metric) error
|
||||
}
|
||||
|
||||
// MetricType is an enumeration of metric types. It deliberately mirrors the
|
||||
// MetricType enum from the protobuf specification to avoid exposing protobuf
|
||||
// references to the user of this package. (The protobuf parts could be
|
||||
// internally vendored.)
|
||||
type MetricType int
|
||||
|
||||
// Possible values for the MetricType enum.
|
||||
const (
|
||||
CounterMetric MetricType = iota
|
||||
GaugeMetric
|
||||
SummaryMetric
|
||||
UntypedMetric
|
||||
HistogramMetric
|
||||
)
|
||||
|
||||
func (m MetricType) Valid() bool {
|
||||
return m >= CounterMetric && m <= HistogramMetric
|
||||
}
|
||||
|
||||
func (m MetricType) String() string {
|
||||
switch m {
|
||||
case CounterMetric:
|
||||
return "COUNTER"
|
||||
case GaugeMetric:
|
||||
return "GAUGE"
|
||||
case SummaryMetric:
|
||||
return "SUMMARY"
|
||||
case UntypedMetric:
|
||||
return "UNTYPED"
|
||||
case HistogramMetric:
|
||||
return "HISTOGRAM"
|
||||
default:
|
||||
return "INVALID"
|
||||
}
|
||||
}
|
||||
|
||||
// Opts bundles the options for creating most Metric types. Each metric
|
||||
// implementation XXX has its own XXXOpts type, but in most cases, it is just be
|
||||
// an alias of this type (which might change when the requirement arises.)
|
||||
|
@ -96,28 +128,6 @@ type Opts struct {
|
|||
ConstLabels Labels
|
||||
}
|
||||
|
||||
// BuildFQName joins the given three name components by "_". Empty name
|
||||
// components are ignored. If the name parameter itself is empty, an empty
|
||||
// string is returned, no matter what. Metric implementations included in this
|
||||
// library use this function internally to generate the fully-qualified metric
|
||||
// name from the name component in their Opts. Users of the library will only
|
||||
// need this function if they implement their own Metric or instantiate a Desc
|
||||
// (with NewDesc) directly.
|
||||
func BuildFQName(namespace, subsystem, name string) string {
|
||||
if name == "" {
|
||||
return ""
|
||||
}
|
||||
switch {
|
||||
case namespace != "" && subsystem != "":
|
||||
return strings.Join([]string{namespace, subsystem, name}, "_")
|
||||
case namespace != "":
|
||||
return strings.Join([]string{namespace, name}, "_")
|
||||
case subsystem != "":
|
||||
return strings.Join([]string{subsystem, name}, "_")
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// LabelPairSorter implements sort.Interface. It is used to sort a slice of
|
||||
// dto.LabelPair pointers. This is useful for implementing the Write method of
|
||||
// custom metrics.
|
||||
|
@ -150,17 +160,18 @@ func (s hashSorter) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
type invalidMetric struct {
|
||||
desc *Desc
|
||||
desc Desc
|
||||
err error
|
||||
}
|
||||
|
||||
// NewInvalidMetric returns a metric whose Write method always returns the
|
||||
// provided error. It is useful if a Collector finds itself unable to collect
|
||||
// a metric and wishes to report an error to the registry.
|
||||
func NewInvalidMetric(desc *Desc, err error) Metric {
|
||||
return &invalidMetric{desc, err}
|
||||
// provided error, and whose descriptor is invalid, carrying the provided
|
||||
// error. It is useful if a Collector finds itself unable to collect a metric
|
||||
// and wishes to report an error to the registry.
|
||||
func NewInvalidMetric(err error) Metric {
|
||||
return &invalidMetric{NewInvalidDesc(err), err}
|
||||
}
|
||||
|
||||
func (m *invalidMetric) Desc() *Desc { return m.desc }
|
||||
func (m *invalidMetric) Desc() Desc { return m.desc }
|
||||
|
||||
func (m *invalidMetric) Write(*dto.Metric) error { return m.err }
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
// 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.
|
||||
|
||||
package metric
|
||||
|
||||
// Collector is the interface implemented by anything that can be used by
|
||||
// Prometheus to collect metrics. A Collector has to be registered for
|
||||
// collection.
|
||||
//
|
||||
// The stock metrics provided in their respective packages (like Gauge, Counter,
|
||||
// Summary, Histogram) are also Collectors (which only ever collect one metric,
|
||||
// namely itself). An implementer of Collector may, however, collect multiple
|
||||
// metrics in a coordinated fashion and/or create metrics on the fly. Examples
|
||||
// for collectors already implemented in this library are the metric vectors
|
||||
// (i.e. collection of multiple instances of the same Metric but with different
|
||||
// label values) like gauge.Vec or summary.Vec, and the ExpvarCollector.
|
||||
//
|
||||
// Two Collectors are considered equal if their Describe methods yield the same
|
||||
// set of descriptors.
|
||||
type Collector interface {
|
||||
// Describe sends all descriptors required to describe the metrics
|
||||
// collected by this Collector to the provided channel and returns once
|
||||
// the last descriptor has been sent. The sent descriptors fulfill the
|
||||
// consistency and uniqueness requirements described in the Desc
|
||||
// documentation. This method idempotently sends the same descriptors
|
||||
// throughout the lifetime of the Collector. If a Collector encounters
|
||||
// an error while executing this method, it must send an invalid
|
||||
// descriptor (created with NewInvalidDesc) to signal the error to the
|
||||
// registry.
|
||||
Describe(chan<- Desc)
|
||||
// Collect is called by Prometheus when collecting metrics. The
|
||||
// implementation sends each collected metric via the provided channel
|
||||
// and returns once the last metric has been sent. Each sent metric must
|
||||
// be consistent with one of the descriptors returned by
|
||||
// Describe. Returned metrics that are described by the same descriptor
|
||||
// must differ in their variable label values. This method may be called
|
||||
// concurrently and must therefore be implemented in a concurrency safe
|
||||
// way. Blocking occurs at the expense of total performance of rendering
|
||||
// all registered metrics. Ideally, Collector implementations support
|
||||
// concurrent readers. If a Collector finds itself unable to collect a
|
||||
// metric, it can signal the error to the registry by sending a Metric
|
||||
// that will return the error in its Write method..
|
||||
Collect(chan<- Metric)
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
import "fmt"
|
||||
|
||||
func NewDesc(
|
||||
namespace, subsystem, name string,
|
||||
help string,
|
||||
constLabels Labels,
|
||||
variableLabels []string,
|
||||
) Desc {
|
||||
fqName := buildFQName(namespace, subsystem, name)
|
||||
if !metricNameRE.MatchString(fqName) {
|
||||
return NewInvalidDesc(fmt.Errorf("%q is not a valid metric name", fqName))
|
||||
}
|
||||
if help == "" {
|
||||
return NewInvalidDesc(fmt.Errorf("empty help string for metric %q", fqName))
|
||||
}
|
||||
|
||||
return nil // TODO
|
||||
}
|
||||
|
||||
type regularDesc struct {
|
||||
baseDesc
|
||||
fqName, help string
|
||||
constLabelPairs []*dto.LabelPair
|
||||
variableLabels []string
|
||||
}
|
||||
|
||||
type prefixDesc struct {
|
||||
baseDesc
|
||||
prefix string
|
||||
}
|
||||
|
||||
type Set struct {
|
||||
regular map[string]*regularDesc
|
||||
// The prefix ones should be tries. But it's unlikely to have many of them.
|
||||
prefix []*prefixDesc
|
||||
}
|
||||
|
||||
func (s *Set) Add(d Desc) error {
|
||||
if d.Error() != nil {
|
||||
return d.Error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Set) Remove(d Desc) bool {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package prometheus
|
||||
package metric
|
||||
|
||||
// Inline and byte-free variant of hash/fnv's fnv64a.
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// 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.
|
||||
|
||||
package metric
|
||||
|
||||
import dto "github.com/prometheus/client_model/go"
|
||||
|
||||
// A Metric models a single sample value with its meta data being exported to
|
||||
// Prometheus. Implementers of Metric in this package include Gauge, Counter,
|
||||
// Untyped, and Summary. Users can implement their own Metric types, but that
|
||||
// should be rarely needed.
|
||||
type Metric interface {
|
||||
// Desc returns the descriptor for the Metric. This method idempotently
|
||||
// returns the same descriptor throughout the lifetime of the Metric. A
|
||||
// Metric unable to describe itself must return an invalid descriptor
|
||||
// (created with NewInvalidDesc).
|
||||
Desc() Desc
|
||||
// Write encodes the Metric into a "Metric" Protocol Buffer data
|
||||
// transmission object.
|
||||
//
|
||||
// Implementers of custom Metric types must observe concurrency safety
|
||||
// as reads of this metric may occur at any time, and any blocking
|
||||
// occurs at the expense of total performance of rendering all
|
||||
// registered metrics. Ideally Metric implementations should support
|
||||
// concurrent readers.
|
||||
//
|
||||
// The caller may minimize memory allocations by providing a
|
||||
// pre-existing reset dto.Metric pointer. The caller may recycle the
|
||||
// dto.Metric proto message, so Metric implementations should just
|
||||
// populate the provided dto.Metric and then should not keep any
|
||||
// reference to it.
|
||||
//
|
||||
// While populating dto.Metric, labels must be sorted lexicographically.
|
||||
// (Implementers may find LabelPairSorter useful for that.)
|
||||
Write(*dto.Metric) error
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// 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.
|
||||
|
||||
package promhttp
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/registry"
|
||||
)
|
||||
|
||||
// Constants relevant to the HTTP interface.
|
||||
const (
|
||||
// APIVersion is the version of the format of the exported data. This
|
||||
// will match this library's version, which subscribes to the Semantic
|
||||
// Versioning scheme.
|
||||
APIVersion = "0.0.4"
|
||||
|
||||
// DelimitedTelemetryContentType is the content type set on telemetry
|
||||
// data responses in delimited protobuf format.
|
||||
DelimitedTelemetryContentType = `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`
|
||||
// TextTelemetryContentType is the content type set on telemetry data
|
||||
// responses in text format.
|
||||
TextTelemetryContentType = `text/plain; version=` + APIVersion
|
||||
// ProtoTextTelemetryContentType is the content type set on telemetry
|
||||
// data responses in protobuf text format. (Only used for debugging.)
|
||||
ProtoTextTelemetryContentType = `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=text`
|
||||
// ProtoCompactTextTelemetryContentType is the content type set on
|
||||
// telemetry data responses in protobuf compact text format. (Only used
|
||||
// for debugging.)
|
||||
ProtoCompactTextTelemetryContentType = `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`
|
||||
|
||||
contentTypeHeader = "Content-Type"
|
||||
contentLengthHeader = "Content-Length"
|
||||
contentEncodingHeader = "Content-Encoding"
|
||||
|
||||
acceptEncodingHeader = "Accept-Encoding"
|
||||
acceptHeader = "Accept"
|
||||
)
|
||||
|
||||
func Handler(r registry.Registry) http.Handler {
|
||||
return nil // TODO
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2014 The Prometheus Authors
|
||||
// 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
|
||||
|
@ -11,7 +11,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package prometheus
|
||||
package promhttp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
@ -23,6 +23,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// TODO: Rework handler instrumentation (histograms, more configurable...).
|
||||
|
||||
var instLabels = []string{"method", "code"}
|
||||
|
||||
type nower interface {
|
|
@ -27,7 +27,6 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -36,56 +35,19 @@ import (
|
|||
"github.com/prometheus/common/expfmt"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
var (
|
||||
defRegistry = newDefaultRegistry()
|
||||
errAlreadyReg = errors.New("duplicate metrics collector registration attempted")
|
||||
)
|
||||
|
||||
// Constants relevant to the HTTP interface.
|
||||
const (
|
||||
// APIVersion is the version of the format of the exported data. This
|
||||
// will match this library's version, which subscribes to the Semantic
|
||||
// Versioning scheme.
|
||||
APIVersion = "0.0.4"
|
||||
|
||||
// DelimitedTelemetryContentType is the content type set on telemetry
|
||||
// data responses in delimited protobuf format.
|
||||
DelimitedTelemetryContentType = `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=delimited`
|
||||
// TextTelemetryContentType is the content type set on telemetry data
|
||||
// responses in text format.
|
||||
TextTelemetryContentType = `text/plain; version=` + APIVersion
|
||||
// ProtoTextTelemetryContentType is the content type set on telemetry
|
||||
// data responses in protobuf text format. (Only used for debugging.)
|
||||
ProtoTextTelemetryContentType = `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=text`
|
||||
// ProtoCompactTextTelemetryContentType is the content type set on
|
||||
// telemetry data responses in protobuf compact text format. (Only used
|
||||
// for debugging.)
|
||||
ProtoCompactTextTelemetryContentType = `application/vnd.google.protobuf; proto=io.prometheus.client.MetricFamily; encoding=compact-text`
|
||||
|
||||
// Constants for object pools.
|
||||
numBufs = 4
|
||||
numMetricFamilies = 1000
|
||||
numMetrics = 10000
|
||||
|
||||
// Capacity for the channel to collect metrics and descriptors.
|
||||
capMetricChan = 1000
|
||||
capDescChan = 10
|
||||
|
||||
contentTypeHeader = "Content-Type"
|
||||
contentLengthHeader = "Content-Length"
|
||||
contentEncodingHeader = "Content-Encoding"
|
||||
|
||||
acceptEncodingHeader = "Accept-Encoding"
|
||||
acceptHeader = "Accept"
|
||||
)
|
||||
|
||||
// Handler returns the HTTP handler for the global Prometheus registry. It is
|
||||
// already instrumented with InstrumentHandler (using "prometheus" as handler
|
||||
// name). Usually the handler is used to handle the "/metrics" endpoint.
|
||||
// Handler returns an instrumented HTTP handler for the default Prometheus
|
||||
// registry. It is already instrumented with InstrumentHandler (using
|
||||
// "prometheus" as handler name). Usually the handler is used to handle the
|
||||
// "/metrics" endpoint.
|
||||
func Handler() http.Handler {
|
||||
return InstrumentHandler("prometheus", defRegistry)
|
||||
return promhttp.InstrumentHandler(
|
||||
"prometheus",
|
||||
promhttp.Handler(registry.Default),
|
||||
)
|
||||
}
|
||||
|
||||
// UninstrumentedHandler works in the same way as Handler, but the returned HTTP
|
||||
|
@ -94,30 +56,26 @@ func Handler() http.Handler {
|
|||
// different handler name (or with a different instrumentation approach
|
||||
// altogether). See the InstrumentHandler example.
|
||||
func UninstrumentedHandler() http.Handler {
|
||||
return defRegistry
|
||||
return promhttp.Handler(registry.Default)
|
||||
}
|
||||
|
||||
// Register registers a new Collector to be included in metrics collection. It
|
||||
// returns an error if the descriptors provided by the Collector are invalid or
|
||||
// if they - in combination with descriptors of already registered Collectors -
|
||||
// do not fulfill the consistency and uniqueness criteria described in the Desc
|
||||
// documentation.
|
||||
// Register registers a new Collector to be included in metrics collection with
|
||||
// the default registry. It returns an error if the descriptors provided by the
|
||||
// Collector are invalid or if they - in combination with descriptors of already
|
||||
// registered Collectors - do not fulfill the consistency and uniqueness
|
||||
// criteria described in the Desc documentation.
|
||||
//
|
||||
// Do not register the same Collector multiple times concurrently. (Registering
|
||||
// the same Collector twice would result in an error anyway, but on top of that,
|
||||
// it is not safe to do so concurrently.)
|
||||
func Register(m Collector) error {
|
||||
_, err := defRegistry.Register(m)
|
||||
return err
|
||||
func Register(c Collector) error {
|
||||
return registry.Default.Register(c)
|
||||
}
|
||||
|
||||
// MustRegister works like Register but panics where Register would have
|
||||
// returned an error.
|
||||
func MustRegister(m Collector) {
|
||||
err := Register(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
func MustRegister(c Collector) {
|
||||
registry.MustRegister(registry.Default, c)
|
||||
}
|
||||
|
||||
// RegisterOrGet works like Register but does not return an error if a Collector
|
||||
|
@ -129,18 +87,14 @@ func MustRegister(m Collector) {
|
|||
//
|
||||
// As for Register, it is still not safe to call RegisterOrGet with the same
|
||||
// Collector multiple times concurrently.
|
||||
func RegisterOrGet(m Collector) (Collector, error) {
|
||||
return defRegistry.RegisterOrGet(m)
|
||||
func RegisterOrGet(c Collector) (Collector, error) {
|
||||
return registry.RegisterOrGet(registry.Default, c)
|
||||
}
|
||||
|
||||
// MustRegisterOrGet works like Register but panics where RegisterOrGet would
|
||||
// have returned an error.
|
||||
func MustRegisterOrGet(m Collector) Collector {
|
||||
existing, err := RegisterOrGet(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return existing
|
||||
func MustRegisterOrGet(c Collector) Collector {
|
||||
return registry.MustRegisterOrGet(registry.Default, c)
|
||||
}
|
||||
|
||||
// Unregister unregisters the Collector that equals the Collector passed in as
|
||||
|
@ -148,50 +102,10 @@ func MustRegisterOrGet(m Collector) Collector {
|
|||
// yields the same set of descriptors.) The function returns whether a Collector
|
||||
// was unregistered.
|
||||
func Unregister(c Collector) bool {
|
||||
return defRegistry.Unregister(c)
|
||||
return registry.Default.Unregister(c)
|
||||
}
|
||||
|
||||
// SetMetricFamilyInjectionHook sets a function that is called whenever metrics
|
||||
// are collected. The hook function must be set before metrics collection begins
|
||||
// (i.e. call SetMetricFamilyInjectionHook before setting the HTTP handler.) The
|
||||
// MetricFamily protobufs returned by the hook function are merged with the
|
||||
// metrics collected in the usual way.
|
||||
//
|
||||
// This is a way to directly inject MetricFamily protobufs managed and owned by
|
||||
// the caller. The caller has full responsibility. As no registration of the
|
||||
// injected metrics has happened, there is no descriptor to check against, and
|
||||
// there are no registration-time checks. If collect-time checks are disabled
|
||||
// (see function EnableCollectChecks), no sanity checks are performed on the
|
||||
// returned protobufs at all. If collect-checks are enabled, type and uniqueness
|
||||
// checks are performed, but no further consistency checks (which would require
|
||||
// knowledge of a metric descriptor).
|
||||
//
|
||||
// Sorting concerns: The caller is responsible for sorting the label pairs in
|
||||
// each metric. However, the order of metrics will be sorted by the registry as
|
||||
// it is required anyway after merging with the metric families collected
|
||||
// conventionally.
|
||||
//
|
||||
// The function must be callable at any time and concurrently.
|
||||
func SetMetricFamilyInjectionHook(hook func() []*dto.MetricFamily) {
|
||||
defRegistry.metricFamilyInjectionHook = hook
|
||||
}
|
||||
|
||||
// PanicOnCollectError sets the behavior whether a panic is caused upon an error
|
||||
// while metrics are collected and served to the HTTP endpoint. By default, an
|
||||
// internal server error (status code 500) is served with an error message.
|
||||
func PanicOnCollectError(b bool) {
|
||||
defRegistry.panicOnCollectError = b
|
||||
}
|
||||
|
||||
// EnableCollectChecks enables (or disables) additional consistency checks
|
||||
// during metrics collection. These additional checks are not enabled by default
|
||||
// because they inflict a performance penalty and the errors they check for can
|
||||
// only happen if the used Metric and Collector types have internal programming
|
||||
// errors. It can be helpful to enable these checks while working with custom
|
||||
// Collectors or Metrics whose correctness is not well established yet.
|
||||
func EnableCollectChecks(b bool) {
|
||||
defRegistry.collectChecksEnabled = b
|
||||
}
|
||||
// TODO: Move out from here.
|
||||
|
||||
// encoder is a function that writes a dto.MetricFamily to an io.Writer in a
|
||||
// certain encoding. It returns the number of bytes written and any error
|
||||
|
@ -305,7 +219,7 @@ func (r *registry) Unregister(c Collector) bool {
|
|||
}()
|
||||
|
||||
descIDs := map[uint64]struct{}{}
|
||||
var collectorID uint64 // Just a sum of the desc IDs.
|
||||
var collectorID uint64 // Just a sum of the desc IDs. TODO: should be fnv on its own
|
||||
for desc := range descChan {
|
||||
if _, exists := descIDs[desc.id]; !exists {
|
||||
collectorID += desc.id
|
||||
|
@ -670,13 +584,6 @@ func newRegistry() *registry {
|
|||
}
|
||||
}
|
||||
|
||||
func newDefaultRegistry() *registry {
|
||||
r := newRegistry()
|
||||
r.Register(NewProcessCollector(os.Getpid(), ""))
|
||||
r.Register(NewGoCollector())
|
||||
return r
|
||||
}
|
||||
|
||||
// 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).
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
// 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.
|
||||
|
||||
// Package registry provides the interface of the metrics registry and means to
|
||||
// create concrete instantiations thereof.
|
||||
|
||||
package registry
|
|
@ -0,0 +1,24 @@
|
|||
// 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.
|
||||
|
||||
package registry
|
||||
|
||||
import "github.com/prometheus/client_golang/prometheus/metric"
|
||||
|
||||
type AlreadyRegisteredError struct {
|
||||
ExistingCollector, NewCollector metric.Collector
|
||||
}
|
||||
|
||||
func (err AlreadyRegisteredError) Error() string {
|
||||
return "" // TODO
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// 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.
|
||||
|
||||
package registry
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// TODO: These are from the old code. Vet!
|
||||
const (
|
||||
// Constants for object pools.
|
||||
numBufs = 4
|
||||
numMetricFamilies = 1000
|
||||
numMetrics = 10000
|
||||
|
||||
// Capacity for the channel to collect metrics and descriptors.
|
||||
capMetricChan = 1000
|
||||
capDescChan = 10
|
||||
)
|
||||
|
||||
func init() {
|
||||
MustRegister(Default, collectors.NewProcessCollector(os.Getpid(), ""))
|
||||
MustRegister(Default, collectors.NewGoCollector())
|
||||
}
|
||||
|
||||
// Default is the default registry implicitly used by the top-level functions in
|
||||
// the prometheus package. It is using the default value of Opts and has a
|
||||
// ProcessCollector and a GoCollector pre-registered.
|
||||
var Default Registry = New(Opts{})
|
||||
|
||||
func New(opts Opts) Registry {
|
||||
return ®istry{}
|
||||
}
|
||||
|
||||
type registry struct {
|
||||
}
|
||||
|
||||
func (r *registry) Register(prometheus.Collector) error {
|
||||
return nil // TODO
|
||||
}
|
||||
|
||||
func (r *registry) Unregister(prometheus.Collector) bool {
|
||||
return false // TODO
|
||||
}
|
||||
|
||||
func (r *registry) Collect(names map[string]struct{}) <-chan struct {
|
||||
*dto.MetricFamily
|
||||
error
|
||||
} {
|
||||
return nil // TODO
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
// 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.
|
||||
|
||||
// Package registry provides the interface of the metrics registry and means to
|
||||
// instantiate implementations thereof. It also provides the so-called default
|
||||
// registry, a pre-configured instantiation of a registry that should be
|
||||
// sufficient for most use-cases.
|
||||
package registry
|
||||
|
||||
import (
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/metric"
|
||||
)
|
||||
|
||||
// Registry is the interface for the metrics registry.
|
||||
type Registry interface {
|
||||
// Register registers a new Collector to be included in metrics
|
||||
// collection. It returns an error if the descriptors provided by the
|
||||
// Collector are invalid or if they - in combination with descriptors of
|
||||
// already registered Collectors - do not fulfill the consistency and
|
||||
// uniqueness criteria described in the documentation of metric.Desc.
|
||||
//
|
||||
// If the provided Collector is equal to a Collector already registered
|
||||
// (which includes the case of re-registering the same Collector), the
|
||||
// returned error is an instance of AlreadyRegisteredError, which
|
||||
// contains the previously registered Collector.
|
||||
//
|
||||
// It is in general not safe to register the same Collector multiple
|
||||
// times concurrently.
|
||||
Register(metric.Collector) error
|
||||
// Unregister unregisters the Collector that equals the Collector passed
|
||||
// in as an argument. The function returns whether a Collector was
|
||||
// unregistered.
|
||||
Unregister(metric.Collector) bool
|
||||
// Collect returns a channel that yields MetricFamily protobufs
|
||||
// (collected from registered collectors) together with applicable
|
||||
// errors. The metric family pointer returned with an error could be nil
|
||||
// or point to a (presumably incomplete) metric family. Once all
|
||||
// MetricFamilies have been read, the channel is closed. To not leak
|
||||
// resources, the channel must always be read until closed, even if one
|
||||
// ore more errors have been returned. If names is nil or empty, all
|
||||
// MetricFamilies are returned. Otherwise, only MetricFamilies with a
|
||||
// name contained in names are returned. Implementations should aim for
|
||||
// lexicographical sorting of MetricFamilies if the resource cost of
|
||||
// sorting is not prohibitive.
|
||||
Collect(names map[string]struct{}) <-chan struct {
|
||||
*dto.MetricFamily
|
||||
error
|
||||
}
|
||||
}
|
||||
|
||||
// Opts are options for the instantiation of new registries. The zero value of
|
||||
// Opts is a safe default.
|
||||
type Opts struct {
|
||||
// If true, metrics are checked for consistency during collection. The
|
||||
// check has a performance overhead and is not necessary with
|
||||
// well-behaved collectors. It can be helpful to enable the check while
|
||||
// working with custom Collectors whose correctness is not well
|
||||
// established yet or where inconsistent collection might happen by
|
||||
// design.
|
||||
CollectCheckEnabled bool
|
||||
// If true, the channel returned by the Collect method will never yield
|
||||
// an error (so that no error handling has to be implemented when
|
||||
// receiving from the channel). Instead, the program will panic. This
|
||||
// behavior is useful in programs where collect errors cannot (or must
|
||||
// not) happen.
|
||||
PanicOnCollectError bool
|
||||
// The MetricFamilyInjectionHook is a function that is called whenever
|
||||
// metrics are collected. The MetricFamily protobufs returned by the
|
||||
// hook function are merged with the metrics collected in the usual way.
|
||||
//
|
||||
// This is a way to directly inject MetricFamily protobufs managed and
|
||||
// owned by the caller. The caller has full responsibility. As no
|
||||
// registration of the injected metrics has happened, there was no check
|
||||
// at registration-time. If CollectCheckEnabled is false, only very
|
||||
// limited sanity checks are performed on the returned protobufs.
|
||||
//
|
||||
// Sorting concerns: The caller is responsible for sorting the label
|
||||
// pairs in each metric. However, the order of metrics will be sorted by
|
||||
// the registry as it is required anyway after merging with the metric
|
||||
// families collected conventionally.
|
||||
//
|
||||
// The function must be callable at any time and concurrently.
|
||||
MetricFamilyInjectionHook func() []*dto.MetricFamily
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// 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.
|
||||
|
||||
package registry
|
||||
|
||||
import "github.com/prometheus/client_golang/prometheus/metric"
|
||||
|
||||
func MustRegister(r Registry, c metric.Collector) {
|
||||
if err := r.Register(c); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func RegisterOrGet(r Registry, c metric.Collector) (metric.Collector, error) {
|
||||
if err := r.Register(c); err != nil {
|
||||
if are, ok := err.(AlreadyRegisteredError); ok {
|
||||
return are.ExistingCollector, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func MustRegisterOrGet(r Registry, c metric.Collector) metric.Collector {
|
||||
existing, err := RegisterOrGet(r, c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return existing
|
||||
}
|
|
@ -241,6 +241,7 @@ func (m *MetricVec) getOrCreateMetric(hash uint64, labelValues ...string) Metric
|
|||
if !ok {
|
||||
// Copy labelValues. Otherwise, they would be allocated even if we don't go
|
||||
// down this code path.
|
||||
// TODO: Use copy.
|
||||
copiedLabelValues := append(make([]string, 0, len(labelValues)), labelValues...)
|
||||
metric = m.newMetric(copiedLabelValues...)
|
||||
m.children[hash] = metric
|
||||
|
|
Loading…
Reference in New Issue