2015-01-21 11:07:45 -08:00
|
|
|
// Copyright 2013 The Prometheus Authors
|
2013-02-07 02:49:04 -08:00
|
|
|
// 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.
|
|
|
|
|
2013-01-07 14:24:26 -08:00
|
|
|
package ast
|
|
|
|
|
|
|
|
import (
|
2013-01-12 12:22:59 -08:00
|
|
|
"encoding/json"
|
2014-05-28 10:44:54 -07:00
|
|
|
"errors"
|
2013-01-07 14:24:26 -08:00
|
|
|
"fmt"
|
2014-12-10 07:16:49 -08:00
|
|
|
"reflect"
|
2013-01-07 14:24:26 -08:00
|
|
|
"sort"
|
|
|
|
"strings"
|
2013-06-25 05:02:27 -07:00
|
|
|
|
|
|
|
clientmodel "github.com/prometheus/client_golang/model"
|
|
|
|
|
|
|
|
"github.com/prometheus/prometheus/stats"
|
2014-06-06 02:55:53 -07:00
|
|
|
"github.com/prometheus/prometheus/storage/local"
|
2013-06-25 05:02:27 -07:00
|
|
|
"github.com/prometheus/prometheus/utility"
|
2013-01-07 14:24:26 -08:00
|
|
|
)
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// OutputFormat is an enum for the possible output formats.
|
2013-01-10 17:27:03 -08:00
|
|
|
type OutputFormat int
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// Possible output formats.
|
2013-01-10 17:27:03 -08:00
|
|
|
const (
|
2014-12-24 16:28:35 -08:00
|
|
|
Text OutputFormat = iota
|
2013-01-12 12:22:59 -08:00
|
|
|
JSON
|
2013-01-10 17:27:03 -08:00
|
|
|
)
|
|
|
|
|
More efficient JSON query result format.
This depends on https://github.com/prometheus/client_golang/pull/51.
For vectors, the result format looks like this:
```json
{
"version": 1,
"type" : "vector",
"value" : [
{
"timestamp" : 1421765411.045,
"value" : "65.475000",
"metric" : {
"quantile" : "0.5",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "304"
}
},
{
"timestamp" : 1421765411.045,
"value" : "5826.339000",
"metric" : {
"quantile" : "0.9",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "prometheus",
"method" : "get",
"code" : "200"
}
},
/* ... */
]
}
```
For matrices, it looks like this:
```json
{
"version": 1,
"type" : "matrix",
"value" : [
{
"metric" : {
"quantile" : "0.99",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "200"
},
"values" : [
[
1421765547.659,
"29162.953000"
],
[
1421765548.659,
"29162.953000"
],
[
1421765549.659,
"29162.953000"
],
/* ... */
]
}
]
}
```
2015-01-20 06:13:49 -08:00
|
|
|
const jsonFormatVersion = 1
|
|
|
|
|
2013-04-26 07:02:52 -07:00
|
|
|
func (opType BinOpType) String() string {
|
2013-01-07 14:24:26 -08:00
|
|
|
opTypeMap := map[BinOpType]string{
|
2014-12-24 16:28:35 -08:00
|
|
|
Add: "+",
|
|
|
|
Sub: "-",
|
|
|
|
Mul: "*",
|
|
|
|
Div: "/",
|
|
|
|
Mod: "%",
|
2013-01-07 14:24:26 -08:00
|
|
|
GT: ">",
|
|
|
|
LT: "<",
|
|
|
|
EQ: "==",
|
|
|
|
NE: "!=",
|
|
|
|
GE: ">=",
|
|
|
|
LE: "<=",
|
2014-12-24 16:28:35 -08:00
|
|
|
And: "AND",
|
|
|
|
Or: "OR",
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
return opTypeMap[opType]
|
|
|
|
}
|
|
|
|
|
2013-04-26 07:02:52 -07:00
|
|
|
func (aggrType AggrType) String() string {
|
2013-01-07 14:24:26 -08:00
|
|
|
aggrTypeMap := map[AggrType]string{
|
2015-04-16 16:12:04 -07:00
|
|
|
Sum: "SUM",
|
|
|
|
Avg: "AVG",
|
|
|
|
Min: "MIN",
|
|
|
|
Max: "MAX",
|
|
|
|
Count: "COUNT",
|
|
|
|
Stdvar: "STDVAR",
|
|
|
|
Stddev: "STDDEV",
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
return aggrTypeMap[aggrType]
|
|
|
|
}
|
|
|
|
|
2013-04-26 07:02:52 -07:00
|
|
|
func (exprType ExprType) String() string {
|
2013-01-10 17:27:03 -08:00
|
|
|
exprTypeMap := map[ExprType]string{
|
2014-12-24 16:28:35 -08:00
|
|
|
ScalarType: "scalar",
|
|
|
|
VectorType: "vector",
|
|
|
|
MatrixType: "matrix",
|
|
|
|
StringType: "string",
|
2013-01-10 17:27:03 -08:00
|
|
|
}
|
|
|
|
return exprTypeMap[exprType]
|
|
|
|
}
|
|
|
|
|
2013-03-14 14:47:17 -07:00
|
|
|
func (vector Vector) String() string {
|
2013-06-06 06:12:37 -07:00
|
|
|
metricStrings := make([]string, 0, len(vector))
|
2013-01-07 14:24:26 -08:00
|
|
|
for _, sample := range vector {
|
|
|
|
metricStrings = append(metricStrings,
|
2013-06-11 02:01:36 -07:00
|
|
|
fmt.Sprintf("%s => %v @[%v]",
|
|
|
|
sample.Metric,
|
2013-01-07 14:24:26 -08:00
|
|
|
sample.Value, sample.Timestamp))
|
|
|
|
}
|
|
|
|
return strings.Join(metricStrings, "\n")
|
|
|
|
}
|
|
|
|
|
2013-03-14 14:47:17 -07:00
|
|
|
func (matrix Matrix) String() string {
|
2013-06-06 06:12:37 -07:00
|
|
|
metricStrings := make([]string, 0, len(matrix))
|
2014-12-08 07:55:49 -08:00
|
|
|
for _, sampleStream := range matrix {
|
2014-12-12 11:01:32 -08:00
|
|
|
metricName, hasName := sampleStream.Metric.Metric[clientmodel.MetricNameLabel]
|
|
|
|
numLabels := len(sampleStream.Metric.Metric)
|
|
|
|
if hasName {
|
|
|
|
numLabels--
|
2013-01-10 17:27:03 -08:00
|
|
|
}
|
2014-12-12 11:01:32 -08:00
|
|
|
labelStrings := make([]string, 0, numLabels)
|
2014-12-08 07:55:49 -08:00
|
|
|
for label, value := range sampleStream.Metric.Metric {
|
2013-06-25 05:02:27 -07:00
|
|
|
if label != clientmodel.MetricNameLabel {
|
2013-06-11 02:01:36 -07:00
|
|
|
labelStrings = append(labelStrings, fmt.Sprintf("%s=%q", label, value))
|
2013-01-10 17:27:03 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Strings(labelStrings)
|
2014-12-08 07:55:49 -08:00
|
|
|
valueStrings := make([]string, 0, len(sampleStream.Values))
|
|
|
|
for _, value := range sampleStream.Values {
|
2013-01-12 12:22:59 -08:00
|
|
|
valueStrings = append(valueStrings,
|
|
|
|
fmt.Sprintf("\n%v @[%v]", value.Value, value.Timestamp))
|
|
|
|
}
|
2013-01-10 17:27:03 -08:00
|
|
|
metricStrings = append(metricStrings,
|
2013-04-26 07:02:52 -07:00
|
|
|
fmt.Sprintf("%s{%s} => %s",
|
2013-01-10 17:27:03 -08:00
|
|
|
metricName,
|
2013-06-11 02:01:36 -07:00
|
|
|
strings.Join(labelStrings, ", "),
|
2013-01-10 17:27:03 -08:00
|
|
|
strings.Join(valueStrings, ", ")))
|
|
|
|
}
|
|
|
|
sort.Strings(metricStrings)
|
|
|
|
return strings.Join(metricStrings, "\n")
|
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// ErrorToJSON converts the given error into JSON.
|
2013-01-17 16:54:26 -08:00
|
|
|
func ErrorToJSON(err error) string {
|
2013-01-12 12:22:59 -08:00
|
|
|
errorStruct := struct {
|
More efficient JSON query result format.
This depends on https://github.com/prometheus/client_golang/pull/51.
For vectors, the result format looks like this:
```json
{
"version": 1,
"type" : "vector",
"value" : [
{
"timestamp" : 1421765411.045,
"value" : "65.475000",
"metric" : {
"quantile" : "0.5",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "304"
}
},
{
"timestamp" : 1421765411.045,
"value" : "5826.339000",
"metric" : {
"quantile" : "0.9",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "prometheus",
"method" : "get",
"code" : "200"
}
},
/* ... */
]
}
```
For matrices, it looks like this:
```json
{
"version": 1,
"type" : "matrix",
"value" : [
{
"metric" : {
"quantile" : "0.99",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "200"
},
"values" : [
[
1421765547.659,
"29162.953000"
],
[
1421765548.659,
"29162.953000"
],
[
1421765549.659,
"29162.953000"
],
/* ... */
]
}
]
}
```
2015-01-20 06:13:49 -08:00
|
|
|
Type string `json:"type"`
|
|
|
|
Value string `json:"value"`
|
|
|
|
Version int `json:"version"`
|
2013-01-12 12:22:59 -08:00
|
|
|
}{
|
More efficient JSON query result format.
This depends on https://github.com/prometheus/client_golang/pull/51.
For vectors, the result format looks like this:
```json
{
"version": 1,
"type" : "vector",
"value" : [
{
"timestamp" : 1421765411.045,
"value" : "65.475000",
"metric" : {
"quantile" : "0.5",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "304"
}
},
{
"timestamp" : 1421765411.045,
"value" : "5826.339000",
"metric" : {
"quantile" : "0.9",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "prometheus",
"method" : "get",
"code" : "200"
}
},
/* ... */
]
}
```
For matrices, it looks like this:
```json
{
"version": 1,
"type" : "matrix",
"value" : [
{
"metric" : {
"quantile" : "0.99",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "200"
},
"values" : [
[
1421765547.659,
"29162.953000"
],
[
1421765548.659,
"29162.953000"
],
[
1421765549.659,
"29162.953000"
],
/* ... */
]
}
]
}
```
2015-01-20 06:13:49 -08:00
|
|
|
Type: "error",
|
|
|
|
Value: err.Error(),
|
|
|
|
Version: jsonFormatVersion,
|
2013-01-12 12:22:59 -08:00
|
|
|
}
|
2013-01-10 17:27:03 -08:00
|
|
|
|
2014-04-22 06:16:37 -07:00
|
|
|
errorJSON, err := json.Marshal(errorStruct)
|
2013-01-12 12:22:59 -08:00
|
|
|
if err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return string(errorJSON)
|
2013-01-10 17:27:03 -08:00
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// TypedValueToJSON converts the given data of type 'scalar',
|
|
|
|
// 'vector', or 'matrix' into its JSON representation.
|
2013-01-15 02:30:55 -08:00
|
|
|
func TypedValueToJSON(data interface{}, typeStr string) string {
|
2013-01-12 12:22:59 -08:00
|
|
|
dataStruct := struct {
|
More efficient JSON query result format.
This depends on https://github.com/prometheus/client_golang/pull/51.
For vectors, the result format looks like this:
```json
{
"version": 1,
"type" : "vector",
"value" : [
{
"timestamp" : 1421765411.045,
"value" : "65.475000",
"metric" : {
"quantile" : "0.5",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "304"
}
},
{
"timestamp" : 1421765411.045,
"value" : "5826.339000",
"metric" : {
"quantile" : "0.9",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "prometheus",
"method" : "get",
"code" : "200"
}
},
/* ... */
]
}
```
For matrices, it looks like this:
```json
{
"version": 1,
"type" : "matrix",
"value" : [
{
"metric" : {
"quantile" : "0.99",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "200"
},
"values" : [
[
1421765547.659,
"29162.953000"
],
[
1421765548.659,
"29162.953000"
],
[
1421765549.659,
"29162.953000"
],
/* ... */
]
}
]
}
```
2015-01-20 06:13:49 -08:00
|
|
|
Type string `json:"type"`
|
|
|
|
Value interface{} `json:"value"`
|
|
|
|
Version int `json:"version"`
|
2013-01-12 12:22:59 -08:00
|
|
|
}{
|
More efficient JSON query result format.
This depends on https://github.com/prometheus/client_golang/pull/51.
For vectors, the result format looks like this:
```json
{
"version": 1,
"type" : "vector",
"value" : [
{
"timestamp" : 1421765411.045,
"value" : "65.475000",
"metric" : {
"quantile" : "0.5",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "304"
}
},
{
"timestamp" : 1421765411.045,
"value" : "5826.339000",
"metric" : {
"quantile" : "0.9",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "prometheus",
"method" : "get",
"code" : "200"
}
},
/* ... */
]
}
```
For matrices, it looks like this:
```json
{
"version": 1,
"type" : "matrix",
"value" : [
{
"metric" : {
"quantile" : "0.99",
"instance" : "http://localhost:9090/metrics",
"job" : "prometheus",
"__name__" : "http_request_duration_microseconds",
"handler" : "/static/",
"method" : "get",
"code" : "200"
},
"values" : [
[
1421765547.659,
"29162.953000"
],
[
1421765548.659,
"29162.953000"
],
[
1421765549.659,
"29162.953000"
],
/* ... */
]
}
]
}
```
2015-01-20 06:13:49 -08:00
|
|
|
Type: typeStr,
|
|
|
|
Value: data,
|
|
|
|
Version: jsonFormatVersion,
|
2013-01-12 12:22:59 -08:00
|
|
|
}
|
2014-04-22 06:16:37 -07:00
|
|
|
dataJSON, err := json.Marshal(dataStruct)
|
2013-01-12 12:22:59 -08:00
|
|
|
if err != nil {
|
2013-01-17 16:54:26 -08:00
|
|
|
return ErrorToJSON(err)
|
2013-01-12 12:22:59 -08:00
|
|
|
}
|
|
|
|
return string(dataJSON)
|
2013-01-10 17:27:03 -08:00
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// EvalToString evaluates the given node into a string of the given format.
|
2014-09-16 06:47:24 -07:00
|
|
|
func EvalToString(node Node, timestamp clientmodel.Timestamp, format OutputFormat, storage local.Storage, queryStats *stats.TimerGroup) string {
|
2015-02-02 23:04:27 -08:00
|
|
|
totalEvalTimer := queryStats.GetTimer(stats.TotalEvalTime).Start()
|
|
|
|
defer totalEvalTimer.Stop()
|
|
|
|
|
2014-06-06 02:55:53 -07:00
|
|
|
prepareTimer := queryStats.GetTimer(stats.TotalQueryPreparationTime).Start()
|
|
|
|
closer, err := prepareInstantQuery(node, timestamp, storage, queryStats)
|
|
|
|
prepareTimer.Stop()
|
2013-03-21 10:06:15 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2014-06-06 02:55:53 -07:00
|
|
|
defer closer.Close()
|
2013-03-21 10:06:15 -07:00
|
|
|
|
2013-06-03 08:07:03 -07:00
|
|
|
evalTimer := queryStats.GetTimer(stats.InnerEvalTime).Start()
|
2013-01-12 12:22:59 -08:00
|
|
|
switch node.Type() {
|
2014-12-24 16:28:35 -08:00
|
|
|
case ScalarType:
|
2014-06-06 02:55:53 -07:00
|
|
|
scalar := node.(ScalarNode).Eval(timestamp)
|
2013-06-03 08:07:03 -07:00
|
|
|
evalTimer.Stop()
|
2013-01-12 12:22:59 -08:00
|
|
|
switch format {
|
2014-12-24 16:28:35 -08:00
|
|
|
case Text:
|
2014-01-30 04:07:26 -08:00
|
|
|
return fmt.Sprintf("scalar: %v @[%v]", scalar, timestamp)
|
2013-01-12 12:22:59 -08:00
|
|
|
case JSON:
|
2013-01-15 02:30:55 -08:00
|
|
|
return TypedValueToJSON(scalar, "scalar")
|
2013-01-12 12:22:59 -08:00
|
|
|
}
|
2014-12-24 16:28:35 -08:00
|
|
|
case VectorType:
|
2014-06-06 02:55:53 -07:00
|
|
|
vector := node.(VectorNode).Eval(timestamp)
|
2013-06-03 08:07:03 -07:00
|
|
|
evalTimer.Stop()
|
2013-01-12 12:22:59 -08:00
|
|
|
switch format {
|
2014-12-24 16:28:35 -08:00
|
|
|
case Text:
|
2013-03-14 14:47:17 -07:00
|
|
|
return vector.String()
|
2013-01-12 12:22:59 -08:00
|
|
|
case JSON:
|
2013-01-15 02:30:55 -08:00
|
|
|
return TypedValueToJSON(vector, "vector")
|
2013-01-12 12:22:59 -08:00
|
|
|
}
|
2014-12-24 16:28:35 -08:00
|
|
|
case MatrixType:
|
2014-06-06 02:55:53 -07:00
|
|
|
matrix := node.(MatrixNode).Eval(timestamp)
|
2013-06-03 08:07:03 -07:00
|
|
|
evalTimer.Stop()
|
2013-01-12 12:22:59 -08:00
|
|
|
switch format {
|
2014-12-24 16:28:35 -08:00
|
|
|
case Text:
|
2013-03-14 14:47:17 -07:00
|
|
|
return matrix.String()
|
2013-01-12 12:22:59 -08:00
|
|
|
case JSON:
|
2013-01-15 02:30:55 -08:00
|
|
|
return TypedValueToJSON(matrix, "matrix")
|
2013-01-12 12:22:59 -08:00
|
|
|
}
|
2014-12-24 16:28:35 -08:00
|
|
|
case StringType:
|
2014-06-06 02:55:53 -07:00
|
|
|
str := node.(StringNode).Eval(timestamp)
|
2013-06-03 08:07:03 -07:00
|
|
|
evalTimer.Stop()
|
2013-01-12 12:22:59 -08:00
|
|
|
switch format {
|
2014-12-24 16:28:35 -08:00
|
|
|
case Text:
|
2013-01-12 12:22:59 -08:00
|
|
|
return str
|
|
|
|
case JSON:
|
2013-01-15 02:30:55 -08:00
|
|
|
return TypedValueToJSON(str, "string")
|
2013-01-12 12:22:59 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
panic("Switch didn't cover all node types")
|
2014-05-28 10:44:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// EvalToVector evaluates the given node into a Vector. Matrices aren't supported.
|
2014-09-16 06:47:24 -07:00
|
|
|
func EvalToVector(node Node, timestamp clientmodel.Timestamp, storage local.Storage, queryStats *stats.TimerGroup) (Vector, error) {
|
2015-02-02 23:04:27 -08:00
|
|
|
totalEvalTimer := queryStats.GetTimer(stats.TotalEvalTime).Start()
|
|
|
|
defer totalEvalTimer.Stop()
|
|
|
|
|
2014-06-06 02:55:53 -07:00
|
|
|
prepareTimer := queryStats.GetTimer(stats.TotalQueryPreparationTime).Start()
|
|
|
|
closer, err := prepareInstantQuery(node, timestamp, storage, queryStats)
|
|
|
|
prepareTimer.Stop()
|
2014-05-28 10:44:54 -07:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2014-06-06 02:55:53 -07:00
|
|
|
defer closer.Close()
|
2014-05-28 10:44:54 -07:00
|
|
|
|
|
|
|
evalTimer := queryStats.GetTimer(stats.InnerEvalTime).Start()
|
|
|
|
switch node.Type() {
|
2014-12-24 16:28:35 -08:00
|
|
|
case ScalarType:
|
2014-06-06 02:55:53 -07:00
|
|
|
scalar := node.(ScalarNode).Eval(timestamp)
|
2014-05-28 10:44:54 -07:00
|
|
|
evalTimer.Stop()
|
2014-12-08 07:55:49 -08:00
|
|
|
return Vector{&Sample{Value: scalar}}, nil
|
2014-12-24 16:28:35 -08:00
|
|
|
case VectorType:
|
2014-06-06 02:55:53 -07:00
|
|
|
vector := node.(VectorNode).Eval(timestamp)
|
2014-05-28 10:44:54 -07:00
|
|
|
evalTimer.Stop()
|
|
|
|
return vector, nil
|
2014-12-24 16:28:35 -08:00
|
|
|
case MatrixType:
|
2014-12-10 07:16:49 -08:00
|
|
|
return nil, errors.New("matrices not supported by EvalToVector")
|
2014-12-24 16:28:35 -08:00
|
|
|
case StringType:
|
2014-06-06 02:55:53 -07:00
|
|
|
str := node.(StringNode).Eval(timestamp)
|
2014-05-28 10:44:54 -07:00
|
|
|
evalTimer.Stop()
|
2014-12-08 07:55:49 -08:00
|
|
|
return Vector{
|
|
|
|
&Sample{
|
|
|
|
Metric: clientmodel.COWMetric{
|
|
|
|
Metric: clientmodel.Metric{
|
|
|
|
"__value__": clientmodel.LabelValue(str),
|
|
|
|
},
|
|
|
|
Copied: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil
|
2014-05-28 10:44:54 -07:00
|
|
|
}
|
|
|
|
panic("Switch didn't cover all node types")
|
2013-01-10 17:27:03 -08:00
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the scalar
|
|
|
|
// literal.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *ScalarLiteral) NodeTreeToDotGraph() string {
|
|
|
|
return fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func functionArgsToDotGraph(node Node, args []Node) string {
|
|
|
|
graph := ""
|
|
|
|
for _, arg := range args {
|
2014-12-10 07:16:49 -08:00
|
|
|
graph += fmt.Sprintf("%x -> %x;\n", reflect.ValueOf(node).Pointer(), reflect.ValueOf(arg).Pointer())
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
for _, arg := range args {
|
|
|
|
graph += arg.NodeTreeToDotGraph()
|
|
|
|
}
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the function
|
|
|
|
// call.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *ScalarFunctionCall) NodeTreeToDotGraph() string {
|
2013-04-26 07:02:52 -07:00
|
|
|
graph := fmt.Sprintf("%#p[label=\"%s\"];\n", node, node.function.name)
|
2013-01-07 14:24:26 -08:00
|
|
|
graph += functionArgsToDotGraph(node, node.args)
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the expression.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *ScalarArithExpr) NodeTreeToDotGraph() string {
|
2014-12-10 07:16:49 -08:00
|
|
|
nodeAddr := reflect.ValueOf(node).Pointer()
|
|
|
|
graph := fmt.Sprintf(
|
|
|
|
`
|
|
|
|
%x[label="%s"];
|
|
|
|
%x -> %x;
|
|
|
|
%x -> %x;
|
2013-04-26 07:02:52 -07:00
|
|
|
%s
|
|
|
|
%s
|
2014-12-10 07:16:49 -08:00
|
|
|
}`,
|
|
|
|
nodeAddr, node.opType,
|
|
|
|
nodeAddr, reflect.ValueOf(node.lhs).Pointer(),
|
|
|
|
nodeAddr, reflect.ValueOf(node.rhs).Pointer(),
|
|
|
|
node.lhs.NodeTreeToDotGraph(),
|
|
|
|
node.rhs.NodeTreeToDotGraph(),
|
|
|
|
)
|
2013-01-07 14:24:26 -08:00
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
2014-02-22 13:29:32 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the vector selector.
|
|
|
|
func (node *VectorSelector) NodeTreeToDotGraph() string {
|
2013-04-26 07:02:52 -07:00
|
|
|
return fmt.Sprintf("%#p[label=\"%s\"];\n", node, node)
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the function
|
|
|
|
// call.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *VectorFunctionCall) NodeTreeToDotGraph() string {
|
2013-04-26 07:02:52 -07:00
|
|
|
graph := fmt.Sprintf("%#p[label=\"%s\"];\n", node, node.function.name)
|
2013-01-07 14:24:26 -08:00
|
|
|
graph += functionArgsToDotGraph(node, node.args)
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the vector
|
|
|
|
// aggregation.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *VectorAggregation) NodeTreeToDotGraph() string {
|
2013-06-06 06:12:37 -07:00
|
|
|
groupByStrings := make([]string, 0, len(node.groupBy))
|
2013-01-07 14:24:26 -08:00
|
|
|
for _, label := range node.groupBy {
|
|
|
|
groupByStrings = append(groupByStrings, string(label))
|
|
|
|
}
|
|
|
|
|
2013-04-26 07:02:52 -07:00
|
|
|
graph := fmt.Sprintf("%#p[label=\"%s BY (%s)\"]\n",
|
2013-01-07 14:24:26 -08:00
|
|
|
node,
|
2013-04-26 07:02:52 -07:00
|
|
|
node.aggrType,
|
2013-01-07 14:24:26 -08:00
|
|
|
strings.Join(groupByStrings, ", "))
|
2014-12-10 07:16:49 -08:00
|
|
|
graph += fmt.Sprintf("%#p -> %x;\n", node, reflect.ValueOf(node.vector).Pointer())
|
2013-01-07 14:24:26 -08:00
|
|
|
graph += node.vector.NodeTreeToDotGraph()
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the expression.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *VectorArithExpr) NodeTreeToDotGraph() string {
|
2014-12-10 07:16:49 -08:00
|
|
|
nodeAddr := reflect.ValueOf(node).Pointer()
|
|
|
|
graph := fmt.Sprintf(
|
|
|
|
`
|
|
|
|
%x[label="%s"];
|
|
|
|
%x -> %x;
|
|
|
|
%x -> %x;
|
2013-04-26 07:02:52 -07:00
|
|
|
%s
|
|
|
|
%s
|
2014-12-10 07:16:49 -08:00
|
|
|
}`,
|
|
|
|
nodeAddr, node.opType,
|
|
|
|
nodeAddr, reflect.ValueOf(node.lhs).Pointer(),
|
|
|
|
nodeAddr, reflect.ValueOf(node.rhs).Pointer(),
|
|
|
|
node.lhs.NodeTreeToDotGraph(),
|
|
|
|
node.rhs.NodeTreeToDotGraph(),
|
|
|
|
)
|
2013-01-07 14:24:26 -08:00
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the matrix
|
2014-02-22 13:29:32 -08:00
|
|
|
// selector.
|
|
|
|
func (node *MatrixSelector) NodeTreeToDotGraph() string {
|
2013-04-26 07:02:52 -07:00
|
|
|
return fmt.Sprintf("%#p[label=\"%s\"];\n", node, node)
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the string
|
|
|
|
// literal.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *StringLiteral) NodeTreeToDotGraph() string {
|
2013-06-11 02:01:36 -07:00
|
|
|
return fmt.Sprintf("%#p[label=\"'%q'\"];\n", node, node.str)
|
2013-01-07 14:24:26 -08:00
|
|
|
}
|
|
|
|
|
2014-02-13 09:48:56 -08:00
|
|
|
// NodeTreeToDotGraph returns a DOT representation of the function
|
|
|
|
// call.
|
2013-01-07 14:24:26 -08:00
|
|
|
func (node *StringFunctionCall) NodeTreeToDotGraph() string {
|
2013-04-26 07:02:52 -07:00
|
|
|
graph := fmt.Sprintf("%#p[label=\"%s\"];\n", node, node.function.name)
|
2013-01-07 14:24:26 -08:00
|
|
|
graph += functionArgsToDotGraph(node, node.args)
|
|
|
|
return graph
|
|
|
|
}
|
2013-06-06 06:12:37 -07:00
|
|
|
|
|
|
|
func (nodes Nodes) String() string {
|
|
|
|
nodeStrings := make([]string, 0, len(nodes))
|
|
|
|
for _, node := range nodes {
|
|
|
|
nodeStrings = append(nodeStrings, node.String())
|
|
|
|
}
|
|
|
|
return strings.Join(nodeStrings, ", ")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *ScalarLiteral) String() string {
|
|
|
|
return fmt.Sprint(node.value)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *ScalarFunctionCall) String() string {
|
|
|
|
return fmt.Sprintf("%s(%s)", node.function.name, node.args)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *ScalarArithExpr) String() string {
|
|
|
|
return fmt.Sprintf("(%s %s %s)", node.lhs, node.opType, node.rhs)
|
|
|
|
}
|
|
|
|
|
2014-02-22 13:29:32 -08:00
|
|
|
func (node *VectorSelector) String() string {
|
2014-03-28 03:58:47 -07:00
|
|
|
labelStrings := make([]string, 0, len(node.labelMatchers)-1)
|
|
|
|
var metricName clientmodel.LabelValue
|
|
|
|
for _, matcher := range node.labelMatchers {
|
|
|
|
if matcher.Name != clientmodel.MetricNameLabel {
|
|
|
|
labelStrings = append(labelStrings, fmt.Sprintf("%s%s%q", matcher.Name, matcher.Type, matcher.Value))
|
|
|
|
} else {
|
|
|
|
metricName = matcher.Value
|
2013-06-06 06:12:37 -07:00
|
|
|
}
|
|
|
|
}
|
2013-06-11 02:01:36 -07:00
|
|
|
|
|
|
|
switch len(labelStrings) {
|
|
|
|
case 0:
|
|
|
|
return string(metricName)
|
|
|
|
default:
|
|
|
|
sort.Strings(labelStrings)
|
|
|
|
return fmt.Sprintf("%s{%s}", metricName, strings.Join(labelStrings, ","))
|
|
|
|
}
|
2013-06-06 06:12:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (node *VectorFunctionCall) String() string {
|
|
|
|
return fmt.Sprintf("%s(%s)", node.function.name, node.args)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *VectorAggregation) String() string {
|
2013-06-13 07:10:05 -07:00
|
|
|
aggrString := fmt.Sprintf("%s(%s)", node.aggrType, node.vector)
|
|
|
|
if len(node.groupBy) > 0 {
|
|
|
|
return fmt.Sprintf("%s BY (%s)", aggrString, node.groupBy)
|
|
|
|
}
|
2014-02-13 09:48:56 -08:00
|
|
|
return aggrString
|
2013-06-06 06:12:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (node *VectorArithExpr) String() string {
|
|
|
|
return fmt.Sprintf("(%s %s %s)", node.lhs, node.opType, node.rhs)
|
|
|
|
}
|
|
|
|
|
2014-02-22 13:29:32 -08:00
|
|
|
func (node *MatrixSelector) String() string {
|
2014-03-28 03:58:47 -07:00
|
|
|
vectorString := (&VectorSelector{labelMatchers: node.labelMatchers}).String()
|
2013-06-06 06:12:37 -07:00
|
|
|
intervalString := fmt.Sprintf("[%s]", utility.DurationToString(node.interval))
|
|
|
|
return vectorString + intervalString
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *StringLiteral) String() string {
|
2013-06-11 02:01:36 -07:00
|
|
|
return fmt.Sprintf("%q", node.str)
|
2013-06-06 06:12:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (node *StringFunctionCall) String() string {
|
|
|
|
return fmt.Sprintf("%s(%s)", node.function.name, node.args)
|
|
|
|
}
|