Fix :dashboardTime: by introducing tvar precedence
In order for :autoGroupBy: and :dashboardTime: to co-exist in a query, it's necessary to introduce template variable precedence to the backend. This is done by adding a `Precedence()` method to the TemplateVariable interface that returns an ordinal indicating the precedence level of the template variable. Precedence starts from 0 (highest) proceeding to the maximum that a `uint` can represent. A template variable at a given precedence level can expect that all template variables with higher precedence will have already been replaced in the query that is passed to its `Exec` call. For example, :autoGroupBy: has lower precedence than :dashboardTime: because it needs to know the selected time range for the query. When the `Exec` method of `GroupByVar` is invoked, it will see the query after :dashboardTime: has already been replaced, allowing it to extract the duration successfully.pull/4934/head
parent
4f37949427
commit
4d22f83da5
|
@ -135,6 +135,7 @@ type Range struct {
|
|||
type TemplateVariable interface {
|
||||
fmt.Stringer
|
||||
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
|
||||
|
||||
|
|
|
@ -8,11 +8,23 @@ import (
|
|||
|
||||
// TemplateReplace replaces templates with values within the query string
|
||||
func TemplateReplace(query string, templates chronograf.TemplateVars) string {
|
||||
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 templates {
|
||||
for _, v := range tvarsByPrecedence[prc] {
|
||||
if evar, ok := v.(chronograf.ExecutableVar); ok {
|
||||
evar.Exec(query)
|
||||
evar.Exec(replaced)
|
||||
}
|
||||
newVal := v.String()
|
||||
if newVal != "" {
|
||||
|
@ -21,6 +33,8 @@ func TemplateReplace(query string, templates chronograf.TemplateVars) string {
|
|||
}
|
||||
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
replaced := replacer.Replace(query)
|
||||
replaced = replacer.Replace(replaced)
|
||||
}
|
||||
|
||||
return replaced
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue