From 442b3364d785df8713693b206c838c3508b09eba Mon Sep 17 00:00:00 2001 From: Julien Pivotto Date: Tue, 25 Aug 2020 12:32:25 +0200 Subject: [PATCH] Promtool: add evaluation time to instant query (#7829) * Promtool: add evaluation time to instant query Signed-off-by: Julien Pivotto * Apply suggestion Signed-off-by: Julien Pivotto --- cmd/promtool/main.go | 21 +++++++++++---- cmd/promtool/main_test.go | 54 +++++++++++++++++---------------------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/cmd/promtool/main.go b/cmd/promtool/main.go index 5c2029042..2d2c98fbb 100644 --- a/cmd/promtool/main.go +++ b/cmd/promtool/main.go @@ -70,9 +70,11 @@ func main() { queryCmd := app.Command("query", "Run query against a Prometheus server.") queryCmdFmt := queryCmd.Flag("format", "Output format of the query.").Short('o').Default("promql").Enum("promql", "json") + queryInstantCmd := queryCmd.Command("instant", "Run instant query.") - queryServer := queryInstantCmd.Arg("server", "Prometheus server to query.").Required().String() - queryExpr := queryInstantCmd.Arg("expr", "PromQL query expression.").Required().String() + queryInstantServer := queryInstantCmd.Arg("server", "Prometheus server to query.").Required().String() + queryInstantExpr := queryInstantCmd.Arg("expr", "PromQL query expression.").Required().String() + queryInstantTime := queryInstantCmd.Flag("time", "Query evaluation time (RFC3339 or Unix timestamp).").String() queryRangeCmd := queryCmd.Command("range", "Run range query.") queryRangeServer := queryRangeCmd.Arg("server", "Prometheus server to query.").Required().String() @@ -153,7 +155,7 @@ func main() { os.Exit(CheckMetrics()) case queryInstantCmd.FullCommand(): - os.Exit(QueryInstant(*queryServer, *queryExpr, p)) + os.Exit(QueryInstant(*queryInstantServer, *queryInstantExpr, *queryInstantTime, p)) case queryRangeCmd.FullCommand(): os.Exit(QueryRange(*queryRangeServer, *queryRangeHeaders, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep, p)) @@ -427,7 +429,7 @@ func CheckMetrics() int { } // QueryInstant performs an instant query against a Prometheus server. -func QueryInstant(url, query string, p printer) int { +func QueryInstant(url, query, evalTime string, p printer) int { config := api.Config{ Address: url, } @@ -439,11 +441,20 @@ func QueryInstant(url, query string, p printer) int { return 1 } + eTime := time.Now() + if evalTime != "" { + eTime, err = parseTime(evalTime) + if err != nil { + fmt.Fprintln(os.Stderr, "error parsing evaluation time:", err) + return 1 + } + } + // Run query against client. api := v1.NewAPI(c) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - val, _, err := api.Query(ctx, query, time.Now()) // Ignoring warnings for now. + val, _, err := api.Query(ctx, query, eTime) // Ignoring warnings for now. cancel() if err != nil { fmt.Fprintln(os.Stderr, "query error:", err) diff --git a/cmd/promtool/main_test.go b/cmd/promtool/main_test.go index 1d28cf292..a40ff0a86 100644 --- a/cmd/promtool/main_test.go +++ b/cmd/promtool/main_test.go @@ -19,6 +19,8 @@ import ( "net/http/httptest" "testing" "time" + + "github.com/prometheus/prometheus/util/testutil" ) func TestQueryRange(t *testing.T) { @@ -27,41 +29,31 @@ func TestQueryRange(t *testing.T) { p := &promqlPrinter{} exitCode := QueryRange(s.URL, map[string]string{}, "up", "0", "300", 0, p) - expectedPath := "/api/v1/query_range" - gotPath := getRequest().URL.Path - if gotPath != expectedPath { - t.Errorf("unexpected URL path %s (wanted %s)", gotPath, expectedPath) - } + testutil.Equals(t, "/api/v1/query_range", getRequest().URL.Path) form := getRequest().Form - actual := form.Get("query") - if actual != "up" { - t.Errorf("unexpected value %s for query", actual) - } - actual = form.Get("step") - if actual != "1" { - t.Errorf("unexpected value %s for step", actual) - } - if exitCode > 0 { - t.Error() - } + testutil.Equals(t, "up", form.Get("query")) + testutil.Equals(t, "1", form.Get("step")) + testutil.Equals(t, 0, exitCode) exitCode = QueryRange(s.URL, map[string]string{}, "up", "0", "300", 10*time.Millisecond, p) - gotPath = getRequest().URL.Path - if gotPath != expectedPath { - t.Errorf("unexpected URL path %s (wanted %s)", gotPath, expectedPath) - } + testutil.Equals(t, "/api/v1/query_range", getRequest().URL.Path) form = getRequest().Form - actual = form.Get("query") - if actual != "up" { - t.Errorf("unexpected value %s for query", actual) - } - actual = form.Get("step") - if actual != "0.01" { - t.Errorf("unexpected value %s for step", actual) - } - if exitCode > 0 { - t.Error() - } + testutil.Equals(t, "up", form.Get("query")) + testutil.Equals(t, "0.01", form.Get("step")) + testutil.Equals(t, 0, exitCode) +} + +func TestQueryInstant(t *testing.T) { + s, getRequest := mockServer(200, `{"status": "success", "data": {"resultType": "vector", "result": []}}`) + defer s.Close() + + p := &promqlPrinter{} + exitCode := QueryInstant(s.URL, "up", "300", p) + testutil.Equals(t, "/api/v1/query", getRequest().URL.Path) + form := getRequest().Form + testutil.Equals(t, "up", form.Get("query")) + testutil.Equals(t, "300", form.Get("time")) + testutil.Equals(t, 0, exitCode) } func mockServer(code int, body string) (*httptest.Server, func() *http.Request) {