metric.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. package prometheus
  14. import (
  15. "strings"
  16. dto "github.com/prometheus/client_model/go"
  17. )
  18. const separatorByte byte = 255
  19. // A Metric models a single sample value with its meta data being exported to
  20. // Prometheus. Implementations of Metric in this package are Gauge, Counter,
  21. // Histogram, Summary, and Untyped.
  22. type Metric interface {
  23. // Desc returns the descriptor for the Metric. This method idempotently
  24. // returns the same descriptor throughout the lifetime of the
  25. // Metric. The returned descriptor is immutable by contract. A Metric
  26. // unable to describe itself must return an invalid descriptor (created
  27. // with NewInvalidDesc).
  28. Desc() *Desc
  29. // Write encodes the Metric into a "Metric" Protocol Buffer data
  30. // transmission object.
  31. //
  32. // Metric implementations must observe concurrency safety as reads of
  33. // this metric may occur at any time, and any blocking occurs at the
  34. // expense of total performance of rendering all registered
  35. // metrics. Ideally, Metric implementations should support concurrent
  36. // readers.
  37. //
  38. // While populating dto.Metric, it is the responsibility of the
  39. // implementation to ensure validity of the Metric protobuf (like valid
  40. // UTF-8 strings or syntactically valid metric and label names). It is
  41. // recommended to sort labels lexicographically. (Implementers may find
  42. // LabelPairSorter useful for that.) Callers of Write should still make
  43. // sure of sorting if they depend on it.
  44. Write(*dto.Metric) error
  45. // TODO(beorn7): The original rationale of passing in a pre-allocated
  46. // dto.Metric protobuf to save allocations has disappeared. The
  47. // signature of this method should be changed to "Write() (*dto.Metric,
  48. // error)".
  49. }
  50. // Opts bundles the options for creating most Metric types. Each metric
  51. // implementation XXX has its own XXXOpts type, but in most cases, it is just be
  52. // an alias of this type (which might change when the requirement arises.)
  53. //
  54. // It is mandatory to set Name and Help to a non-empty string. All other fields
  55. // are optional and can safely be left at their zero value.
  56. type Opts struct {
  57. // Namespace, Subsystem, and Name are components of the fully-qualified
  58. // name of the Metric (created by joining these components with
  59. // "_"). Only Name is mandatory, the others merely help structuring the
  60. // name. Note that the fully-qualified name of the metric must be a
  61. // valid Prometheus metric name.
  62. Namespace string
  63. Subsystem string
  64. Name string
  65. // Help provides information about this metric. Mandatory!
  66. //
  67. // Metrics with the same fully-qualified name must have the same Help
  68. // string.
  69. Help string
  70. // ConstLabels are used to attach fixed labels to this metric. Metrics
  71. // with the same fully-qualified name must have the same label names in
  72. // their ConstLabels.
  73. //
  74. // Note that in most cases, labels have a value that varies during the
  75. // lifetime of a process. Those labels are usually managed with a metric
  76. // vector collector (like CounterVec, GaugeVec, UntypedVec). ConstLabels
  77. // serve only special purposes. One is for the special case where the
  78. // value of a label does not change during the lifetime of a process,
  79. // e.g. if the revision of the running binary is put into a
  80. // label. Another, more advanced purpose is if more than one Collector
  81. // needs to collect Metrics with the same fully-qualified name. In that
  82. // case, those Metrics must differ in the values of their
  83. // ConstLabels. See the Collector examples.
  84. //
  85. // If the value of a label never changes (not even between binaries),
  86. // that label most likely should not be a label at all (but part of the
  87. // metric name).
  88. ConstLabels Labels
  89. }
  90. // BuildFQName joins the given three name components by "_". Empty name
  91. // components are ignored. If the name parameter itself is empty, an empty
  92. // string is returned, no matter what. Metric implementations included in this
  93. // library use this function internally to generate the fully-qualified metric
  94. // name from the name component in their Opts. Users of the library will only
  95. // need this function if they implement their own Metric or instantiate a Desc
  96. // (with NewDesc) directly.
  97. func BuildFQName(namespace, subsystem, name string) string {
  98. if name == "" {
  99. return ""
  100. }
  101. switch {
  102. case namespace != "" && subsystem != "":
  103. return strings.Join([]string{namespace, subsystem, name}, "_")
  104. case namespace != "":
  105. return strings.Join([]string{namespace, name}, "_")
  106. case subsystem != "":
  107. return strings.Join([]string{subsystem, name}, "_")
  108. }
  109. return name
  110. }
  111. // LabelPairSorter implements sort.Interface. It is used to sort a slice of
  112. // dto.LabelPair pointers. This is useful for implementing the Write method of
  113. // custom metrics.
  114. type LabelPairSorter []*dto.LabelPair
  115. func (s LabelPairSorter) Len() int {
  116. return len(s)
  117. }
  118. func (s LabelPairSorter) Swap(i, j int) {
  119. s[i], s[j] = s[j], s[i]
  120. }
  121. func (s LabelPairSorter) Less(i, j int) bool {
  122. return s[i].GetName() < s[j].GetName()
  123. }
  124. type hashSorter []uint64
  125. func (s hashSorter) Len() int {
  126. return len(s)
  127. }
  128. func (s hashSorter) Swap(i, j int) {
  129. s[i], s[j] = s[j], s[i]
  130. }
  131. func (s hashSorter) Less(i, j int) bool {
  132. return s[i] < s[j]
  133. }
  134. type invalidMetric struct {
  135. desc *Desc
  136. err error
  137. }
  138. // NewInvalidMetric returns a metric whose Write method always returns the
  139. // provided error. It is useful if a Collector finds itself unable to collect
  140. // a metric and wishes to report an error to the registry.
  141. func NewInvalidMetric(desc *Desc, err error) Metric {
  142. return &invalidMetric{desc, err}
  143. }
  144. func (m *invalidMetric) Desc() *Desc { return m.desc }
  145. func (m *invalidMetric) Write(*dto.Metric) error { return m.err }