diff --git a/chronograf.go b/chronograf.go index 70f92b03fa..e5e4511fb4 100644 --- a/chronograf.go +++ b/chronograf.go @@ -134,7 +134,8 @@ type Range struct { type TemplateVariable interface { fmt.Stringer - Name() string // returns the variable name + Name() string // returns the variable name + Precedence() uint // ordinal indicating precedence level for replacement } type ExecutableVar interface { @@ -178,6 +179,10 @@ func (t BasicTemplateVar) String() string { } } +func (t BasicTemplateVar) Precedence() uint { + return 0 +} + type GroupByVar struct { Var string `json:"tempVar"` // the name of the variable as present in the query Duration time.Duration `json:"duration,omitempty"` // the Duration supplied by the query @@ -231,6 +236,10 @@ func (g *GroupByVar) Name() string { return g.Var } +func (g *GroupByVar) Precedence() uint { + return 1 +} + // TemplateID is the unique ID used to identify a template type TemplateID string diff --git a/influx/templates.go b/influx/templates.go index 669aa526a7..c006f7fa1e 100644 --- a/influx/templates.go +++ b/influx/templates.go @@ -8,19 +8,33 @@ import ( // TemplateReplace replaces templates with values within the query string func TemplateReplace(query string, templates chronograf.TemplateVars) string { - replacements := []string{} - - for _, v := range templates { - if evar, ok := v.(chronograf.ExecutableVar); ok { - evar.Exec(query) - } - newVal := v.String() - if newVal != "" { - replacements = append(replacements, v.Name(), newVal) + tvarsByPrecedence := make(map[uint]chronograf.TemplateVars, len(templates)) + maxPrecedence := uint(0) + for _, tmp := range templates { + precedence := tmp.Precedence() + if precedence > maxPrecedence { + maxPrecedence = precedence } + tvarsByPrecedence[precedence] = append(tvarsByPrecedence[precedence], tmp) + } + + replaced := query + for prc := uint(0); prc <= maxPrecedence; prc++ { + replacements := []string{} + + for _, v := range tvarsByPrecedence[prc] { + if evar, ok := v.(chronograf.ExecutableVar); ok { + evar.Exec(replaced) + } + newVal := v.String() + if newVal != "" { + replacements = append(replacements, v.Name(), newVal) + } + } + + replacer := strings.NewReplacer(replacements...) + replaced = replacer.Replace(replaced) } - replacer := strings.NewReplacer(replacements...) - replaced := replacer.Replace(query) return replaced } diff --git a/influx/templates_test.go b/influx/templates_test.go index 44a6a76eea..8d0e7ba0f4 100644 --- a/influx/templates_test.go +++ b/influx/templates_test.go @@ -147,7 +147,29 @@ func TestTemplateReplace(t *testing.T) { ReportingInterval: 10 * time.Second, }, }, - want: `SELECT mean(usage_idle) from "cpu" where time > now() - 4320h group by time(1555s)`, + want: `SELECT mean(usage_idle) from "cpu" WHERE time > now() - 4320h group by time(1555s)`, + }, + { + name: "auto group by with :dashboardTime:", + query: `SELECT mean(usage_idle) from "cpu" WHERE time > :dashboardTime: :autoGroupBy:`, + vars: chronograf.TemplateVars{ + &chronograf.GroupByVar{ + Var: ":autoGroupBy:", + Duration: 0 * time.Minute, + Resolution: 1000, + ReportingInterval: 10 * time.Second, + }, + &chronograf.BasicTemplateVar{ + Var: ":dashboardTime:", + Values: []chronograf.BasicTemplateValue{ + { + Type: "constant", + Value: "now() - 4320h", + }, + }, + }, + }, + want: `SELECT mean(usage_idle) from "cpu" WHERE time > now() - 4320h group by time(1555s)`, }, } for _, tt := range tests { diff --git a/ui/src/dashboards/containers/DashboardPage.js b/ui/src/dashboards/containers/DashboardPage.js index 106550edb9..eea4997986 100644 --- a/ui/src/dashboards/containers/DashboardPage.js +++ b/ui/src/dashboards/containers/DashboardPage.js @@ -268,8 +268,7 @@ class DashboardPage extends Component { } const templatesIncludingDashTime = (dashboard && - dashboard.templates.concat(dashboardTime) && - dashboard.templates.concat(autoGroupBy)) || [] + dashboard.templates.concat(dashboardTime).concat(autoGroupBy)) || [] const {selectedCell, isEditMode, isTemplating} = this.state