Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

290 linhas
9.8 KiB

  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. "math"
  16. "sync/atomic"
  17. "time"
  18. dto "github.com/prometheus/client_model/go"
  19. )
  20. // Gauge is a Metric that represents a single numerical value that can
  21. // arbitrarily go up and down.
  22. //
  23. // A Gauge is typically used for measured values like temperatures or current
  24. // memory usage, but also "counts" that can go up and down, like the number of
  25. // running goroutines.
  26. //
  27. // To create Gauge instances, use NewGauge.
  28. type Gauge interface {
  29. Metric
  30. Collector
  31. // Set sets the Gauge to an arbitrary value.
  32. Set(float64)
  33. // Inc increments the Gauge by 1. Use Add to increment it by arbitrary
  34. // values.
  35. Inc()
  36. // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
  37. // values.
  38. Dec()
  39. // Add adds the given value to the Gauge. (The value can be negative,
  40. // resulting in a decrease of the Gauge.)
  41. Add(float64)
  42. // Sub subtracts the given value from the Gauge. (The value can be
  43. // negative, resulting in an increase of the Gauge.)
  44. Sub(float64)
  45. // SetToCurrentTime sets the Gauge to the current Unix time in seconds.
  46. SetToCurrentTime()
  47. }
  48. // GaugeOpts is an alias for Opts. See there for doc comments.
  49. type GaugeOpts Opts
  50. // NewGauge creates a new Gauge based on the provided GaugeOpts.
  51. //
  52. // The returned implementation is optimized for a fast Set method. If you have a
  53. // choice for managing the value of a Gauge via Set vs. Inc/Dec/Add/Sub, pick
  54. // the former. For example, the Inc method of the returned Gauge is slower than
  55. // the Inc method of a Counter returned by NewCounter. This matches the typical
  56. // scenarios for Gauges and Counters, where the former tends to be Set-heavy and
  57. // the latter Inc-heavy.
  58. func NewGauge(opts GaugeOpts) Gauge {
  59. desc := NewDesc(
  60. BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
  61. opts.Help,
  62. nil,
  63. opts.ConstLabels,
  64. )
  65. result := &gauge{desc: desc, labelPairs: desc.constLabelPairs}
  66. result.init(result) // Init self-collection.
  67. return result
  68. }
  69. type gauge struct {
  70. // valBits contains the bits of the represented float64 value. It has
  71. // to go first in the struct to guarantee alignment for atomic
  72. // operations. http://golang.org/pkg/sync/atomic/#pkg-note-BUG
  73. valBits uint64
  74. selfCollector
  75. desc *Desc
  76. labelPairs []*dto.LabelPair
  77. }
  78. func (g *gauge) Desc() *Desc {
  79. return g.desc
  80. }
  81. func (g *gauge) Set(val float64) {
  82. atomic.StoreUint64(&g.valBits, math.Float64bits(val))
  83. }
  84. func (g *gauge) SetToCurrentTime() {
  85. g.Set(float64(time.Now().UnixNano()) / 1e9)
  86. }
  87. func (g *gauge) Inc() {
  88. g.Add(1)
  89. }
  90. func (g *gauge) Dec() {
  91. g.Add(-1)
  92. }
  93. func (g *gauge) Add(val float64) {
  94. for {
  95. oldBits := atomic.LoadUint64(&g.valBits)
  96. newBits := math.Float64bits(math.Float64frombits(oldBits) + val)
  97. if atomic.CompareAndSwapUint64(&g.valBits, oldBits, newBits) {
  98. return
  99. }
  100. }
  101. }
  102. func (g *gauge) Sub(val float64) {
  103. g.Add(val * -1)
  104. }
  105. func (g *gauge) Write(out *dto.Metric) error {
  106. val := math.Float64frombits(atomic.LoadUint64(&g.valBits))
  107. return populateMetric(GaugeValue, val, g.labelPairs, nil, out)
  108. }
  109. // GaugeVec is a Collector that bundles a set of Gauges that all share the same
  110. // Desc, but have different values for their variable labels. This is used if
  111. // you want to count the same thing partitioned by various dimensions
  112. // (e.g. number of operations queued, partitioned by user and operation
  113. // type). Create instances with NewGaugeVec.
  114. type GaugeVec struct {
  115. *MetricVec
  116. }
  117. // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
  118. // partitioned by the given label names.
  119. func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
  120. desc := NewDesc(
  121. BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
  122. opts.Help,
  123. labelNames,
  124. opts.ConstLabels,
  125. )
  126. return &GaugeVec{
  127. MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
  128. if len(lvs) != len(desc.variableLabels) {
  129. panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
  130. }
  131. result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)}
  132. result.init(result) // Init self-collection.
  133. return result
  134. }),
  135. }
  136. }
  137. // GetMetricWithLabelValues returns the Gauge for the given slice of label
  138. // values (same order as the variable labels in Desc). If that combination of
  139. // label values is accessed for the first time, a new Gauge is created.
  140. //
  141. // It is possible to call this method without using the returned Gauge to only
  142. // create the new Gauge but leave it at its starting value 0. See also the
  143. // SummaryVec example.
  144. //
  145. // Keeping the Gauge for later use is possible (and should be considered if
  146. // performance is critical), but keep in mind that Reset, DeleteLabelValues and
  147. // Delete can be used to delete the Gauge from the GaugeVec. In that case, the
  148. // Gauge will still exist, but it will not be exported anymore, even if a
  149. // Gauge with the same label values is created later. See also the CounterVec
  150. // example.
  151. //
  152. // An error is returned if the number of label values is not the same as the
  153. // number of variable labels in Desc (minus any curried labels).
  154. //
  155. // Note that for more than one label value, this method is prone to mistakes
  156. // caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
  157. // an alternative to avoid that type of mistake. For higher label numbers, the
  158. // latter has a much more readable (albeit more verbose) syntax, but it comes
  159. // with a performance overhead (for creating and processing the Labels map).
  160. func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
  161. metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
  162. if metric != nil {
  163. return metric.(Gauge), err
  164. }
  165. return nil, err
  166. }
  167. // GetMetricWith returns the Gauge for the given Labels map (the label names
  168. // must match those of the variable labels in Desc). If that label map is
  169. // accessed for the first time, a new Gauge is created. Implications of
  170. // creating a Gauge without using it and keeping the Gauge for later use are
  171. // the same as for GetMetricWithLabelValues.
  172. //
  173. // An error is returned if the number and names of the Labels are inconsistent
  174. // with those of the variable labels in Desc (minus any curried labels).
  175. //
  176. // This method is used for the same purpose as
  177. // GetMetricWithLabelValues(...string). See there for pros and cons of the two
  178. // methods.
  179. func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
  180. metric, err := v.MetricVec.GetMetricWith(labels)
  181. if metric != nil {
  182. return metric.(Gauge), err
  183. }
  184. return nil, err
  185. }
  186. // WithLabelValues works as GetMetricWithLabelValues, but panics where
  187. // GetMetricWithLabelValues would have returned an error. Not returning an
  188. // error allows shortcuts like
  189. // myVec.WithLabelValues("404", "GET").Add(42)
  190. func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge {
  191. g, err := v.GetMetricWithLabelValues(lvs...)
  192. if err != nil {
  193. panic(err)
  194. }
  195. return g
  196. }
  197. // With works as GetMetricWith, but panics where GetMetricWithLabels would have
  198. // returned an error. Not returning an error allows shortcuts like
  199. // myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42)
  200. func (v *GaugeVec) With(labels Labels) Gauge {
  201. g, err := v.GetMetricWith(labels)
  202. if err != nil {
  203. panic(err)
  204. }
  205. return g
  206. }
  207. // CurryWith returns a vector curried with the provided labels, i.e. the
  208. // returned vector has those labels pre-set for all labeled operations performed
  209. // on it. The cardinality of the curried vector is reduced accordingly. The
  210. // order of the remaining labels stays the same (just with the curried labels
  211. // taken out of the sequence – which is relevant for the
  212. // (GetMetric)WithLabelValues methods). It is possible to curry a curried
  213. // vector, but only with labels not yet used for currying before.
  214. //
  215. // The metrics contained in the GaugeVec are shared between the curried and
  216. // uncurried vectors. They are just accessed differently. Curried and uncurried
  217. // vectors behave identically in terms of collection. Only one must be
  218. // registered with a given registry (usually the uncurried version). The Reset
  219. // method deletes all metrics, even if called on a curried vector.
  220. func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
  221. vec, err := v.MetricVec.CurryWith(labels)
  222. if vec != nil {
  223. return &GaugeVec{vec}, err
  224. }
  225. return nil, err
  226. }
  227. // MustCurryWith works as CurryWith but panics where CurryWith would have
  228. // returned an error.
  229. func (v *GaugeVec) MustCurryWith(labels Labels) *GaugeVec {
  230. vec, err := v.CurryWith(labels)
  231. if err != nil {
  232. panic(err)
  233. }
  234. return vec
  235. }
  236. // GaugeFunc is a Gauge whose value is determined at collect time by calling a
  237. // provided function.
  238. //
  239. // To create GaugeFunc instances, use NewGaugeFunc.
  240. type GaugeFunc interface {
  241. Metric
  242. Collector
  243. }
  244. // NewGaugeFunc creates a new GaugeFunc based on the provided GaugeOpts. The
  245. // value reported is determined by calling the given function from within the
  246. // Write method. Take into account that metric collection may happen
  247. // concurrently. Therefore, it must be safe to call the provided function
  248. // concurrently.
  249. //
  250. // NewGaugeFunc is a good way to create an “info” style metric with a constant
  251. // value of 1. Example:
  252. // https://github.com/prometheus/common/blob/8558a5b7db3c84fa38b4766966059a7bd5bfa2ee/version/info.go#L36-L56
  253. func NewGaugeFunc(opts GaugeOpts, function func() float64) GaugeFunc {
  254. return newValueFunc(NewDesc(
  255. BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
  256. opts.Help,
  257. nil,
  258. opts.ConstLabels,
  259. ), GaugeValue, function)
  260. }