Forráskód Böngészése

feat(influxdb): add query part definitions

bergquist 9 éve
szülő
commit
9968fa5bc5

+ 25 - 6
pkg/tsdb/influxdb/parser.go

@@ -1,6 +1,10 @@
 package influxdb
 
-import "github.com/grafana/grafana/pkg/components/simplejson"
+import (
+	"strconv"
+
+	"github.com/grafana/grafana/pkg/components/simplejson"
+)
 
 type InfluxdbQueryParser struct{}
 
@@ -108,14 +112,29 @@ func (*InfluxdbQueryParser) parseQueryPart(model *simplejson.Json) (*QueryPart,
 	for _, paramObj := range model.Get("params").MustArray() {
 		param := simplejson.NewFromAny(paramObj)
 
-		pv, err := param.String()
-		if err != nil {
-			return nil, err
+		stringParam, err := param.String()
+		if err == nil {
+			params = append(params, stringParam)
+			continue
+		}
+
+		intParam, err := param.Int()
+		if err == nil {
+			params = append(params, strconv.Itoa(intParam))
+			continue
 		}
-		params = append(params, pv)
+
+		return nil, err
+
+	}
+
+	qp, err := NewQueryPart(typ, params)
+	if err != nil {
+		return nil, err
 	}
 
-	return &QueryPart{Type: typ, Params: params}, nil
+	return qp, nil
+	//return &QueryPart{Type: typ, Params: params}, nil
 }
 
 func (qp *InfluxdbQueryParser) parseGroupBy(model *simplejson.Json) ([]*QueryPart, error) {

+ 6 - 4
pkg/tsdb/influxdb/parser_test.go

@@ -14,7 +14,7 @@ func TestInfluxdbQueryParser(t *testing.T) {
 
 		Convey("converting metric name", func() {
 			json := `
-                  {
+      {
               "dsType": "influxdb",
               "groupBy": [
                 {
@@ -31,7 +31,7 @@ func TestInfluxdbQueryParser(t *testing.T) {
                 },
                 {
                   "params": [
-                    "null"
+                    "none"
                   ],
                   "type": "fill"
                 }
@@ -61,8 +61,10 @@ func TestInfluxdbQueryParser(t *testing.T) {
                     ]
                   },
                   {
-                    "type": "mean",
-                    "params": []
+                    "type": "bottom",
+                    "params": [
+                      3
+                    ]
                   }
                 ],
                 [

+ 32 - 19
pkg/tsdb/influxdb/query_part.go

@@ -7,8 +7,14 @@ import (
 
 var renders map[string]QueryDefinition
 
+type DefinitionParameters struct {
+	Name string
+	Type string
+}
+
 type QueryDefinition struct {
 	Renderer func(part *QueryPart, innerExpr string) string
+	Params   []DefinitionParameters
 }
 
 func init() {
@@ -26,34 +32,34 @@ func init() {
 
 	renders["derivative"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h']}],
+		Params:   []DefinitionParameters{{Name: "duration", Type: "interval"}},
 	}
 
 	renders["non_negative_derivative"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h']}],
+		Params:   []DefinitionParameters{{Name: "duration", Type: "interval"}},
 	}
 	renders["difference"] = QueryDefinition{Renderer: functionRenderer}
 	renders["moving_average"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{ name: "window", type: "number", options: [5, 10, 20, 30, 40]}]
+		Params:   []DefinitionParameters{{Name: "window", Type: "number"}},
 	}
 	renders["stddev"] = QueryDefinition{Renderer: functionRenderer}
 	renders["time"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{ name: "interval", type: "time", options: ['auto', '1s', '10s', '1m', '5m', '10m', '15m', '1h'] }],
+		Params:   []DefinitionParameters{{Name: "interval", Type: "time"}},
 	}
 	renders["fill"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{ name: "fill", type: "string", options: ['none', 'null', '0', 'previous'] }],
+		Params:   []DefinitionParameters{{Name: "fill", Type: "string"}},
 	}
 	renders["elapsed"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{ name: "duration", type: "interval", options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h']}],
+		Params:   []DefinitionParameters{{Name: "duration", Type: "interval"}},
 	}
 	renders["bottom"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{name: 'count', type: 'int'}],
+		Params:   []DefinitionParameters{{Name: "count", Type: "int"}},
 	}
 
 	renders["first"] = QueryDefinition{Renderer: functionRenderer}
@@ -62,15 +68,15 @@ func init() {
 	renders["min"] = QueryDefinition{Renderer: functionRenderer}
 	renders["percentile"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{name: 'nth', type: 'int'}],
+		Params:   []DefinitionParameters{{Name: "nth", Type: "int"}},
 	}
 	renders["top"] = QueryDefinition{
 		Renderer: functionRenderer,
-		//params: [{name: 'count', type: 'int'}],
+		Params:   []DefinitionParameters{{Name: "count", Type: "int"}},
 	}
 	renders["tag"] = QueryDefinition{
 		Renderer: fieldRenderer,
-		//params: [{name: 'tag', type: 'string', dynamicLookup: true}],
+		Params:   []DefinitionParameters{{Name: "tag", Type: "string"}},
 	}
 
 	renders["math"] = QueryDefinition{Renderer: suffixRenderer}
@@ -81,7 +87,7 @@ func fieldRenderer(part *QueryPart, innerExpr string) string {
 	if part.Params[0] == "*" {
 		return "*"
 	}
-	return fmt.Sprintf(`"%v"`, part.Params[0])
+	return fmt.Sprintf(`"%s"`, part.Params[0])
 }
 
 func functionRenderer(part *QueryPart, innerExpr string) string {
@@ -106,19 +112,26 @@ func (r QueryDefinition) Render(part *QueryPart, innerExpr string) string {
 	return r.Renderer(part, innerExpr)
 }
 
-type QueryPartDefinition struct {
+func NewQueryPart(typ string, params []string) (*QueryPart, error) {
+	def, exist := renders[typ]
+
+	if !exist {
+		return nil, fmt.Errorf("Missing query definition for %s", typ)
+	}
+
+	return &QueryPart{
+		Type:   typ,
+		Params: params,
+		Def:    def,
+	}, nil
 }
 
 type QueryPart struct {
+	Def    QueryDefinition
 	Type   string
 	Params []string
 }
 
-func (qp *QueryPart) Render(expr string) (string, error) {
-	renderFn, exist := renders[qp.Type]
-	if !exist {
-		return "", fmt.Errorf("could not find render strategy %s", qp.Type)
-	}
-
-	return renderFn.Renderer(qp, expr), nil
+func (qp *QueryPart) Render(expr string) string {
+	return qp.Def.Renderer(qp, expr)
 }

+ 24 - 26
pkg/tsdb/influxdb/query_part_test.go

@@ -10,52 +10,50 @@ func TestInfluxdbQueryPart(t *testing.T) {
 	Convey("Influxdb query part builder", t, func() {
 
 		Convey("should handle field renderer parts", func() {
-			part := QueryPart{
-				Type:   "field",
-				Params: []string{"value"},
-			}
+			part, err := NewQueryPart("field", []string{"value"})
+			So(err, ShouldBeNil)
 
-			res, _ := part.Render("value")
+			res := part.Render("value")
 			So(res, ShouldEqual, `"value"`)
 		})
 
 		Convey("should handle nested function parts", func() {
-			part := QueryPart{
-				Type:   "derivative",
-				Params: []string{"10s"},
-			}
+			part, err := NewQueryPart("derivative", []string{"10s"})
+			So(err, ShouldBeNil)
 
-			res, _ := part.Render("mean(value)")
+			res := part.Render("mean(value)")
 			So(res, ShouldEqual, "derivative(mean(value), 10s)")
 		})
 
-		Convey("should nest spread function", func() {
-			part := QueryPart{
-				Type: "spread",
-			}
+		Convey("bottom", func() {
+			part, err := NewQueryPart("bottom", []string{"3"})
+			So(err, ShouldBeNil)
+
+			res := part.Render("value")
+			So(res, ShouldEqual, "bottom(value, 3)")
+		})
 
-			res, err := part.Render("value")
+		Convey("should nest spread function", func() {
+			part, err := NewQueryPart("spread", []string{})
 			So(err, ShouldBeNil)
-			So(res, ShouldEqual, "spread(value)")
+
+			res := part.Render("value")
+			So(res, ShouldEqual, `spread(value)`)
 		})
 
 		Convey("should handle suffix parts", func() {
-			part := QueryPart{
-				Type:   "math",
-				Params: []string{"/ 100"},
-			}
+			part, err := NewQueryPart("math", []string{"/ 100"})
+			So(err, ShouldBeNil)
 
-			res, _ := part.Render("mean(value)")
+			res := part.Render("mean(value)")
 			So(res, ShouldEqual, "mean(value) / 100")
 		})
 
 		Convey("should handle alias parts", func() {
-			part := QueryPart{
-				Type:   "alias",
-				Params: []string{"test"},
-			}
+			part, err := NewQueryPart("alias", []string{"test"})
+			So(err, ShouldBeNil)
 
-			res, _ := part.Render("mean(value)")
+			res := part.Render("mean(value)")
 			So(res, ShouldEqual, `mean(value) AS "test"`)
 		})
 	})