value.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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.
  69. func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) (Metric, error) {
  70. if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil {
  71. return nil, err
  72. }
  73. return &constMetric{
  74. desc: desc,
  75. valType: valueType,
  76. val: value,
  77. labelPairs: makeLabelPairs(desc, labelValues),
  78. }, nil
  79. }
  80. // MustNewConstMetric is a version of NewConstMetric that panics where
  81. // NewConstMetric would have returned an error.
  82. func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues ...string) Metric {
  83. m, err := NewConstMetric(desc, valueType, value, labelValues...)
  84. if err != nil {
  85. panic(err)
  86. }
  87. return m
  88. }
  89. type constMetric struct {
  90. desc *Desc
  91. valType ValueType
  92. val float64
  93. labelPairs []*dto.LabelPair
  94. }
  95. func (m *constMetric) Desc() *Desc {
  96. return m.desc
  97. }
  98. func (m *constMetric) Write(out *dto.Metric) error {
  99. return populateMetric(m.valType, m.val, m.labelPairs, out)
  100. }
  101. func populateMetric(
  102. t ValueType,
  103. v float64,
  104. labelPairs []*dto.LabelPair,
  105. m *dto.Metric,
  106. ) error {
  107. m.Label = labelPairs
  108. switch t {
  109. case CounterValue:
  110. m.Counter = &dto.Counter{Value: proto.Float64(v)}
  111. case GaugeValue:
  112. m.Gauge = &dto.Gauge{Value: proto.Float64(v)}
  113. case UntypedValue:
  114. m.Untyped = &dto.Untyped{Value: proto.Float64(v)}
  115. default:
  116. return fmt.Errorf("encountered unknown type %v", t)
  117. }
  118. return nil
  119. }
  120. func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
  121. totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
  122. if totalLen == 0 {
  123. // Super fast path.
  124. return nil
  125. }
  126. if len(desc.variableLabels) == 0 {
  127. // Moderately fast path.
  128. return desc.constLabelPairs
  129. }
  130. labelPairs := make([]*dto.LabelPair, 0, totalLen)
  131. for i, n := range desc.variableLabels {
  132. labelPairs = append(labelPairs, &dto.LabelPair{
  133. Name: proto.String(n),
  134. Value: proto.String(labelValues[i]),
  135. })
  136. }
  137. labelPairs = append(labelPairs, desc.constLabelPairs...)
  138. sort.Sort(labelPairSorter(labelPairs))
  139. return labelPairs
  140. }