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
|
// already implemented in this library are the metric vectors (i.e. collection
|
||||||
// of multiple instances of the same Metric but with different label values)
|
// of multiple instances of the same Metric but with different label values)
|
||||||
// like GaugeVec or SummaryVec, and the ExpvarCollector.
|
// 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 {
|
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
|
||||||
|
@ -46,7 +49,9 @@ type Collector interface {
|
||||||
// therefore be implemented in a concurrency safe way. Blocking occurs
|
// therefore be implemented in a concurrency safe way. Blocking occurs
|
||||||
// at the expense of total performance of rendering all registered
|
// at the expense of total performance of rendering all registered
|
||||||
// metrics. Ideally, Collector implementations support concurrent
|
// 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)
|
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
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// 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 {
|
type processCollector struct {
|
||||||
pid int
|
pid int
|
||||||
collectFn func(chan<- Metric)
|
collectFn func(chan<- metric.Metric)
|
||||||
pidFn func() (int, error)
|
pidFn func() (int, error)
|
||||||
cpuTotal Counter
|
cpuTotal Counter
|
||||||
openFDs, maxFDs Gauge
|
openFDs, maxFDs Gauge
|
|
@ -1,4 +1,4 @@
|
||||||
package prometheus
|
package collectors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
|
@ -30,6 +31,197 @@ const reservedLabelPrefix = "__"
|
||||||
// create a Desc.
|
// create a Desc.
|
||||||
type Labels map[string]string
|
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
|
// Desc is the descriptor used by every Prometheus Metric. It is essentially
|
||||||
// the immutable meta-data of a Metric. The normal Metric implementations
|
// 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
|
// 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{}{}
|
labelNameSet := map[string]struct{}{}
|
||||||
// First add only the const label names and sort them...
|
// First add only the const label names and sort them...
|
||||||
for labelName := range constLabels {
|
for labelName := range constLabels {
|
||||||
if !checkLabelName(labelName) {
|
if !validLabelName(labelName) {
|
||||||
d.err = fmt.Errorf("%q is not a valid label name", labelName)
|
d.err = fmt.Errorf("%q is not a valid label name", labelName)
|
||||||
return d
|
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
|
// cannot be in a regular label name. That prevents matching the label
|
||||||
// dimension with a different mix between preset and variable labels.
|
// dimension with a different mix between preset and variable labels.
|
||||||
for _, labelName := range variableLabels {
|
for _, labelName := range variableLabels {
|
||||||
if !checkLabelName(labelName) {
|
if !validLabelName(labelName) {
|
||||||
d.err = fmt.Errorf("%q is not a valid label name", labelName)
|
d.err = fmt.Errorf("%q is not a valid label name", labelName)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
@ -159,16 +351,6 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
|
||||||
return d
|
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 {
|
func (d *Desc) String() string {
|
||||||
lpStrings := make([]string, 0, len(d.constLabelPairs))
|
lpStrings := make([]string, 0, len(d.constLabelPairs))
|
||||||
for _, lp := range d.constLabelPairs {
|
for _, lp := range d.constLabelPairs {
|
||||||
|
@ -185,8 +367,3 @@ func (d *Desc) String() string {
|
||||||
d.variableLabels,
|
d.variableLabels,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkLabelName(l string) bool {
|
|
||||||
return labelNameRE.MatchString(l) &&
|
|
||||||
!strings.HasPrefix(l, reservedLabelPrefix)
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,11 +13,7 @@
|
||||||
|
|
||||||
package prometheus
|
package prometheus
|
||||||
|
|
||||||
import (
|
import dto "github.com/prometheus/client_model/go"
|
||||||
"strings"
|
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
|
||||||
)
|
|
||||||
|
|
||||||
const separatorByte byte = 255
|
const separatorByte byte = 255
|
||||||
|
|
||||||
|
@ -53,6 +49,42 @@ type Metric interface {
|
||||||
Write(*dto.Metric) error
|
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
|
// 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
|
// 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.)
|
// an alias of this type (which might change when the requirement arises.)
|
||||||
|
@ -96,28 +128,6 @@ type Opts struct {
|
||||||
ConstLabels Labels
|
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
|
// LabelPairSorter implements sort.Interface. It is used to sort a slice of
|
||||||
// dto.LabelPair pointers. This is useful for implementing the Write method of
|
// dto.LabelPair pointers. This is useful for implementing the Write method of
|
||||||
// custom metrics.
|
// custom metrics.
|
||||||
|
@ -150,17 +160,18 @@ func (s hashSorter) Less(i, j int) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
type invalidMetric struct {
|
type invalidMetric struct {
|
||||||
desc *Desc
|
desc Desc
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInvalidMetric returns a metric whose Write method always returns the
|
// NewInvalidMetric returns a metric whose Write method always returns the
|
||||||
// provided error. It is useful if a Collector finds itself unable to collect
|
// provided error, and whose descriptor is invalid, carrying the provided
|
||||||
// a metric and wishes to report an error to the registry.
|
// error. It is useful if a Collector finds itself unable to collect a metric
|
||||||
func NewInvalidMetric(desc *Desc, err error) Metric {
|
// and wishes to report an error to the registry.
|
||||||
return &invalidMetric{desc, err}
|
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 }
|
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.
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
// You may obtain a copy of the License at
|
// You may obtain a copy of the License at
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
// 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
|
package promhttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
@ -23,6 +23,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: Rework handler instrumentation (histograms, more configurable...).
|
||||||
|
|
||||||
var instLabels = []string{"method", "code"}
|
var instLabels = []string{"method", "code"}
|
||||||
|
|
||||||
type nower interface {
|
type nower interface {
|
|
@ -27,7 +27,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -36,56 +35,19 @@ import (
|
||||||
"github.com/prometheus/common/expfmt"
|
"github.com/prometheus/common/expfmt"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// Handler returns an instrumented HTTP handler for the default Prometheus
|
||||||
defRegistry = newDefaultRegistry()
|
// registry. It is already instrumented with InstrumentHandler (using
|
||||||
errAlreadyReg = errors.New("duplicate metrics collector registration attempted")
|
// "prometheus" as handler name). Usually the handler is used to handle the
|
||||||
)
|
// "/metrics" endpoint.
|
||||||
|
|
||||||
// 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.
|
|
||||||
func Handler() http.Handler {
|
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
|
// 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
|
// different handler name (or with a different instrumentation approach
|
||||||
// altogether). See the InstrumentHandler example.
|
// altogether). See the InstrumentHandler example.
|
||||||
func UninstrumentedHandler() http.Handler {
|
func UninstrumentedHandler() http.Handler {
|
||||||
return defRegistry
|
return promhttp.Handler(registry.Default)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register registers a new Collector to be included in metrics collection. It
|
// Register registers a new Collector to be included in metrics collection with
|
||||||
// returns an error if the descriptors provided by the Collector are invalid or
|
// the default registry. It returns an error if the descriptors provided by the
|
||||||
// if they - in combination with descriptors of already registered Collectors -
|
// Collector are invalid or if they - in combination with descriptors of already
|
||||||
// do not fulfill the consistency and uniqueness criteria described in the Desc
|
// registered Collectors - do not fulfill the consistency and uniqueness
|
||||||
// documentation.
|
// criteria described in the Desc documentation.
|
||||||
//
|
//
|
||||||
// Do not register the same Collector multiple times concurrently. (Registering
|
// 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,
|
// the same Collector twice would result in an error anyway, but on top of that,
|
||||||
// it is not safe to do so concurrently.)
|
// it is not safe to do so concurrently.)
|
||||||
func Register(m Collector) error {
|
func Register(c Collector) error {
|
||||||
_, err := defRegistry.Register(m)
|
return registry.Default.Register(c)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustRegister works like Register but panics where Register would have
|
// MustRegister works like Register but panics where Register would have
|
||||||
// returned an error.
|
// returned an error.
|
||||||
func MustRegister(m Collector) {
|
func MustRegister(c Collector) {
|
||||||
err := Register(m)
|
registry.MustRegister(registry.Default, c)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterOrGet works like Register but does not return an error if a Collector
|
// 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
|
// As for Register, it is still not safe to call RegisterOrGet with the same
|
||||||
// Collector multiple times concurrently.
|
// Collector multiple times concurrently.
|
||||||
func RegisterOrGet(m Collector) (Collector, error) {
|
func RegisterOrGet(c Collector) (Collector, error) {
|
||||||
return defRegistry.RegisterOrGet(m)
|
return registry.RegisterOrGet(registry.Default, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustRegisterOrGet works like Register but panics where RegisterOrGet would
|
// MustRegisterOrGet works like Register but panics where RegisterOrGet would
|
||||||
// have returned an error.
|
// have returned an error.
|
||||||
func MustRegisterOrGet(m Collector) Collector {
|
func MustRegisterOrGet(c Collector) Collector {
|
||||||
existing, err := RegisterOrGet(m)
|
return registry.MustRegisterOrGet(registry.Default, c)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return existing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unregister unregisters the Collector that equals the Collector passed in as
|
// 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
|
// yields the same set of descriptors.) The function returns whether a Collector
|
||||||
// was unregistered.
|
// was unregistered.
|
||||||
func Unregister(c Collector) bool {
|
func Unregister(c Collector) bool {
|
||||||
return defRegistry.Unregister(c)
|
return registry.Default.Unregister(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMetricFamilyInjectionHook sets a function that is called whenever metrics
|
// TODO: Move out from here.
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// encoder is a function that writes a dto.MetricFamily to an io.Writer in a
|
// 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
|
// 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{}{}
|
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 {
|
for desc := range descChan {
|
||||||
if _, exists := descIDs[desc.id]; !exists {
|
if _, exists := descIDs[desc.id]; !exists {
|
||||||
collectorID += desc.id
|
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
|
// decorateWriter wraps a writer to handle gzip compression if requested. It
|
||||||
// returns the decorated writer and the appropriate "Content-Encoding" header
|
// returns the decorated writer and the appropriate "Content-Encoding" header
|
||||||
// (which is empty if no compression is enabled).
|
// (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 {
|
if !ok {
|
||||||
// Copy labelValues. Otherwise, they would be allocated even if we don't go
|
// Copy labelValues. Otherwise, they would be allocated even if we don't go
|
||||||
// down this code path.
|
// down this code path.
|
||||||
|
// TODO: Use copy.
|
||||||
copiedLabelValues := append(make([]string, 0, len(labelValues)), labelValues...)
|
copiedLabelValues := append(make([]string, 0, len(labelValues)), labelValues...)
|
||||||
metric = m.newMetric(copiedLabelValues...)
|
metric = m.newMetric(copiedLabelValues...)
|
||||||
m.children[hash] = metric
|
m.children[hash] = metric
|
||||||
|
|
Loading…
Reference in New Issue