From 49d7998d082a4cc9f52c49a905b729efe1d2ff00 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Tue, 26 Jun 2018 13:10:38 -0700 Subject: [PATCH] Return query duration from /query endpoint --- influx/templates.go | 1 + influx/templates_test.go | 6 ++++++ server/queries.go | 10 ++++++++++ server/queries_test.go | 6 +++--- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/influx/templates.go b/influx/templates.go index 86168f772..3bdefb503 100644 --- a/influx/templates.go +++ b/influx/templates.go @@ -11,6 +11,7 @@ import ( ) // SortTemplates the templates by size, then type, then value. +// :interval: needs to be the last template replacement func SortTemplates(ts []chronograf.TemplateVar) []chronograf.TemplateVar { sort.Slice(ts, func(i, j int) bool { if ts[i].Var == ":interval:" { diff --git a/influx/templates_test.go b/influx/templates_test.go index 3da6ef421..c92c7c74c 100644 --- a/influx/templates_test.go +++ b/influx/templates_test.go @@ -448,6 +448,12 @@ func Test_RenderTemplate(t *testing.T) { resolution: 333, want: "SELECT mean(usage_idle) FROM cpu WHERE time > '2017-07-24T15:33:42.994Z' and time < '2017-07-24T15:33:42.994Z' GROUP BY time(1ms)", }, + { + name: "subqueries render :interval:", + query: `SELECT last(sum) FROM (SELECT sum(rate) FROM (SELECT non_negative_derivative(max("counter"),1s) AS "rate" FROM "kube-infra"."monthly"."http_api_requests_total" WHERE path != '/metrics' and time > now() - 1d GROUP BY time(:interval:),* FILL(null)) GROUP BY time(:interval:))`, + resolution: 333, + want: `SELECT last(sum) FROM (SELECT sum(rate) FROM (SELECT non_negative_derivative(max("counter"),1s) AS "rate" FROM "kube-infra"."monthly"."http_api_requests_total" WHERE path != '/metrics' and time > now() - 1d GROUP BY time(25909s),* FILL(null)) GROUP BY time(259s))`, + }, { name: "query should be returned if there are no template variables", query: "SHOW DATABASES", diff --git a/server/queries.go b/server/queries.go index c48d5ef49..936333e77 100644 --- a/server/queries.go +++ b/server/queries.go @@ -29,6 +29,7 @@ type QueriesRequest struct { // QueryResponse is the return result of a QueryRequest including // the raw query, the templated query, the queryConfig and the queryAST type QueryResponse struct { + Duration int64 `json:"durationMs"` ID string `json:"id"` Query string `json:"query"` QueryConfig chronograf.QueryConfig `json:"queryConfig"` @@ -90,6 +91,15 @@ func (s *Service) Queries(w http.ResponseWriter, r *http.Request) { qr.QueryAST = stmt } + if dur, err := influx.ParseTime(query, time.Now()); err == nil { + ms := dur.Nanoseconds() / int64(time.Millisecond) + if ms == 0 { + ms = 1 + } + + qr.Duration = ms + } + if len(req.TemplateVars) > 0 { qr.TemplateVars = req.TemplateVars qr.QueryConfig.RawText = &qr.Query diff --git a/server/queries_test.go b/server/queries_test.go index 754220403..86aa4358a 100644 --- a/server/queries_test.go +++ b/server/queries_test.go @@ -60,7 +60,7 @@ func TestService_Queries(t *testing.T) { "id": "82b60d37-251e-4afe-ac93-ca20a3642b11" } ]}`))), - want: `{"queries":[{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","query":"SELECT \"pingReq\" FROM db.\"monitor\".\"httpd\" WHERE time \u003e now() - 1m","queryConfig":{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","database":"db","measurement":"httpd","retentionPolicy":"monitor","fields":[{"value":"pingReq","type":"field","alias":""}],"tags":{},"groupBy":{"time":"","tags":[]},"areTagsAccepted":false,"rawText":null,"range":{"upper":"","lower":"now() - 1m"},"shifts":[]},"queryAST":{"condition":{"expr":"binary","op":"\u003e","lhs":{"expr":"reference","val":"time"},"rhs":{"expr":"binary","op":"-","lhs":{"expr":"call","name":"now"},"rhs":{"expr":"literal","val":"1m","type":"duration"}}},"fields":[{"column":{"expr":"reference","val":"pingReq"}}],"sources":[{"database":"db","retentionPolicy":"monitor","name":"httpd","type":"measurement"}]}}]} + want: `{"queries":[{"durationMs":59999,"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","query":"SELECT \"pingReq\" FROM db.\"monitor\".\"httpd\" WHERE time \u003e now() - 1m","queryConfig":{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","database":"db","measurement":"httpd","retentionPolicy":"monitor","fields":[{"value":"pingReq","type":"field","alias":""}],"tags":{},"groupBy":{"time":"","tags":[]},"areTagsAccepted":false,"rawText":null,"range":{"upper":"","lower":"now() - 1m"},"shifts":[]},"queryAST":{"condition":{"expr":"binary","op":"\u003e","lhs":{"expr":"reference","val":"time"},"rhs":{"expr":"binary","op":"-","lhs":{"expr":"call","name":"now"},"rhs":{"expr":"literal","val":"1m","type":"duration"}}},"fields":[{"column":{"expr":"reference","val":"pingReq"}}],"sources":[{"database":"db","retentionPolicy":"monitor","name":"httpd","type":"measurement"}]}}]} `, }, { @@ -81,7 +81,7 @@ func TestService_Queries(t *testing.T) { "id": "82b60d37-251e-4afe-ac93-ca20a3642b11" } ]}`))), - want: `{"queries":[{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","query":"SHOW DATABASES","queryConfig":{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","database":"","measurement":"","retentionPolicy":"","fields":[],"tags":{},"groupBy":{"time":"","tags":[]},"areTagsAccepted":false,"rawText":"SHOW DATABASES","range":null,"shifts":[]}}]} + want: `{"queries":[{"durationMs":0,"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","query":"SHOW DATABASES","queryConfig":{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","database":"","measurement":"","retentionPolicy":"","fields":[],"tags":{},"groupBy":{"time":"","tags":[]},"areTagsAccepted":false,"rawText":"SHOW DATABASES","range":null,"shifts":[]}}]} `, }, { @@ -162,7 +162,7 @@ func TestService_Queries(t *testing.T) { } ] }`))), - want: `{"queries":[{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","query":"SELECT \"pingReq\" FROM :dbs:.\"monitor\".\"httpd\" WHERE time \u003e :dashboardTime: AND time \u003c :upperDashboardTime: GROUP BY time(:interval:)","queryConfig":{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","database":"","measurement":"","retentionPolicy":"","fields":[],"tags":{},"groupBy":{"time":"","tags":[]},"areTagsAccepted":false,"rawText":"SELECT \"pingReq\" FROM :dbs:.\"monitor\".\"httpd\" WHERE time \u003e :dashboardTime: AND time \u003c :upperDashboardTime: GROUP BY time(:interval:)","range":null,"shifts":[]},"queryTemplated":"SELECT \"pingReq\" FROM \"_internal\".\"monitor\".\"httpd\" WHERE time \u003e now() - 15m AND time \u003c now() GROUP BY time(2s)","tempVars":[{"tempVar":":upperDashboardTime:","values":[{"value":"now()","type":"constant","selected":true}]},{"tempVar":":dashboardTime:","values":[{"value":"now() - 15m","type":"constant","selected":true}]},{"tempVar":":dbs:","values":[{"value":"_internal","type":"database","selected":true}]},{"tempVar":":interval:","values":[{"value":"333","type":"points","selected":false}]}]}]} + want: `{"queries":[{"durationMs":899999,"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","query":"SELECT \"pingReq\" FROM :dbs:.\"monitor\".\"httpd\" WHERE time \u003e :dashboardTime: AND time \u003c :upperDashboardTime: GROUP BY time(:interval:)","queryConfig":{"id":"82b60d37-251e-4afe-ac93-ca20a3642b11","database":"","measurement":"","retentionPolicy":"","fields":[],"tags":{},"groupBy":{"time":"","tags":[]},"areTagsAccepted":false,"rawText":"SELECT \"pingReq\" FROM :dbs:.\"monitor\".\"httpd\" WHERE time \u003e :dashboardTime: AND time \u003c :upperDashboardTime: GROUP BY time(:interval:)","range":null,"shifts":[]},"queryTemplated":"SELECT \"pingReq\" FROM \"_internal\".\"monitor\".\"httpd\" WHERE time \u003e now() - 15m AND time \u003c now() GROUP BY time(2s)","tempVars":[{"tempVar":":upperDashboardTime:","values":[{"value":"now()","type":"constant","selected":true}]},{"tempVar":":dashboardTime:","values":[{"value":"now() - 15m","type":"constant","selected":true}]},{"tempVar":":dbs:","values":[{"value":"_internal","type":"database","selected":true}]},{"tempVar":":interval:","values":[{"value":"333","type":"points","selected":false}]}]}]} `, }, }