value_histogram.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright 2013 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 model
  14. import (
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "strconv"
  19. "strings"
  20. )
  21. type FloatString float64
  22. func (v FloatString) String() string {
  23. return strconv.FormatFloat(float64(v), 'f', -1, 64)
  24. }
  25. func (v FloatString) MarshalJSON() ([]byte, error) {
  26. return json.Marshal(v.String())
  27. }
  28. func (v *FloatString) UnmarshalJSON(b []byte) error {
  29. if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
  30. return errors.New("float value must be a quoted string")
  31. }
  32. f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
  33. if err != nil {
  34. return err
  35. }
  36. *v = FloatString(f)
  37. return nil
  38. }
  39. type HistogramBucket struct {
  40. Boundaries int32
  41. Lower FloatString
  42. Upper FloatString
  43. Count FloatString
  44. }
  45. func (s HistogramBucket) MarshalJSON() ([]byte, error) {
  46. b, err := json.Marshal(s.Boundaries)
  47. if err != nil {
  48. return nil, err
  49. }
  50. l, err := json.Marshal(s.Lower)
  51. if err != nil {
  52. return nil, err
  53. }
  54. u, err := json.Marshal(s.Upper)
  55. if err != nil {
  56. return nil, err
  57. }
  58. c, err := json.Marshal(s.Count)
  59. if err != nil {
  60. return nil, err
  61. }
  62. return []byte(fmt.Sprintf("[%s,%s,%s,%s]", b, l, u, c)), nil
  63. }
  64. func (s *HistogramBucket) UnmarshalJSON(buf []byte) error {
  65. tmp := []interface{}{&s.Boundaries, &s.Lower, &s.Upper, &s.Count}
  66. wantLen := len(tmp)
  67. if err := json.Unmarshal(buf, &tmp); err != nil {
  68. return err
  69. }
  70. if gotLen := len(tmp); gotLen != wantLen {
  71. return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen)
  72. }
  73. return nil
  74. }
  75. func (s *HistogramBucket) Equal(o *HistogramBucket) bool {
  76. return s == o || (s.Boundaries == o.Boundaries && s.Lower == o.Lower && s.Upper == o.Upper && s.Count == o.Count)
  77. }
  78. func (b HistogramBucket) String() string {
  79. var sb strings.Builder
  80. lowerInclusive := b.Boundaries == 1 || b.Boundaries == 3
  81. upperInclusive := b.Boundaries == 0 || b.Boundaries == 3
  82. if lowerInclusive {
  83. sb.WriteRune('[')
  84. } else {
  85. sb.WriteRune('(')
  86. }
  87. fmt.Fprintf(&sb, "%g,%g", b.Lower, b.Upper)
  88. if upperInclusive {
  89. sb.WriteRune(']')
  90. } else {
  91. sb.WriteRune(')')
  92. }
  93. fmt.Fprintf(&sb, ":%v", b.Count)
  94. return sb.String()
  95. }
  96. type HistogramBuckets []*HistogramBucket
  97. func (s HistogramBuckets) Equal(o HistogramBuckets) bool {
  98. if len(s) != len(o) {
  99. return false
  100. }
  101. for i, bucket := range s {
  102. if !bucket.Equal(o[i]) {
  103. return false
  104. }
  105. }
  106. return true
  107. }
  108. type SampleHistogram struct {
  109. Count FloatString `json:"count"`
  110. Sum FloatString `json:"sum"`
  111. Buckets HistogramBuckets `json:"buckets"`
  112. }
  113. func (s SampleHistogram) String() string {
  114. return fmt.Sprintf("Count: %f, Sum: %f, Buckets: %v", s.Count, s.Sum, s.Buckets)
  115. }
  116. func (s *SampleHistogram) Equal(o *SampleHistogram) bool {
  117. return s == o || (s.Count == o.Count && s.Sum == o.Sum && s.Buckets.Equal(o.Buckets))
  118. }
  119. type SampleHistogramPair struct {
  120. Timestamp Time
  121. // Histogram should never be nil, it's only stored as pointer for efficiency.
  122. Histogram *SampleHistogram
  123. }
  124. func (s SampleHistogramPair) MarshalJSON() ([]byte, error) {
  125. if s.Histogram == nil {
  126. return nil, errors.New("histogram is nil")
  127. }
  128. t, err := json.Marshal(s.Timestamp)
  129. if err != nil {
  130. return nil, err
  131. }
  132. v, err := json.Marshal(s.Histogram)
  133. if err != nil {
  134. return nil, err
  135. }
  136. return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
  137. }
  138. func (s *SampleHistogramPair) UnmarshalJSON(buf []byte) error {
  139. tmp := []interface{}{&s.Timestamp, &s.Histogram}
  140. wantLen := len(tmp)
  141. if err := json.Unmarshal(buf, &tmp); err != nil {
  142. return err
  143. }
  144. if gotLen := len(tmp); gotLen != wantLen {
  145. return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen)
  146. }
  147. if s.Histogram == nil {
  148. return errors.New("histogram is null")
  149. }
  150. return nil
  151. }
  152. func (s SampleHistogramPair) String() string {
  153. return fmt.Sprintf("%s @[%s]", s.Histogram, s.Timestamp)
  154. }
  155. func (s *SampleHistogramPair) Equal(o *SampleHistogramPair) bool {
  156. return s == o || (s.Histogram.Equal(o.Histogram) && s.Timestamp.Equal(o.Timestamp))
  157. }