| 
									
										
										
										
											2017-04-19 20:43:09 +08:00
										 |  |  | // Copyright 2017 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | package promql | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/prometheus/prometheus/pkg/labels" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Value is a generic interface for values resulting from a query evaluation.
 | 
					
						
							|  |  |  | type Value interface { | 
					
						
							|  |  |  | 	Type() ValueType | 
					
						
							|  |  |  | 	String() string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (Matrix) Type() ValueType { return ValueTypeMatrix } | 
					
						
							|  |  |  | func (Vector) Type() ValueType { return ValueTypeVector } | 
					
						
							|  |  |  | func (Scalar) Type() ValueType { return ValueTypeScalar } | 
					
						
							|  |  |  | func (String) Type() ValueType { return ValueTypeString } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ValueType describes a type of a value.
 | 
					
						
							|  |  |  | type ValueType string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // The valid value types.
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	ValueTypeNone   = "none" | 
					
						
							|  |  |  | 	ValueTypeVector = "vector" | 
					
						
							|  |  |  | 	ValueTypeScalar = "scalar" | 
					
						
							|  |  |  | 	ValueTypeMatrix = "matrix" | 
					
						
							|  |  |  | 	ValueTypeString = "string" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // String represents a string value.
 | 
					
						
							|  |  |  | type String struct { | 
					
						
							|  |  |  | 	V string | 
					
						
							|  |  |  | 	T int64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s String) String() string { | 
					
						
							|  |  |  | 	return s.V | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | func (s String) MarshalJSON() ([]byte, error) { | 
					
						
							|  |  |  | 	return json.Marshal([...]interface{}{float64(s.T) / 1000, s.V}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | // Scalar is a data point that's explicitly not associated with a metric.
 | 
					
						
							|  |  |  | type Scalar struct { | 
					
						
							|  |  |  | 	T int64 | 
					
						
							|  |  |  | 	V float64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s Scalar) String() string { | 
					
						
							| 
									
										
										
										
											2016-12-30 00:31:14 +08:00
										 |  |  | 	v := strconv.FormatFloat(s.V, 'f', -1, 64) | 
					
						
							|  |  |  | 	return fmt.Sprintf("scalar: %v @[%v]", v, s.T) | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | func (s Scalar) MarshalJSON() ([]byte, error) { | 
					
						
							|  |  |  | 	v := strconv.FormatFloat(s.V, 'f', -1, 64) | 
					
						
							|  |  |  | 	return json.Marshal([...]interface{}{float64(s.T) / 1000, v}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | // Series is a stream of data points belonging to a metric.
 | 
					
						
							|  |  |  | type Series struct { | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | 	Metric labels.Labels `json:"metric"` | 
					
						
							|  |  |  | 	Points []Point       `json:"values"` | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s Series) String() string { | 
					
						
							|  |  |  | 	vals := make([]string, len(s.Points)) | 
					
						
							|  |  |  | 	for i, v := range s.Points { | 
					
						
							|  |  |  | 		vals[i] = v.String() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s =>\n%s", s.Metric, strings.Join(vals, "\n")) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Point represents a single data point for a given timestamp.
 | 
					
						
							|  |  |  | type Point struct { | 
					
						
							|  |  |  | 	T int64 | 
					
						
							|  |  |  | 	V float64 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (p Point) String() string { | 
					
						
							| 
									
										
										
										
											2016-12-30 00:31:14 +08:00
										 |  |  | 	v := strconv.FormatFloat(p.V, 'f', -1, 64) | 
					
						
							|  |  |  | 	return fmt.Sprintf("%v @[%v]", v, p.T) | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | // MarshalJSON implements json.Marshaler.
 | 
					
						
							|  |  |  | func (p Point) MarshalJSON() ([]byte, error) { | 
					
						
							|  |  |  | 	v := strconv.FormatFloat(p.V, 'f', -1, 64) | 
					
						
							|  |  |  | 	return json.Marshal([...]interface{}{float64(p.T) / 1000, v}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | // Sample is a single sample belonging to a metric.
 | 
					
						
							|  |  |  | type Sample struct { | 
					
						
							|  |  |  | 	Point | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Metric labels.Labels | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (s Sample) String() string { | 
					
						
							|  |  |  | 	return fmt.Sprintf("%s => %s", s.Metric, s.Point) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | func (s Sample) MarshalJSON() ([]byte, error) { | 
					
						
							|  |  |  | 	v := struct { | 
					
						
							|  |  |  | 		M labels.Labels `json:"metric"` | 
					
						
							|  |  |  | 		V Point         `json:"value"` | 
					
						
							|  |  |  | 	}{ | 
					
						
							|  |  |  | 		M: s.Metric, | 
					
						
							|  |  |  | 		V: s.Point, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return json.Marshal(v) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | // Vector is basically only an alias for model.Samples, but the
 | 
					
						
							|  |  |  | // contract is that in a Vector, all Samples have the same timestamp.
 | 
					
						
							|  |  |  | type Vector []Sample | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (vec Vector) String() string { | 
					
						
							|  |  |  | 	entries := make([]string, len(vec)) | 
					
						
							|  |  |  | 	for i, s := range vec { | 
					
						
							|  |  |  | 		entries[i] = s.String() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return strings.Join(entries, "\n") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Matrix is a slice of Seriess that implements sort.Interface and
 | 
					
						
							|  |  |  | // has a String method.
 | 
					
						
							|  |  |  | type Matrix []Series | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (m Matrix) String() string { | 
					
						
							|  |  |  | 	// TODO(fabxc): sort, or can we rely on order from the querier?
 | 
					
						
							|  |  |  | 	strs := make([]string, len(m)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, ss := range m { | 
					
						
							|  |  |  | 		strs[i] = ss.String() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return strings.Join(strs, "\n") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-29 16:27:30 +08:00
										 |  |  | func (m Matrix) Len() int           { return len(m) } | 
					
						
							|  |  |  | func (m Matrix) Less(i, j int) bool { return labels.Compare(m[i].Metric, m[j].Metric) < 0 } | 
					
						
							|  |  |  | func (m Matrix) Swap(i, j int)      { m[i], m[j] = m[j], m[i] } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 16:16:48 +08:00
										 |  |  | // Result holds the resulting value of an execution or an error
 | 
					
						
							|  |  |  | // if any occurred.
 | 
					
						
							|  |  |  | type Result struct { | 
					
						
							|  |  |  | 	Err   error | 
					
						
							|  |  |  | 	Value Value | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Vector returns a Vector if the result value is one. An error is returned if
 | 
					
						
							|  |  |  | // the result was an error or the result value is not a Vector.
 | 
					
						
							|  |  |  | func (r *Result) Vector() (Vector, error) { | 
					
						
							|  |  |  | 	if r.Err != nil { | 
					
						
							|  |  |  | 		return nil, r.Err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v, ok := r.Value.(Vector) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("query result is not a Vector") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return v, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Matrix returns a Matrix. An error is returned if
 | 
					
						
							|  |  |  | // the result was an error or the result value is not a Matrix.
 | 
					
						
							|  |  |  | func (r *Result) Matrix() (Matrix, error) { | 
					
						
							|  |  |  | 	if r.Err != nil { | 
					
						
							|  |  |  | 		return nil, r.Err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v, ok := r.Value.(Matrix) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("query result is not a range Vector") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return v, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Scalar returns a Scalar value. An error is returned if
 | 
					
						
							|  |  |  | // the result was an error or the result value is not a Scalar.
 | 
					
						
							|  |  |  | func (r *Result) Scalar() (Scalar, error) { | 
					
						
							|  |  |  | 	if r.Err != nil { | 
					
						
							|  |  |  | 		return Scalar{}, r.Err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	v, ok := r.Value.(Scalar) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return Scalar{}, fmt.Errorf("query result is not a Scalar") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return v, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (r *Result) String() string { | 
					
						
							|  |  |  | 	if r.Err != nil { | 
					
						
							|  |  |  | 		return r.Err.Error() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if r.Value == nil { | 
					
						
							|  |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return r.Value.String() | 
					
						
							|  |  |  | } |