value.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. "fmt"
  16. "sort"
  17. "github.com/golang/protobuf/proto"
  18. dto "github.com/prometheus/client_model/go"
  19. )
  20. // ValueType is an enumeration of metric types that represent a simple value.
  21. type ValueType int
  22. // Possible values for the ValueType enum.
  23. const (
  24. _ ValueType = iota
  25. CounterValue
  26. GaugeValue
  27. UntypedValue
  28. )
  29. // valueFunc is a generic metric for simple values retrieved on collect time
  30. // from a function. It implements Metric and Collector. Its effective type is
  31. // determined by ValueType. This is a low-level building block used by the
  32. // library to back the implementations of CounterFunc, GaugeFunc, and
  33. // UntypedFunc.
  34. type valueFunc struct {
  35. selfCollector
  36. desc *Desc
  37. valType ValueType
  38. function func() float64
  39. labelPairs []*dto.LabelPair
  40. }
  41. // newValueFunc returns a newly allocated valueFunc with the given Desc and
  42. // ValueType. The value reported is determined by calling the given function
  43. // from within the Write method. Take into account that metric collection may
  44. // happen concurrently. If that results in concurrent calls to Write, like in
  45. // the case where a valueFunc is directly registered with Prometheus, the
  46. // provided function must be concurrency-safe.
  47. func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *valueFunc {
  48. result := &valueFunc{
  49. desc: desc,
  50. valType: valueType,
  51. function: function,
  52. labelPairs: makeLabelPairs(desc, nil),
  53. }
  54. result.init(result)
  55. return result
  56. }
  57. func (v *valueFunc) Desc() *Desc {
  58. return v.desc
  59. }
  60. func (v *valueFunc) Write(out *dto.Metric) error {
  61. return populateMetric(v.valType, v.function(), v.labelPairs, out)
  62. }
  63. // NewConstMetric returns a metric with one fixed value that cannot be
  64. // changed. Users of this package will not have much use for it in regular
  65. // operations. However, when implementing custom Collectors, it is useful as a
  66. // throw-away metric that is generated on the fly to send it to Prometheus in
  67. // the Collect method. NewConstMetric returns an error if the length of
  68. // labelValues is not consistent with the variable labels in Desc or if Desc is
  69. // invalid.
  70. func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) {
  71. if desc.err != nil {
  72. return nil, desc.err
  73. }
  74. if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
  75. return nil, err
  76. }
  77. return &constMetric{
  78. desc: desc,
  79. valType: valueType,
  80. val: value,
  81. labelPairs: makeLabelPairs(desc, labelValues),
  82. }, nil
  83. }
  84. // MustNewConstMetric is a version of NewConstMetric that panics where
  85. // NewConstMetric would have returned an error.
  86. func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric {
  87. m, err := NewConstMetric(desc, valueType, value, labelValues...)
  88. if err != nil {
  89. panic(err)
  90. }
  91. return m
  92. }
  93. type constMetric struct {
  94. desc *Desc
  95. valType ValueType
  96. val float64
  97. labelPairs []*dto.LabelPair
  98. }
  99. func (m *constMetric) Desc() *Desc {
  100. return m.desc
  101. }
  102. func (m *constMetric) Write(out *dto.Metric) error {
  103. return populateMetric(m.valType, m.val, m.labelPairs, out)
  104. }
  105. func populateMetric(
  106. t ValueType,
  107. v float64,
  108. labelPairs []*dto.LabelPair,
  109. m *dto.Metric,
  110. ) error {
  111. m.Label = labelPairs
  112. switch t {
  113. case CounterValue:
  114. m.Counter = &dto.Counter{Value: proto.Float64(v)}
  115. case GaugeValue:
  116. m.Gauge = &dto.Gauge{Value: proto.Float64(v)}
  117. case UntypedValue:
  118. m.Untyped = &dto.Untyped{Value: proto.Float64(v)}
  119. default:
  120. return fmt.Errorf("encountered unknown type %v", t)
  121. }
  122. return nil
  123. }
  124. func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
  125. totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
  126. if totalLen == 0 {
  127. // Super fast path.
  128. return nil
  129. }
  130. if len(desc.variableLabels) == 0 {
  131. // Moderately fast path.
  132. return desc.constLabelPairs
  133. }
  134. labelPairs := make([]*dto.LabelPair, 0, totalLen)
  135. for i, n := range desc.variableLabels {
  136. labelPairs = append(labelPairs, &dto.LabelPair{
  137. Name: proto.String(n),
  138. Value: proto.String(labelValues[i]),
  139. })
  140. }
  141. labelPairs = append(labelPairs, desc.constLabelPairs...)
  142. sort.Sort(labelPairSorter(labelPairs))
  143. return labelPairs
  144. }