blob: c9d8fb1a28313eeba3c79d3fcddb701572a1f1b6 [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -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"
19 "math"
20 "sort"
21 "strconv"
22 "strings"
23)
24
25var (
26 // ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
27 // non-existing sample pair. It is a SamplePair with timestamp Earliest and
28 // value 0.0. Note that the natural zero value of SamplePair has a timestamp
29 // of 0, which is possible to appear in a real SamplePair and thus not
30 // suitable to signal a non-existing SamplePair.
31 ZeroSamplePair = SamplePair{Timestamp: Earliest}
32
33 // ZeroSample is the pseudo zero-value of Sample used to signal a
34 // non-existing sample. It is a Sample with timestamp Earliest, value 0.0,
35 // and metric nil. Note that the natural zero value of Sample has a timestamp
36 // of 0, which is possible to appear in a real Sample and thus not suitable
37 // to signal a non-existing Sample.
38 ZeroSample = Sample{Timestamp: Earliest}
39)
40
41// A SampleValue is a representation of a value for a given sample at a given
42// time.
43type SampleValue float64
44
45// MarshalJSON implements json.Marshaler.
46func (v SampleValue) MarshalJSON() ([]byte, error) {
47 return json.Marshal(v.String())
48}
49
50// UnmarshalJSON implements json.Unmarshaler.
51func (v *SampleValue) UnmarshalJSON(b []byte) error {
52 if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
53 return fmt.Errorf("sample value must be a quoted string")
54 }
55 f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
56 if err != nil {
57 return err
58 }
59 *v = SampleValue(f)
60 return nil
61}
62
63// Equal returns true if the value of v and o is equal or if both are NaN. Note
64// that v==o is false if both are NaN. If you want the conventional float
65// behavior, use == to compare two SampleValues.
66func (v SampleValue) Equal(o SampleValue) bool {
67 if v == o {
68 return true
69 }
70 return math.IsNaN(float64(v)) && math.IsNaN(float64(o))
71}
72
73func (v SampleValue) String() string {
74 return strconv.FormatFloat(float64(v), 'f', -1, 64)
75}
76
77// SamplePair pairs a SampleValue with a Timestamp.
78type SamplePair struct {
79 Timestamp Time
80 Value SampleValue
81}
82
83// MarshalJSON implements json.Marshaler.
84func (s SamplePair) MarshalJSON() ([]byte, error) {
85 t, err := json.Marshal(s.Timestamp)
86 if err != nil {
87 return nil, err
88 }
89 v, err := json.Marshal(s.Value)
90 if err != nil {
91 return nil, err
92 }
93 return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
94}
95
96// UnmarshalJSON implements json.Unmarshaler.
97func (s *SamplePair) UnmarshalJSON(b []byte) error {
98 v := [...]json.Unmarshaler{&s.Timestamp, &s.Value}
99 return json.Unmarshal(b, &v)
100}
101
102// Equal returns true if this SamplePair and o have equal Values and equal
103// Timestamps. The semantics of Value equality is defined by SampleValue.Equal.
104func (s *SamplePair) Equal(o *SamplePair) bool {
105 return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp))
106}
107
108func (s SamplePair) String() string {
109 return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp)
110}
111
112// Sample is a sample pair associated with a metric.
113type Sample struct {
114 Metric Metric `json:"metric"`
115 Value SampleValue `json:"value"`
116 Timestamp Time `json:"timestamp"`
117}
118
119// Equal compares first the metrics, then the timestamp, then the value. The
120// semantics of value equality is defined by SampleValue.Equal.
121func (s *Sample) Equal(o *Sample) bool {
122 if s == o {
123 return true
124 }
125
126 if !s.Metric.Equal(o.Metric) {
127 return false
128 }
129 if !s.Timestamp.Equal(o.Timestamp) {
130 return false
131 }
132
133 return s.Value.Equal(o.Value)
134}
135
136func (s Sample) String() string {
137 return fmt.Sprintf("%s => %s", s.Metric, SamplePair{
138 Timestamp: s.Timestamp,
139 Value: s.Value,
140 })
141}
142
143// MarshalJSON implements json.Marshaler.
144func (s Sample) MarshalJSON() ([]byte, error) {
145 v := struct {
146 Metric Metric `json:"metric"`
147 Value SamplePair `json:"value"`
148 }{
149 Metric: s.Metric,
150 Value: SamplePair{
151 Timestamp: s.Timestamp,
152 Value: s.Value,
153 },
154 }
155
156 return json.Marshal(&v)
157}
158
159// UnmarshalJSON implements json.Unmarshaler.
160func (s *Sample) UnmarshalJSON(b []byte) error {
161 v := struct {
162 Metric Metric `json:"metric"`
163 Value SamplePair `json:"value"`
164 }{
165 Metric: s.Metric,
166 Value: SamplePair{
167 Timestamp: s.Timestamp,
168 Value: s.Value,
169 },
170 }
171
172 if err := json.Unmarshal(b, &v); err != nil {
173 return err
174 }
175
176 s.Metric = v.Metric
177 s.Timestamp = v.Value.Timestamp
178 s.Value = v.Value.Value
179
180 return nil
181}
182
183// Samples is a sortable Sample slice. It implements sort.Interface.
184type Samples []*Sample
185
186func (s Samples) Len() int {
187 return len(s)
188}
189
190// Less compares first the metrics, then the timestamp.
191func (s Samples) Less(i, j int) bool {
192 switch {
193 case s[i].Metric.Before(s[j].Metric):
194 return true
195 case s[j].Metric.Before(s[i].Metric):
196 return false
197 case s[i].Timestamp.Before(s[j].Timestamp):
198 return true
199 default:
200 return false
201 }
202}
203
204func (s Samples) Swap(i, j int) {
205 s[i], s[j] = s[j], s[i]
206}
207
208// Equal compares two sets of samples and returns true if they are equal.
209func (s Samples) Equal(o Samples) bool {
210 if len(s) != len(o) {
211 return false
212 }
213
214 for i, sample := range s {
215 if !sample.Equal(o[i]) {
216 return false
217 }
218 }
219 return true
220}
221
222// SampleStream is a stream of Values belonging to an attached COWMetric.
223type SampleStream struct {
224 Metric Metric `json:"metric"`
225 Values []SamplePair `json:"values"`
226}
227
228func (ss SampleStream) String() string {
229 vals := make([]string, len(ss.Values))
230 for i, v := range ss.Values {
231 vals[i] = v.String()
232 }
233 return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n"))
234}
235
236// Value is a generic interface for values resulting from a query evaluation.
237type Value interface {
238 Type() ValueType
239 String() string
240}
241
242func (Matrix) Type() ValueType { return ValMatrix }
243func (Vector) Type() ValueType { return ValVector }
244func (*Scalar) Type() ValueType { return ValScalar }
245func (*String) Type() ValueType { return ValString }
246
247type ValueType int
248
249const (
250 ValNone ValueType = iota
251 ValScalar
252 ValVector
253 ValMatrix
254 ValString
255)
256
257// MarshalJSON implements json.Marshaler.
258func (et ValueType) MarshalJSON() ([]byte, error) {
259 return json.Marshal(et.String())
260}
261
262func (et *ValueType) UnmarshalJSON(b []byte) error {
263 var s string
264 if err := json.Unmarshal(b, &s); err != nil {
265 return err
266 }
267 switch s {
268 case "<ValNone>":
269 *et = ValNone
270 case "scalar":
271 *et = ValScalar
272 case "vector":
273 *et = ValVector
274 case "matrix":
275 *et = ValMatrix
276 case "string":
277 *et = ValString
278 default:
279 return fmt.Errorf("unknown value type %q", s)
280 }
281 return nil
282}
283
284func (e ValueType) String() string {
285 switch e {
286 case ValNone:
287 return "<ValNone>"
288 case ValScalar:
289 return "scalar"
290 case ValVector:
291 return "vector"
292 case ValMatrix:
293 return "matrix"
294 case ValString:
295 return "string"
296 }
297 panic("ValueType.String: unhandled value type")
298}
299
300// Scalar is a scalar value evaluated at the set timestamp.
301type Scalar struct {
302 Value SampleValue `json:"value"`
303 Timestamp Time `json:"timestamp"`
304}
305
306func (s Scalar) String() string {
307 return fmt.Sprintf("scalar: %v @[%v]", s.Value, s.Timestamp)
308}
309
310// MarshalJSON implements json.Marshaler.
311func (s Scalar) MarshalJSON() ([]byte, error) {
312 v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64)
313 return json.Marshal([...]interface{}{s.Timestamp, string(v)})
314}
315
316// UnmarshalJSON implements json.Unmarshaler.
317func (s *Scalar) UnmarshalJSON(b []byte) error {
318 var f string
319 v := [...]interface{}{&s.Timestamp, &f}
320
321 if err := json.Unmarshal(b, &v); err != nil {
322 return err
323 }
324
325 value, err := strconv.ParseFloat(f, 64)
326 if err != nil {
327 return fmt.Errorf("error parsing sample value: %s", err)
328 }
329 s.Value = SampleValue(value)
330 return nil
331}
332
333// String is a string value evaluated at the set timestamp.
334type String struct {
335 Value string `json:"value"`
336 Timestamp Time `json:"timestamp"`
337}
338
339func (s *String) String() string {
340 return s.Value
341}
342
343// MarshalJSON implements json.Marshaler.
344func (s String) MarshalJSON() ([]byte, error) {
345 return json.Marshal([]interface{}{s.Timestamp, s.Value})
346}
347
348// UnmarshalJSON implements json.Unmarshaler.
349func (s *String) UnmarshalJSON(b []byte) error {
350 v := [...]interface{}{&s.Timestamp, &s.Value}
351 return json.Unmarshal(b, &v)
352}
353
354// Vector is basically only an alias for Samples, but the
355// contract is that in a Vector, all Samples have the same timestamp.
356type Vector []*Sample
357
358func (vec Vector) String() string {
359 entries := make([]string, len(vec))
360 for i, s := range vec {
361 entries[i] = s.String()
362 }
363 return strings.Join(entries, "\n")
364}
365
366func (vec Vector) Len() int { return len(vec) }
367func (vec Vector) Swap(i, j int) { vec[i], vec[j] = vec[j], vec[i] }
368
369// Less compares first the metrics, then the timestamp.
370func (vec Vector) Less(i, j int) bool {
371 switch {
372 case vec[i].Metric.Before(vec[j].Metric):
373 return true
374 case vec[j].Metric.Before(vec[i].Metric):
375 return false
376 case vec[i].Timestamp.Before(vec[j].Timestamp):
377 return true
378 default:
379 return false
380 }
381}
382
383// Equal compares two sets of samples and returns true if they are equal.
384func (vec Vector) Equal(o Vector) bool {
385 if len(vec) != len(o) {
386 return false
387 }
388
389 for i, sample := range vec {
390 if !sample.Equal(o[i]) {
391 return false
392 }
393 }
394 return true
395}
396
397// Matrix is a list of time series.
398type Matrix []*SampleStream
399
400func (m Matrix) Len() int { return len(m) }
401func (m Matrix) Less(i, j int) bool { return m[i].Metric.Before(m[j].Metric) }
402func (m Matrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
403
404func (mat Matrix) String() string {
405 matCp := make(Matrix, len(mat))
406 copy(matCp, mat)
407 sort.Sort(matCp)
408
409 strs := make([]string, len(matCp))
410
411 for i, ss := range matCp {
412 strs[i] = ss.String()
413 }
414
415 return strings.Join(strs, "\n")
416}