blob: a9995a37eeeaa194c56c21177f9f1b29ca1ac6ff [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// 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
14package model
15
16import (
17 "encoding/json"
18 "fmt"
khenaidooab1f7bd2019-11-14 14:00:27 -050019 "sort"
20 "strconv"
21 "strings"
22)
23
Abhay Kumara2ae5992025-11-10 14:02:24 +000024// ZeroSample is the pseudo zero-value of Sample used to signal a
25// non-existing sample. It is a Sample with timestamp Earliest, value 0.0,
26// and metric nil. Note that the natural zero value of Sample has a timestamp
27// of 0, which is possible to appear in a real Sample and thus not suitable
28// to signal a non-existing Sample.
29var ZeroSample = Sample{Timestamp: Earliest}
khenaidooab1f7bd2019-11-14 14:00:27 -050030
Abhay Kumara2ae5992025-11-10 14:02:24 +000031// Sample is a sample pair associated with a metric. A single sample must either
32// define Value or Histogram but not both. Histogram == nil implies the Value
33// field is used, otherwise it should be ignored.
khenaidooab1f7bd2019-11-14 14:00:27 -050034type Sample struct {
Abhay Kumara2ae5992025-11-10 14:02:24 +000035 Metric Metric `json:"metric"`
36 Value SampleValue `json:"value"`
37 Timestamp Time `json:"timestamp"`
38 Histogram *SampleHistogram `json:"histogram"`
khenaidooab1f7bd2019-11-14 14:00:27 -050039}
40
41// Equal compares first the metrics, then the timestamp, then the value. The
42// semantics of value equality is defined by SampleValue.Equal.
43func (s *Sample) Equal(o *Sample) bool {
44 if s == o {
45 return true
46 }
47
48 if !s.Metric.Equal(o.Metric) {
49 return false
50 }
51 if !s.Timestamp.Equal(o.Timestamp) {
52 return false
53 }
Abhay Kumara2ae5992025-11-10 14:02:24 +000054 if s.Histogram != nil {
55 return s.Histogram.Equal(o.Histogram)
56 }
khenaidooab1f7bd2019-11-14 14:00:27 -050057 return s.Value.Equal(o.Value)
58}
59
60func (s Sample) String() string {
Abhay Kumara2ae5992025-11-10 14:02:24 +000061 if s.Histogram != nil {
62 return fmt.Sprintf("%s => %s", s.Metric, SampleHistogramPair{
63 Timestamp: s.Timestamp,
64 Histogram: s.Histogram,
65 })
66 }
khenaidooab1f7bd2019-11-14 14:00:27 -050067 return fmt.Sprintf("%s => %s", s.Metric, SamplePair{
68 Timestamp: s.Timestamp,
69 Value: s.Value,
70 })
71}
72
73// MarshalJSON implements json.Marshaler.
74func (s Sample) MarshalJSON() ([]byte, error) {
Abhay Kumara2ae5992025-11-10 14:02:24 +000075 if s.Histogram != nil {
76 v := struct {
77 Metric Metric `json:"metric"`
78 Histogram SampleHistogramPair `json:"histogram"`
79 }{
80 Metric: s.Metric,
81 Histogram: SampleHistogramPair{
82 Timestamp: s.Timestamp,
83 Histogram: s.Histogram,
84 },
85 }
86 return json.Marshal(&v)
87 }
khenaidooab1f7bd2019-11-14 14:00:27 -050088 v := struct {
89 Metric Metric `json:"metric"`
90 Value SamplePair `json:"value"`
91 }{
92 Metric: s.Metric,
93 Value: SamplePair{
94 Timestamp: s.Timestamp,
95 Value: s.Value,
96 },
97 }
khenaidooab1f7bd2019-11-14 14:00:27 -050098 return json.Marshal(&v)
99}
100
101// UnmarshalJSON implements json.Unmarshaler.
102func (s *Sample) UnmarshalJSON(b []byte) error {
103 v := struct {
Abhay Kumara2ae5992025-11-10 14:02:24 +0000104 Metric Metric `json:"metric"`
105 Value SamplePair `json:"value"`
106 Histogram SampleHistogramPair `json:"histogram"`
khenaidooab1f7bd2019-11-14 14:00:27 -0500107 }{
108 Metric: s.Metric,
109 Value: SamplePair{
110 Timestamp: s.Timestamp,
111 Value: s.Value,
112 },
Abhay Kumara2ae5992025-11-10 14:02:24 +0000113 Histogram: SampleHistogramPair{
114 Timestamp: s.Timestamp,
115 Histogram: s.Histogram,
116 },
khenaidooab1f7bd2019-11-14 14:00:27 -0500117 }
118
119 if err := json.Unmarshal(b, &v); err != nil {
120 return err
121 }
122
123 s.Metric = v.Metric
Abhay Kumara2ae5992025-11-10 14:02:24 +0000124 if v.Histogram.Histogram != nil {
125 s.Timestamp = v.Histogram.Timestamp
126 s.Histogram = v.Histogram.Histogram
127 } else {
128 s.Timestamp = v.Value.Timestamp
129 s.Value = v.Value.Value
130 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500131
132 return nil
133}
134
135// Samples is a sortable Sample slice. It implements sort.Interface.
136type Samples []*Sample
137
138func (s Samples) Len() int {
139 return len(s)
140}
141
142// Less compares first the metrics, then the timestamp.
143func (s Samples) Less(i, j int) bool {
144 switch {
145 case s[i].Metric.Before(s[j].Metric):
146 return true
147 case s[j].Metric.Before(s[i].Metric):
148 return false
149 case s[i].Timestamp.Before(s[j].Timestamp):
150 return true
151 default:
152 return false
153 }
154}
155
156func (s Samples) Swap(i, j int) {
157 s[i], s[j] = s[j], s[i]
158}
159
160// Equal compares two sets of samples and returns true if they are equal.
161func (s Samples) Equal(o Samples) bool {
162 if len(s) != len(o) {
163 return false
164 }
165
166 for i, sample := range s {
167 if !sample.Equal(o[i]) {
168 return false
169 }
170 }
171 return true
172}
173
174// SampleStream is a stream of Values belonging to an attached COWMetric.
175type SampleStream struct {
Abhay Kumara2ae5992025-11-10 14:02:24 +0000176 Metric Metric `json:"metric"`
177 Values []SamplePair `json:"values"`
178 Histograms []SampleHistogramPair `json:"histograms"`
khenaidooab1f7bd2019-11-14 14:00:27 -0500179}
180
181func (ss SampleStream) String() string {
Abhay Kumara2ae5992025-11-10 14:02:24 +0000182 valuesLength := len(ss.Values)
183 vals := make([]string, valuesLength+len(ss.Histograms))
khenaidooab1f7bd2019-11-14 14:00:27 -0500184 for i, v := range ss.Values {
185 vals[i] = v.String()
186 }
Abhay Kumara2ae5992025-11-10 14:02:24 +0000187 for i, v := range ss.Histograms {
188 vals[i+valuesLength] = v.String()
189 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500190 return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n"))
191}
192
Abhay Kumara2ae5992025-11-10 14:02:24 +0000193func (ss SampleStream) MarshalJSON() ([]byte, error) {
194 switch {
195 case len(ss.Histograms) > 0 && len(ss.Values) > 0:
196 v := struct {
197 Metric Metric `json:"metric"`
198 Values []SamplePair `json:"values"`
199 Histograms []SampleHistogramPair `json:"histograms"`
200 }{
201 Metric: ss.Metric,
202 Values: ss.Values,
203 Histograms: ss.Histograms,
204 }
205 return json.Marshal(&v)
206 case len(ss.Histograms) > 0:
207 v := struct {
208 Metric Metric `json:"metric"`
209 Histograms []SampleHistogramPair `json:"histograms"`
210 }{
211 Metric: ss.Metric,
212 Histograms: ss.Histograms,
213 }
214 return json.Marshal(&v)
215 default:
216 v := struct {
217 Metric Metric `json:"metric"`
218 Values []SamplePair `json:"values"`
219 }{
220 Metric: ss.Metric,
221 Values: ss.Values,
222 }
223 return json.Marshal(&v)
224 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500225}
226
Abhay Kumara2ae5992025-11-10 14:02:24 +0000227func (ss *SampleStream) UnmarshalJSON(b []byte) error {
228 v := struct {
229 Metric Metric `json:"metric"`
230 Values []SamplePair `json:"values"`
231 Histograms []SampleHistogramPair `json:"histograms"`
232 }{
233 Metric: ss.Metric,
234 Values: ss.Values,
235 Histograms: ss.Histograms,
236 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500237
Abhay Kumara2ae5992025-11-10 14:02:24 +0000238 if err := json.Unmarshal(b, &v); err != nil {
khenaidooab1f7bd2019-11-14 14:00:27 -0500239 return err
240 }
khenaidooab1f7bd2019-11-14 14:00:27 -0500241
Abhay Kumara2ae5992025-11-10 14:02:24 +0000242 ss.Metric = v.Metric
243 ss.Values = v.Values
244 ss.Histograms = v.Histograms
245
246 return nil
khenaidooab1f7bd2019-11-14 14:00:27 -0500247}
248
249// Scalar is a scalar value evaluated at the set timestamp.
250type Scalar struct {
251 Value SampleValue `json:"value"`
252 Timestamp Time `json:"timestamp"`
253}
254
255func (s Scalar) String() string {
256 return fmt.Sprintf("scalar: %v @[%v]", s.Value, s.Timestamp)
257}
258
259// MarshalJSON implements json.Marshaler.
260func (s Scalar) MarshalJSON() ([]byte, error) {
261 v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64)
Abhay Kumara2ae5992025-11-10 14:02:24 +0000262 return json.Marshal([...]interface{}{s.Timestamp, v})
khenaidooab1f7bd2019-11-14 14:00:27 -0500263}
264
265// UnmarshalJSON implements json.Unmarshaler.
266func (s *Scalar) UnmarshalJSON(b []byte) error {
267 var f string
268 v := [...]interface{}{&s.Timestamp, &f}
269
270 if err := json.Unmarshal(b, &v); err != nil {
271 return err
272 }
273
274 value, err := strconv.ParseFloat(f, 64)
275 if err != nil {
Abhay Kumara2ae5992025-11-10 14:02:24 +0000276 return fmt.Errorf("error parsing sample value: %w", err)
khenaidooab1f7bd2019-11-14 14:00:27 -0500277 }
278 s.Value = SampleValue(value)
279 return nil
280}
281
282// String is a string value evaluated at the set timestamp.
283type String struct {
284 Value string `json:"value"`
285 Timestamp Time `json:"timestamp"`
286}
287
288func (s *String) String() string {
289 return s.Value
290}
291
292// MarshalJSON implements json.Marshaler.
293func (s String) MarshalJSON() ([]byte, error) {
294 return json.Marshal([]interface{}{s.Timestamp, s.Value})
295}
296
297// UnmarshalJSON implements json.Unmarshaler.
298func (s *String) UnmarshalJSON(b []byte) error {
299 v := [...]interface{}{&s.Timestamp, &s.Value}
300 return json.Unmarshal(b, &v)
301}
302
303// Vector is basically only an alias for Samples, but the
304// contract is that in a Vector, all Samples have the same timestamp.
305type Vector []*Sample
306
307func (vec Vector) String() string {
308 entries := make([]string, len(vec))
309 for i, s := range vec {
310 entries[i] = s.String()
311 }
312 return strings.Join(entries, "\n")
313}
314
315func (vec Vector) Len() int { return len(vec) }
316func (vec Vector) Swap(i, j int) { vec[i], vec[j] = vec[j], vec[i] }
317
318// Less compares first the metrics, then the timestamp.
319func (vec Vector) Less(i, j int) bool {
320 switch {
321 case vec[i].Metric.Before(vec[j].Metric):
322 return true
323 case vec[j].Metric.Before(vec[i].Metric):
324 return false
325 case vec[i].Timestamp.Before(vec[j].Timestamp):
326 return true
327 default:
328 return false
329 }
330}
331
332// Equal compares two sets of samples and returns true if they are equal.
333func (vec Vector) Equal(o Vector) bool {
334 if len(vec) != len(o) {
335 return false
336 }
337
338 for i, sample := range vec {
339 if !sample.Equal(o[i]) {
340 return false
341 }
342 }
343 return true
344}
345
346// Matrix is a list of time series.
347type Matrix []*SampleStream
348
349func (m Matrix) Len() int { return len(m) }
350func (m Matrix) Less(i, j int) bool { return m[i].Metric.Before(m[j].Metric) }
351func (m Matrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
352
Abhay Kumara2ae5992025-11-10 14:02:24 +0000353func (m Matrix) String() string {
354 matCp := make(Matrix, len(m))
355 copy(matCp, m)
khenaidooab1f7bd2019-11-14 14:00:27 -0500356 sort.Sort(matCp)
357
358 strs := make([]string, len(matCp))
359
360 for i, ss := range matCp {
361 strs[i] = ss.String()
362 }
363
364 return strings.Join(strs, "\n")
365}