1// Copyright 2014 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package prometheus
15
16import (
17	"strings"
18
19	dto "github.com/coreos/etcd/Godeps/_workspace/src/github.com/prometheus/client_model/go"
20)
21
22const separatorByte byte = 255
23
24// A Metric models a single sample value with its meta data being exported to
25// Prometheus. Implementers of Metric in this package inclued Gauge, Counter,
26// Untyped, and Summary. Users can implement their own Metric types, but that
27// should be rarely needed. See the example for SelfCollector, which is also an
28// example for a user-implemented Metric.
29type Metric interface {
30	// Desc returns the descriptor for the Metric. This method idempotently
31	// returns the same descriptor throughout the lifetime of the
32	// Metric. The returned descriptor is immutable by contract. A Metric
33	// unable to describe itself must return an invalid descriptor (created
34	// with NewInvalidDesc).
35	Desc() *Desc
36	// Write encodes the Metric into a "Metric" Protocol Buffer data
37	// transmission object.
38	//
39	// Implementers of custom Metric types must observe concurrency safety
40	// as reads of this metric may occur at any time, and any blocking
41	// occurs at the expense of total performance of rendering all
42	// registered metrics. Ideally Metric implementations should support
43	// concurrent readers.
44	//
45	// The Prometheus client library attempts to minimize memory allocations
46	// and will provide a pre-existing reset dto.Metric pointer. Prometheus
47	// may recycle the dto.Metric proto message, so Metric implementations
48	// should just populate the provided dto.Metric and then should not keep
49	// any reference to it.
50	//
51	// While populating dto.Metric, labels must be sorted lexicographically.
52	// (Implementers may find LabelPairSorter useful for that.)
53	Write(*dto.Metric) error
54}
55
56// Opts bundles the options for creating most Metric types. Each metric
57// implementation XXX has its own XXXOpts type, but in most cases, it is just be
58// an alias of this type (which might change when the requirement arises.)
59//
60// It is mandatory to set Name and Help to a non-empty string. All other fields
61// are optional and can safely be left at their zero value.
62type Opts struct {
63	// Namespace, Subsystem, and Name are components of the fully-qualified
64	// name of the Metric (created by joining these components with
65	// "_"). Only Name is mandatory, the others merely help structuring the
66	// name. Note that the fully-qualified name of the metric must be a
67	// valid Prometheus metric name.
68	Namespace string
69	Subsystem string
70	Name      string
71
72	// Help provides information about this metric. Mandatory!
73	//
74	// Metrics with the same fully-qualified name must have the same Help
75	// string.
76	Help string
77
78	// ConstLabels are used to attach fixed labels to this metric. Metrics
79	// with the same fully-qualified name must have the same label names in
80	// their ConstLabels.
81	//
82	// Note that in most cases, labels have a value that varies during the
83	// lifetime of a process. Those labels are usually managed with a metric
84	// vector collector (like CounterVec, GaugeVec, UntypedVec). ConstLabels
85	// serve only special purposes. One is for the special case where the
86	// value of a label does not change during the lifetime of a process,
87	// e.g. if the revision of the running binary is put into a
88	// label. Another, more advanced purpose is if more than one Collector
89	// needs to collect Metrics with the same fully-qualified name. In that
90	// case, those Metrics must differ in the values of their
91	// ConstLabels. See the Collector examples.
92	//
93	// If the value of a label never changes (not even between binaries),
94	// that label most likely should not be a label at all (but part of the
95	// metric name).
96	ConstLabels Labels
97}
98
99// BuildFQName joins the given three name components by "_". Empty name
100// components are ignored. If the name parameter itself is empty, an empty
101// string is returned, no matter what. Metric implementations included in this
102// library use this function internally to generate the fully-qualified metric
103// name from the name component in their Opts. Users of the library will only
104// need this function if they implement their own Metric or instantiate a Desc
105// (with NewDesc) directly.
106func BuildFQName(namespace, subsystem, name string) string {
107	if name == "" {
108		return ""
109	}
110	switch {
111	case namespace != "" && subsystem != "":
112		return strings.Join([]string{namespace, subsystem, name}, "_")
113	case namespace != "":
114		return strings.Join([]string{namespace, name}, "_")
115	case subsystem != "":
116		return strings.Join([]string{subsystem, name}, "_")
117	}
118	return name
119}
120
121// LabelPairSorter implements sort.Interface. It is used to sort a slice of
122// dto.LabelPair pointers. This is useful for implementing the Write method of
123// custom metrics.
124type LabelPairSorter []*dto.LabelPair
125
126func (s LabelPairSorter) Len() int {
127	return len(s)
128}
129
130func (s LabelPairSorter) Swap(i, j int) {
131	s[i], s[j] = s[j], s[i]
132}
133
134func (s LabelPairSorter) Less(i, j int) bool {
135	return s[i].GetName() < s[j].GetName()
136}
137
138type hashSorter []uint64
139
140func (s hashSorter) Len() int {
141	return len(s)
142}
143
144func (s hashSorter) Swap(i, j int) {
145	s[i], s[j] = s[j], s[i]
146}
147
148func (s hashSorter) Less(i, j int) bool {
149	return s[i] < s[j]
150}
151
152type invalidMetric struct {
153	desc *Desc
154	err  error
155}
156
157// NewInvalidMetric returns a metric whose Write method always returns the
158// provided error. It is useful if a Collector finds itself unable to collect
159// a metric and wishes to report an error to the registry.
160func NewInvalidMetric(desc *Desc, err error) Metric {
161	return &invalidMetric{desc, err}
162}
163
164func (m *invalidMetric) Desc() *Desc { return m.desc }
165
166func (m *invalidMetric) Write(*dto.Metric) error { return m.err }
167