2013-02-07 10:49:04 +00:00
|
|
|
// Copyright 2013 Prometheus Team
|
|
|
|
// 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 22:24:26 +00:00
|
|
|
package ast
|
|
|
|
|
|
|
|
import (
|
2013-01-12 20:22:59 +00:00
|
|
|
"encoding/json"
|
2013-01-07 22:24:26 +00:00
|
|
|
"fmt"
|
2013-02-13 16:41:35 +00:00
|
|
|
"github.com/prometheus/prometheus/utility"
|
2013-01-07 22:24:26 +00:00
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2013-01-11 01:27:03 +00:00
|
|
|
type OutputFormat int
|
|
|
|
|
|
|
|
const (
|
2013-01-12 20:22:59 +00:00
|
|
|
TEXT OutputFormat = iota
|
|
|
|
JSON
|
2013-01-11 01:27:03 +00:00
|
|
|
)
|
|
|
|
|
2013-01-07 22:24:26 +00:00
|
|
|
func binOpTypeToString(opType BinOpType) string {
|
|
|
|
opTypeMap := map[BinOpType]string{
|
|
|
|
ADD: "+",
|
|
|
|
SUB: "-",
|
|
|
|
MUL: "*",
|
|
|
|
DIV: "/",
|
|
|
|
MOD: "%",
|
|
|
|
GT: ">",
|
|
|
|
LT: "<",
|
|
|
|
EQ: "==",
|
|
|
|
NE: "!=",
|
|
|
|
GE: ">=",
|
|
|
|
LE: "<=",
|
|
|
|
}
|
|
|
|
return opTypeMap[opType]
|
|
|
|
}
|
|
|
|
|
|
|
|
func aggrTypeToString(aggrType AggrType) string {
|
|
|
|
aggrTypeMap := map[AggrType]string{
|
|
|
|
SUM: "SUM",
|
|
|
|
AVG: "AVG",
|
|
|
|
MIN: "MIN",
|
|
|
|
MAX: "MAX",
|
|
|
|
}
|
|
|
|
return aggrTypeMap[aggrType]
|
|
|
|
}
|
|
|
|
|
2013-01-11 01:27:03 +00:00
|
|
|
func exprTypeToString(exprType ExprType) string {
|
|
|
|
exprTypeMap := map[ExprType]string{
|
|
|
|
SCALAR: "scalar",
|
|
|
|
VECTOR: "vector",
|
|
|
|
MATRIX: "matrix",
|
|
|
|
STRING: "string",
|
|
|
|
}
|
|
|
|
return exprTypeMap[exprType]
|
|
|
|
}
|
|
|
|
|
2013-01-07 22:24:26 +00:00
|
|
|
func (vector Vector) ToString() string {
|
|
|
|
metricStrings := []string{}
|
|
|
|
for _, sample := range vector {
|
|
|
|
metricName, ok := sample.Metric["name"]
|
|
|
|
if !ok {
|
|
|
|
panic("Tried to print vector without metric name")
|
|
|
|
}
|
|
|
|
labelStrings := []string{}
|
|
|
|
for label, value := range sample.Metric {
|
|
|
|
if label != "name" {
|
2013-01-17 23:07:00 +00:00
|
|
|
// TODO escape special chars in label values here and elsewhere.
|
2013-01-07 22:24:26 +00:00
|
|
|
labelStrings = append(labelStrings, fmt.Sprintf("%v='%v'", label, value))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Strings(labelStrings)
|
|
|
|
metricStrings = append(metricStrings,
|
|
|
|
fmt.Sprintf("%v{%v} => %v @[%v]",
|
|
|
|
metricName,
|
|
|
|
strings.Join(labelStrings, ","),
|
|
|
|
sample.Value, sample.Timestamp))
|
|
|
|
}
|
|
|
|
sort.Strings(metricStrings)
|
|
|
|
return strings.Join(metricStrings, "\n")
|
|
|
|
}
|
|
|
|
|
2013-01-11 01:27:03 +00:00
|
|
|
func (matrix Matrix) ToString() string {
|
|
|
|
metricStrings := []string{}
|
|
|
|
for _, sampleSet := range matrix {
|
|
|
|
metricName, ok := sampleSet.Metric["name"]
|
|
|
|
if !ok {
|
|
|
|
panic("Tried to print matrix without metric name")
|
|
|
|
}
|
|
|
|
labelStrings := []string{}
|
|
|
|
for label, value := range sampleSet.Metric {
|
|
|
|
if label != "name" {
|
|
|
|
labelStrings = append(labelStrings, fmt.Sprintf("%v='%v'", label, value))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Strings(labelStrings)
|
2013-01-12 20:22:59 +00:00
|
|
|
valueStrings := []string{}
|
|
|
|
for _, value := range sampleSet.Values {
|
|
|
|
valueStrings = append(valueStrings,
|
|
|
|
fmt.Sprintf("\n%v @[%v]", value.Value, value.Timestamp))
|
|
|
|
}
|
2013-01-11 01:27:03 +00:00
|
|
|
metricStrings = append(metricStrings,
|
|
|
|
fmt.Sprintf("%v{%v} => %v",
|
|
|
|
metricName,
|
|
|
|
strings.Join(labelStrings, ","),
|
|
|
|
strings.Join(valueStrings, ", ")))
|
|
|
|
}
|
|
|
|
sort.Strings(metricStrings)
|
|
|
|
return strings.Join(metricStrings, "\n")
|
|
|
|
}
|
|
|
|
|
2013-01-18 00:54:26 +00:00
|
|
|
func ErrorToJSON(err error) string {
|
2013-01-12 20:22:59 +00:00
|
|
|
errorStruct := struct {
|
|
|
|
Type string
|
2013-01-22 00:50:16 +00:00
|
|
|
Value string
|
2013-01-12 20:22:59 +00:00
|
|
|
}{
|
|
|
|
Type: "error",
|
2013-01-22 00:50:16 +00:00
|
|
|
Value: err.Error(),
|
2013-01-12 20:22:59 +00:00
|
|
|
}
|
2013-01-11 01:27:03 +00:00
|
|
|
|
2013-01-12 20:22:59 +00:00
|
|
|
errorJSON, err := json.MarshalIndent(errorStruct, "", "\t")
|
|
|
|
if err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return string(errorJSON)
|
2013-01-11 01:27:03 +00:00
|
|
|
}
|
|
|
|
|
2013-01-15 10:30:55 +00:00
|
|
|
func TypedValueToJSON(data interface{}, typeStr string) string {
|
2013-01-12 20:22:59 +00:00
|
|
|
dataStruct := struct {
|
|
|
|
Type string
|
|
|
|
Value interface{}
|
|
|
|
}{
|
|
|
|
Type: typeStr,
|
|
|
|
Value: data,
|
|
|
|
}
|
|
|
|
dataJSON, err := json.MarshalIndent(dataStruct, "", "\t")
|
|
|
|
if err != nil {
|
2013-01-18 00:54:26 +00:00
|
|
|
return ErrorToJSON(err)
|
2013-01-12 20:22:59 +00:00
|
|
|
}
|
|
|
|
return string(dataJSON)
|
2013-01-11 01:27:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func EvalToString(node Node, timestamp *time.Time, format OutputFormat) string {
|
2013-01-12 20:22:59 +00:00
|
|
|
switch node.Type() {
|
|
|
|
case SCALAR:
|
|
|
|
scalar := node.(ScalarNode).Eval(timestamp)
|
|
|
|
switch format {
|
|
|
|
case TEXT:
|
|
|
|
return fmt.Sprintf("scalar: %v", scalar)
|
|
|
|
case JSON:
|
2013-01-15 10:30:55 +00:00
|
|
|
return TypedValueToJSON(scalar, "scalar")
|
2013-01-12 20:22:59 +00:00
|
|
|
}
|
|
|
|
case VECTOR:
|
|
|
|
vector := node.(VectorNode).Eval(timestamp)
|
|
|
|
switch format {
|
|
|
|
case TEXT:
|
|
|
|
return vector.ToString()
|
|
|
|
case JSON:
|
2013-01-15 10:30:55 +00:00
|
|
|
return TypedValueToJSON(vector, "vector")
|
2013-01-12 20:22:59 +00:00
|
|
|
}
|
|
|
|
case MATRIX:
|
|
|
|
matrix := node.(MatrixNode).Eval(timestamp)
|
|
|
|
switch format {
|
|
|
|
case TEXT:
|
|
|
|
return matrix.ToString()
|
|
|
|
case JSON:
|
2013-01-15 10:30:55 +00:00
|
|
|
return TypedValueToJSON(matrix, "matrix")
|
2013-01-12 20:22:59 +00:00
|
|
|
}
|
|
|
|
case STRING:
|
|
|
|
str := node.(StringNode).Eval(timestamp)
|
|
|
|
switch format {
|
|
|
|
case TEXT:
|
|
|
|
return str
|
|
|
|
case JSON:
|
2013-01-15 10:30:55 +00:00
|
|
|
return TypedValueToJSON(str, "string")
|
2013-01-12 20:22:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
panic("Switch didn't cover all node types")
|
2013-01-11 01:27:03 +00:00
|
|
|
}
|
|
|
|
|
2013-01-07 22:24:26 +00:00
|
|
|
func (node *VectorLiteral) ToString() string {
|
|
|
|
metricName, ok := node.labels["name"]
|
|
|
|
if !ok {
|
|
|
|
panic("Tried to print vector without metric name")
|
|
|
|
}
|
|
|
|
labelStrings := []string{}
|
|
|
|
for label, value := range node.labels {
|
|
|
|
if label != "name" {
|
|
|
|
labelStrings = append(labelStrings, fmt.Sprintf("%v='%v'", label, value))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Strings(labelStrings)
|
|
|
|
return fmt.Sprintf("%v{%v}", metricName, strings.Join(labelStrings, ","))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *MatrixLiteral) ToString() string {
|
|
|
|
vectorString := (&VectorLiteral{labels: node.labels}).ToString()
|
2013-02-13 16:41:35 +00:00
|
|
|
intervalString := fmt.Sprintf("['%v']", utility.DurationToString(node.interval))
|
2013-01-07 22:24:26 +00:00
|
|
|
return vectorString + intervalString
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
graph += fmt.Sprintf("%#p -> %#p;\n", node, arg)
|
|
|
|
}
|
|
|
|
for _, arg := range args {
|
|
|
|
graph += arg.NodeTreeToDotGraph()
|
|
|
|
}
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *ScalarFunctionCall) NodeTreeToDotGraph() string {
|
|
|
|
graph := fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.function.name)
|
|
|
|
graph += functionArgsToDotGraph(node, node.args)
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *ScalarArithExpr) NodeTreeToDotGraph() string {
|
|
|
|
graph := fmt.Sprintf("%#p[label=\"%v\"];\n", node, binOpTypeToString(node.opType))
|
|
|
|
graph += fmt.Sprintf("%#p -> %#p;\n", node, node.lhs)
|
|
|
|
graph += fmt.Sprintf("%#p -> %#p;\n", node, node.rhs)
|
|
|
|
graph += node.lhs.NodeTreeToDotGraph()
|
|
|
|
graph += node.rhs.NodeTreeToDotGraph()
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *VectorLiteral) NodeTreeToDotGraph() string {
|
|
|
|
return fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.ToString())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *VectorFunctionCall) NodeTreeToDotGraph() string {
|
|
|
|
graph := fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.function.name)
|
|
|
|
graph += functionArgsToDotGraph(node, node.args)
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *VectorAggregation) NodeTreeToDotGraph() string {
|
|
|
|
groupByStrings := []string{}
|
|
|
|
for _, label := range node.groupBy {
|
|
|
|
groupByStrings = append(groupByStrings, string(label))
|
|
|
|
}
|
|
|
|
|
|
|
|
graph := fmt.Sprintf("%#p[label=\"%v BY (%v)\"]\n",
|
|
|
|
node,
|
|
|
|
aggrTypeToString(node.aggrType),
|
|
|
|
strings.Join(groupByStrings, ", "))
|
|
|
|
graph += fmt.Sprintf("%#p -> %#p;\n", node, node.vector)
|
|
|
|
graph += node.vector.NodeTreeToDotGraph()
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *VectorArithExpr) NodeTreeToDotGraph() string {
|
|
|
|
graph := fmt.Sprintf("%#p[label=\"%v\"];\n", node, binOpTypeToString(node.opType))
|
|
|
|
graph += fmt.Sprintf("%#p -> %#p;\n", node, node.lhs)
|
|
|
|
graph += fmt.Sprintf("%#p -> %#p;\n", node, node.rhs)
|
|
|
|
graph += node.lhs.NodeTreeToDotGraph()
|
|
|
|
graph += node.rhs.NodeTreeToDotGraph()
|
|
|
|
return graph
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *MatrixLiteral) NodeTreeToDotGraph() string {
|
|
|
|
return fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.ToString())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *StringLiteral) NodeTreeToDotGraph() string {
|
|
|
|
return fmt.Sprintf("%#p[label=\"'%v'\"];\n", node.str)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (node *StringFunctionCall) NodeTreeToDotGraph() string {
|
|
|
|
graph := fmt.Sprintf("%#p[label=\"%v\"];\n", node, node.function.name)
|
|
|
|
graph += functionArgsToDotGraph(node, node.args)
|
|
|
|
return graph
|
|
|
|
}
|