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