Rename queryConfig field to Value and support top/bottom

pull/10616/head
Chris Goller 2017-10-16 10:56:12 -05:00
parent 6d6a2d4a2a
commit 7b786657aa
13 changed files with 316 additions and 187 deletions

View File

@ -495,7 +495,7 @@ type TriggerValues struct {
// Field represent influxql fields and functions from the UI
type Field struct {
Name interface{} `json:"name"`
Value interface{} `json:"value"`
Type string `json:"type"`
Alias string `json:"alias"`
Args []Field `json:"args,omitempty"`

View File

@ -152,18 +152,28 @@ func Convert(influxQL string) (chronograf.QueryConfig, error) {
switch ref := arg.(type) {
case *influxql.VarRef:
fldArgs = append(fldArgs, chronograf.Field{
Name: ref.Val,
Type: "field",
Value: ref.Val,
Type: "field",
})
case *influxql.IntegerLiteral:
fldArgs = append(fldArgs, chronograf.Field{
Name: ref.Val,
Type: "integer",
Value: ref.Val,
Type: "integer",
})
case *influxql.NumberLiteral:
fldArgs = append(fldArgs, chronograf.Field{
Name: ref.Val,
Type: "number",
Value: ref.Val,
Type: "number",
})
case *influxql.RegexLiteral:
fldArgs = append(fldArgs, chronograf.Field{
Value: ref.Val.String(),
Type: "regex",
})
case *influxql.Wildcard:
fldArgs = append(fldArgs, chronograf.Field{
Value: "*",
Type: "wildcard",
})
default:
return raw, nil
@ -171,7 +181,7 @@ func Convert(influxQL string) (chronograf.QueryConfig, error) {
}
qc.Fields = append(qc.Fields, chronograf.Field{
Name: f.Name,
Value: f.Name,
Type: "func",
Alias: fld.Alias,
Args: fldArgs,
@ -181,7 +191,7 @@ func Convert(influxQL string) (chronograf.QueryConfig, error) {
return raw, nil
}
qc.Fields = append(qc.Fields, chronograf.Field{
Name: f.Val,
Value: f.Val,
Type: "field",
Alias: fld.Alias,
})
@ -460,6 +470,8 @@ var supportedFuncs = map[string]bool{
"spread": true,
"stddev": true,
"percentile": true,
"top": true,
"bottom": true,
}
// shortDur converts duration into the queryConfig duration format

View File

@ -24,20 +24,20 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
chronograf.Field{
Name: "usage_guest_nice",
Type: "field",
Value: "usage_guest_nice",
Type: "field",
},
chronograf.Field{
Name: "usage_system",
Type: "field",
Value: "usage_system",
Type: "field",
},
chronograf.Field{
Name: "usage_guest",
Type: "field",
Value: "usage_guest",
Type: "field",
},
},
Tags: map[string][]string{},
@ -55,42 +55,42 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
},
},
chronograf.Field{
Name: "median",
Type: "func",
Value: "median",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
},
},
chronograf.Field{
Name: "count",
Type: "func",
Value: "count",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_guest_nice",
Type: "field",
Value: "usage_guest_nice",
Type: "field",
},
},
},
chronograf.Field{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_guest_nice",
Type: "field",
Value: "usage_guest_nice",
Type: "field",
},
},
},
@ -134,8 +134,8 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{"host": []string{"myhost"}},
@ -170,8 +170,8 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{"host": []string{"myhost"}},
@ -195,8 +195,8 @@ func TestConvert(t *testing.T) {
Tags: map[string][]string{},
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
GroupBy: chronograf.GroupBy{
@ -242,8 +242,8 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{},
@ -262,8 +262,8 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{"host": []string{"myhost"}},
@ -287,8 +287,8 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{
@ -331,8 +331,8 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{
@ -358,20 +358,20 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
chronograf.Field{
Name: "usage_guest_nice",
Type: "field",
Value: "usage_guest_nice",
Type: "field",
},
chronograf.Field{
Name: "usage_system",
Type: "field",
Value: "usage_system",
Type: "field",
},
chronograf.Field{
Name: "usage_guest",
Type: "field",
Value: "usage_guest",
Type: "field",
},
},
Tags: map[string][]string{
@ -405,20 +405,20 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
chronograf.Field{
Name: "usage_guest_nice",
Type: "field",
Value: "usage_guest_nice",
Type: "field",
},
chronograf.Field{
Name: "usage_system",
Type: "field",
Value: "usage_system",
Type: "field",
},
chronograf.Field{
Name: "usage_guest",
Type: "field",
Value: "usage_guest",
Type: "field",
},
},
Tags: map[string][]string{
@ -452,12 +452,12 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
},
},
@ -483,12 +483,12 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
},
},
@ -507,19 +507,20 @@ func TestConvert(t *testing.T) {
},
{
name: "Test implicit null fill accepted and made explicit",
influxQL: `SELECT mean("usage_idle") FROM "telegraf"."autogen"."cpu" WHERE time > now() - 15m GROUP BY time(1m)`,
influxQL: `SELECT mean("usage_idle") as "mean_usage_idle" FROM "telegraf"."autogen"."cpu" WHERE time > now() - 15m GROUP BY time(1m)`,
want: chronograf.QueryConfig{
Database: "telegraf",
Measurement: "cpu",
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Alias: "mean_usage_idle",
Args: []chronograf.Field{
{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
},
},
@ -536,6 +537,122 @@ func TestConvert(t *testing.T) {
},
},
},
{
name: "Test percentile with a number parameter",
influxQL: `SELECT percentile("usage_idle", 3.14) as "mean_usage_idle" FROM "telegraf"."autogen"."cpu" WHERE time > now() - 15m GROUP BY time(1m)`,
want: chronograf.QueryConfig{
Database: "telegraf",
Measurement: "cpu",
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Value: "percentile",
Type: "func",
Alias: "mean_usage_idle",
Args: []chronograf.Field{
{
Value: "usage_idle",
Type: "field",
},
chronograf.Field{
Value: 3.14,
Type: "number",
},
},
},
},
GroupBy: chronograf.GroupBy{
Time: "1m",
Tags: []string{},
},
Tags: map[string][]string{},
AreTagsAccepted: false,
Fill: "null",
Range: &chronograf.DurationRange{
Lower: "now() - 15m",
},
},
},
{
name: "Test top with 2 arguments",
influxQL: `SELECT TOP("water_level","location",2) FROM "h2o_feet"`,
want: chronograf.QueryConfig{
Measurement: "h2o_feet",
Fields: []chronograf.Field{
chronograf.Field{
Value: "top",
Type: "func",
Args: []chronograf.Field{
{
Value: "water_level",
Type: "field",
},
chronograf.Field{
Value: "location",
Type: "field",
},
chronograf.Field{
Value: int64(2),
Type: "integer",
},
},
},
},
GroupBy: chronograf.GroupBy{
Tags: []string{},
},
Tags: map[string][]string{},
AreTagsAccepted: false,
},
},
{
name: "count of a regex",
influxQL: ` SELECT COUNT(/water/) FROM "h2o_feet"`,
want: chronograf.QueryConfig{
Measurement: "h2o_feet",
Fields: []chronograf.Field{
chronograf.Field{
Value: "count",
Type: "func",
Args: []chronograf.Field{
{
Value: "water",
Type: "regex",
},
},
},
},
GroupBy: chronograf.GroupBy{
Tags: []string{},
},
Tags: map[string][]string{},
AreTagsAccepted: false,
},
},
{
name: "count of a wildcard",
influxQL: ` SELECT COUNT(*) FROM "h2o_feet"`,
want: chronograf.QueryConfig{
Measurement: "h2o_feet",
Fields: []chronograf.Field{
chronograf.Field{
Value: "count",
Type: "func",
Args: []chronograf.Field{
{
Value: "*",
Type: "wildcard",
},
},
},
},
GroupBy: chronograf.GroupBy{
Tags: []string{},
},
Tags: map[string][]string{},
AreTagsAccepted: false,
},
},
{
name: "Test fill number (int) accepted",
influxQL: `SELECT mean("usage_idle") FROM "telegraf"."autogen"."cpu" WHERE time > now() - 15m GROUP BY time(1m) FILL(1337)`,
@ -545,12 +662,12 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
},
},
@ -576,12 +693,12 @@ func TestConvert(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
chronograf.Field{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_idle",
Type: "field",
Value: "usage_idle",
Type: "field",
},
},
},

View File

@ -425,12 +425,12 @@ func Reverse(script chronograf.TICKScript) (chronograf.AlertRule, error) {
if fieldFunc.Func != "" {
rule.Query.Fields = []chronograf.Field{
{
Type: "func",
Name: fieldFunc.Func,
Type: "func",
Value: fieldFunc.Func,
Args: []chronograf.Field{
{
Name: fieldFunc.Field,
Type: "field",
Value: fieldFunc.Field,
Type: "field",
},
},
},
@ -438,8 +438,8 @@ func Reverse(script chronograf.TICKScript) (chronograf.AlertRule, error) {
} else {
rule.Query.Fields = []chronograf.Field{
{
Type: "field",
Name: fieldFunc.Field,
Type: "field",
Value: fieldFunc.Field,
},
}
}

View File

@ -113,11 +113,11 @@ func TestReverse(t *testing.T) {
Measurement: "cpu",
Fields: []chronograf.Field{
{
Name: "mean",
Value: "mean",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Type: "func",
@ -226,11 +226,11 @@ func TestReverse(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Value: "mean",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Type: "func",
@ -371,11 +371,11 @@ func TestReverse(t *testing.T) {
Measurement: "haproxy",
Fields: []chronograf.Field{
{
Name: "last",
Value: "last",
Args: []chronograf.Field{
{
Name: "status",
Type: "field",
Value: "status",
Type: "field",
},
},
Type: "func",
@ -492,11 +492,11 @@ func TestReverse(t *testing.T) {
Measurement: "haproxy",
Fields: []chronograf.Field{
{
Name: "last",
Value: "last",
Args: []chronograf.Field{
{
Name: "status",
Type: "field",
Value: "status",
Type: "field",
},
},
Type: "func",
@ -615,11 +615,11 @@ func TestReverse(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Value: "mean",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Type: "func",
@ -746,11 +746,11 @@ func TestReverse(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Value: "mean",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Type: "func",
@ -877,11 +877,11 @@ func TestReverse(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Value: "mean",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Type: "func",
@ -996,8 +996,8 @@ func TestReverse(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{
@ -1131,11 +1131,11 @@ trigger
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Value: "mean",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Type: "func",
@ -1273,11 +1273,11 @@ trigger
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Value: "mean",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Type: "func",
@ -1494,8 +1494,8 @@ trigger
Measurement: "cq",
Fields: []chronograf.Field{
{
Name: "queryOk",
Type: "field",
Value: "queryOk",
Type: "field",
},
},
GroupBy: chronograf.GroupBy{

View File

@ -322,8 +322,8 @@ trigger
Measurement: "cq",
Fields: []chronograf.Field{
{
Name: "queryOk",
Type: "field",
Value: "queryOk",
Type: "field",
},
},
GroupBy: chronograf.GroupBy{
@ -645,8 +645,8 @@ trigger
Measurement: "cq",
Fields: []chronograf.Field{
{
Name: "queryOk",
Type: "field",
Value: "queryOk",
Type: "field",
},
},
GroupBy: chronograf.GroupBy{

View File

@ -44,14 +44,14 @@ func Data(rule chronograf.AlertRule) (string, error) {
if field.Type == "func" && len(field.Args) > 0 && field.Args[0].Type == "field" {
// Only need a window if we have an aggregate function
value = value + "|window().period(period).every(every).align()\n"
value = value + fmt.Sprintf(`|%s('%s').as('value')`, field.Name, field.Args[0].Name)
value = value + fmt.Sprintf(`|%s('%s').as('value')`, field.Value, field.Args[0].Value)
break // only support a single field
}
if value != "" {
break // only support a single field
}
if field.Type == "field" {
value = fmt.Sprintf(`|eval(lambda: "%s").as('value')`, field.Name)
value = fmt.Sprintf(`|eval(lambda: "%s").as('value')`, field.Value)
}
}
if value == "" {

View File

@ -31,12 +31,12 @@ func TestInfluxOut(t *testing.T) {
Query: &chronograf.QueryConfig{
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},

View File

@ -27,12 +27,12 @@ func TestGenerate(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},
@ -78,12 +78,12 @@ func TestThreshold(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},
@ -228,12 +228,12 @@ func TestThresholdStringCrit(t *testing.T) {
Measurement: "haproxy",
Fields: []chronograf.Field{
{
Name: "last",
Type: "func",
Value: "last",
Type: "func",
Args: []chronograf.Field{
{
Name: "status",
Type: "field",
Value: "status",
Type: "field",
},
},
},
@ -372,12 +372,12 @@ func TestThresholdStringCritGreater(t *testing.T) {
Measurement: "haproxy",
Fields: []chronograf.Field{
{
Name: "last",
Type: "func",
Value: "last",
Type: "func",
Args: []chronograf.Field{
{
Name: "status",
Type: "field",
Value: "status",
Type: "field",
},
},
},
@ -514,12 +514,12 @@ func TestThresholdDetail(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},
@ -667,12 +667,12 @@ func TestThresholdInsideRange(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},
@ -819,12 +819,12 @@ func TestThresholdOutsideRange(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},
@ -970,8 +970,8 @@ func TestThresholdNoAggregate(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
Tags: map[string][]string{
@ -1107,12 +1107,12 @@ func TestRelative(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},
@ -1270,12 +1270,12 @@ func TestRelativeChange(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},
@ -1430,12 +1430,12 @@ func TestDeadman(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "mean",
Type: "func",
Value: "mean",
Type: "func",
Args: []chronograf.Field{
{
Name: "usage_user",
Type: "field",
Value: "usage_user",
Type: "field",
},
},
},

View File

@ -156,12 +156,12 @@ func field(q *chronograf.QueryConfig) (string, error) {
if field.Type == "func" && len(field.Args) > 0 {
for _, arg := range field.Args {
if arg.Type == "field" {
return arg.Name.(string), nil
return arg.Value.(string), nil
}
}
return "", fmt.Errorf("No fields set in query")
}
return field.Name.(string), nil
return field.Value.(string), nil
}
}
return "", fmt.Errorf("No fields set in query")

View File

@ -22,8 +22,8 @@ func TestVarsCritStringEqual(t *testing.T) {
RetentionPolicy: "autogen",
Fields: []chronograf.Field{
{
Name: "status",
Type: "field",
Value: "status",
Type: "field",
},
},
GroupBy: chronograf.GroupBy{

View File

@ -311,8 +311,8 @@ func Test_newDashboardResponse(t *testing.T) {
Measurement: "grays_sports_alamanc",
Fields: []chronograf.Field{
{
Type: "field",
Name: "winning_horses",
Type: "field",
Value: "winning_horses",
},
},
GroupBy: chronograf.GroupBy{

View File

@ -37,12 +37,12 @@ func TestValidRuleRequest(t *testing.T) {
Query: &chronograf.QueryConfig{
Fields: []chronograf.Field{
{
Name: "max",
Type: "func",
Value: "max",
Type: "func",
Args: []chronograf.Field{
{
Name: "oldmanpeabody",
Type: "field",
Value: "oldmanpeabody",
Type: "field",
},
},
},
@ -58,12 +58,12 @@ func TestValidRuleRequest(t *testing.T) {
Query: &chronograf.QueryConfig{
Fields: []chronograf.Field{
{
Name: "max",
Type: "func",
Value: "max",
Type: "func",
Args: []chronograf.Field{
{
Name: "oldmanpeabody",
Type: "field",
Value: "oldmanpeabody",
Type: "field",
},
},
},