counter.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. "errors"
  16. )
  17. // Counter is a Metric that represents a single numerical value that only ever
  18. // goes up. That implies that it cannot be used to count items whose number can
  19. // also go down, e.g. the number of currently running goroutines. Those
  20. // "counters" are represented by Gauges.
  21. //
  22. // A Counter is typically used to count requests served, tasks completed, errors
  23. // occurred, etc.
  24. //
  25. // To create Counter instances, use NewCounter.
  26. type Counter interface {
  27. Metric
  28. Collector
  29. // Set is used to set the Counter to an arbitrary value. It is only used
  30. // if you have to transfer a value from an external counter into this
  31. // Prometheus metric. Do not use it for regular handling of a
  32. // Prometheus counter (as it can be used to break the contract of
  33. // monotonically increasing values).
  34. //
  35. // Deprecated: Use NewConstMetric to create a counter for an external
  36. // value. A Counter should never be set.
  37. Set(float64)
  38. // Inc increments the counter by 1.
  39. Inc()
  40. // Add adds the given value to the counter. It panics if the value is <
  41. // 0.
  42. Add(float64)
  43. }
  44. // CounterOpts is an alias for Opts. See there for doc comments.
  45. type CounterOpts Opts
  46. // NewCounter creates a new Counter based on the provided CounterOpts.
  47. func NewCounter(opts CounterOpts) Counter {
  48. desc := NewDesc(
  49. BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
  50. opts.Help,
  51. nil,
  52. opts.ConstLabels,
  53. )
  54. result := &counter{value: value{desc: desc, valType: CounterValue, labelPairs: desc.constLabelPairs}}
  55. result.init(result) // Init self-collection.
  56. return result
  57. }
  58. type counter struct {
  59. value
  60. }
  61. func (c *counter) Add(v float64) {
  62. if v < 0 {
  63. panic(errors.New("counter cannot decrease in value"))
  64. }
  65. c.value.Add(v)
  66. }
  67. // CounterVec is a Collector that bundles a set of Counters that all share the
  68. // same Desc, but have different values for their variable labels. This is used
  69. // if you want to count the same thing partitioned by various dimensions
  70. // (e.g. number of HTTP requests, partitioned by response code and
  71. // method). Create instances with NewCounterVec.
  72. //
  73. // CounterVec embeds MetricVec. See there for a full list of methods with
  74. // detailed documentation.
  75. type CounterVec struct {
  76. *MetricVec
  77. }
  78. // NewCounterVec creates a new CounterVec based on the provided CounterOpts and
  79. // partitioned by the given label names. At least one label name must be
  80. // provided.
  81. func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
  82. desc := NewDesc(
  83. BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
  84. opts.Help,
  85. labelNames,
  86. opts.ConstLabels,
  87. )
  88. return &CounterVec{
  89. MetricVec: newMetricVec(desc, func(lvs ...string) Metric {
  90. result := &counter{value: value{
  91. desc: desc,
  92. valType: CounterValue,
  93. labelPairs: makeLabelPairs(desc, lvs),
  94. }}
  95. result.init(result) // Init self-collection.
  96. return result
  97. }),
  98. }
  99. }
  100. // GetMetricWithLabelValues replaces the method of the same name in
  101. // MetricVec. The difference is that this method returns a Counter and not a
  102. // Metric so that no type conversion is required.
  103. func (m *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
  104. metric, err := m.MetricVec.GetMetricWithLabelValues(lvs...)
  105. if metric != nil {
  106. return metric.(Counter), err
  107. }
  108. return nil, err
  109. }
  110. // GetMetricWith replaces the method of the same name in MetricVec. The
  111. // difference is that this method returns a Counter and not a Metric so that no
  112. // type conversion is required.
  113. func (m *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
  114. metric, err := m.MetricVec.GetMetricWith(labels)
  115. if metric != nil {
  116. return metric.(Counter), err
  117. }
  118. return nil, err
  119. }
  120. // WithLabelValues works as GetMetricWithLabelValues, but panics where
  121. // GetMetricWithLabelValues would have returned an error. By not returning an
  122. // error, WithLabelValues allows shortcuts like
  123. // myVec.WithLabelValues("404", "GET").Add(42)
  124. func (m *CounterVec) WithLabelValues(lvs ...string) Counter {
  125. return m.MetricVec.WithLabelValues(lvs...).(Counter)
  126. }
  127. // With works as GetMetricWith, but panics where GetMetricWithLabels would have
  128. // returned an error. By not returning an error, With allows shortcuts like
  129. // myVec.With(Labels{"code": "404", "method": "GET"}).Add(42)
  130. func (m *CounterVec) With(labels Labels) Counter {
  131. return m.MetricVec.With(labels).(Counter)
  132. }
  133. // CounterFunc is a Counter whose value is determined at collect time by calling a
  134. // provided function.
  135. //
  136. // To create CounterFunc instances, use NewCounterFunc.
  137. type CounterFunc interface {
  138. Metric
  139. Collector
  140. }
  141. // NewCounterFunc creates a new CounterFunc based on the provided
  142. // CounterOpts. The value reported is determined by calling the given function
  143. // from within the Write method. Take into account that metric collection may
  144. // happen concurrently. If that results in concurrent calls to Write, like in
  145. // the case where a CounterFunc is directly registered with Prometheus, the
  146. // provided function must be concurrency-safe. The function should also honor
  147. // the contract for a Counter (values only go up, not down), but compliance will
  148. // not be checked.
  149. func NewCounterFunc(opts CounterOpts, function func() float64) CounterFunc {
  150. return newValueFunc(NewDesc(
  151. BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
  152. opts.Help,
  153. nil,
  154. opts.ConstLabels,
  155. ), CounterValue, function)
  156. }