diff --git a/promql/engine.go b/promql/engine.go index 9f81b52a8..f7b2bbb8d 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -19,6 +19,7 @@ import ( "math" "runtime" "sort" + "strconv" "time" "golang.org/x/net/context" @@ -43,12 +44,6 @@ type Sample struct { Timestamp clientmodel.Timestamp `json:"timestamp"` } -// Scalar is a scalar value evaluated at the set timestamp. -type Scalar struct { - Value clientmodel.SampleValue `json:"value"` - Timestamp clientmodel.Timestamp `json:"timestamp"` -} - // MarshalJSON implements json.Marshaler. func (s *Sample) MarshalJSON() ([]byte, error) { v := struct { @@ -65,16 +60,33 @@ func (s *Sample) MarshalJSON() ([]byte, error) { return json.Marshal(&v) } +// Scalar is a scalar value evaluated at the set timestamp. +type Scalar struct { + Value clientmodel.SampleValue `json:"value"` + Timestamp clientmodel.Timestamp `json:"timestamp"` +} + func (s *Scalar) String() string { return fmt.Sprintf("scalar: %v @[%v]", s.Value, s.Timestamp) } +// MarshalJSON implements json.Marshaler. +func (s *Scalar) MarshalJSON() ([]byte, error) { + v := strconv.FormatFloat(float64(s.Value), 'f', -1, 64) + return json.Marshal([]interface{}{s.Timestamp, string(v)}) +} + // String is a string value evaluated at the set timestamp. type String struct { Value string `json:"value"` Timestamp clientmodel.Timestamp `json:"timestamp"` } +// MarshalJSON implements json.Marshaler. +func (s *String) MarshalJSON() ([]byte, error) { + return json.Marshal([]interface{}{s.Timestamp, s.Value}) +} + func (s *String) String() string { return s.Value } diff --git a/web/api/legacy/query.go b/web/api/legacy/query.go index de7279005..511d75bc8 100644 --- a/web/api/legacy/query.go +++ b/web/api/legacy/query.go @@ -94,11 +94,19 @@ func (api *API) Query(w http.ResponseWriter, r *http.Request) { respondJSON(w, plainVec(vec)) return } + if sca, ok := res.Value.(*promql.Scalar); ok { + respondJSON(w, (*plainScalar)(sca)) + return + } + if str, ok := res.Value.(*promql.String); ok { + respondJSON(w, (*plainString)(str)) + return + } respondJSON(w, res.Value) } -// plainVec is an indirection that hides the original MarshalJSON methods +// plainVec is an indirection that hides the original MarshalJSON method // which does not fit the response format for the legacy API. type plainVec promql.Vector @@ -121,6 +129,30 @@ func (pv plainVec) String() string { return "" } +// plainScalar is an indirection that hides the original MarshalJSON method +// which does not fit the response format for the legacy API. +type plainScalar promql.Scalar + +func (pv plainScalar) Type() promql.ExprType { + return promql.ExprScalar +} + +func (pv plainScalar) String() string { + return "" +} + +// plainString is an indirection that hides the original MarshalJSON method +// which does not fit the response format for the legacy API. +type plainString promql.String + +func (pv plainString) Type() promql.ExprType { + return promql.ExprString +} + +func (pv plainString) String() string { + return "" +} + // QueryRange handles the /api/query_range endpoint. func (api *API) QueryRange(w http.ResponseWriter, r *http.Request) { setAccessControlHeaders(w)