[promtool] Support writing output as json (#4848)

* Support writing output as json

Oftentimes I'll want to execute something based on
the output from promtool, and supporting json
makes it easy to pull out values with a supporting
tool such as jq.

Signed-off-by: stuart nelson <stuartnelson3@gmail.com>
This commit is contained in:
stuart nelson 2018-11-14 18:40:07 +01:00 committed by GitHub
parent b82f930238
commit 6a69471bc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 19 deletions

View file

@ -15,6 +15,7 @@ package main
import (
"context"
"encoding/json"
"fmt"
"math"
"net/url"
@ -29,6 +30,7 @@ import (
"github.com/prometheus/client_golang/api"
"github.com/prometheus/client_golang/api/prometheus/v1"
config_util "github.com/prometheus/common/config"
"github.com/prometheus/common/model"
"github.com/prometheus/common/version"
"github.com/prometheus/prometheus/config"
"github.com/prometheus/prometheus/pkg/rulefmt"
@ -57,6 +59,7 @@ func main() {
checkMetricsCmd := checkCmd.Command("metrics", checkMetricsUsage)
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()
@ -93,7 +96,17 @@ func main() {
"The unit test file.",
).Required().ExistingFiles()
switch kingpin.MustParse(app.Parse(os.Args[1:])) {
parsedCmd := kingpin.MustParse(app.Parse(os.Args[1:]))
var p printer
switch *queryCmdFmt {
case "json":
p = &jsonPrinter{}
case "promql":
p = &promqlPrinter{}
}
switch parsedCmd {
case checkConfigCmd.FullCommand():
os.Exit(CheckConfig(*configFiles...))
@ -104,13 +117,13 @@ func main() {
os.Exit(CheckMetrics())
case queryInstantCmd.FullCommand():
os.Exit(QueryInstant(*queryServer, *queryExpr))
os.Exit(QueryInstant(*queryServer, *queryExpr, p))
case queryRangeCmd.FullCommand():
os.Exit(QueryRange(*queryRangeServer, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep))
os.Exit(QueryRange(*queryRangeServer, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep, p))
case querySeriesCmd.FullCommand():
os.Exit(QuerySeries(*querySeriesServer, *querySeriesMatch, *querySeriesBegin, *querySeriesEnd))
os.Exit(QuerySeries(*querySeriesServer, *querySeriesMatch, *querySeriesBegin, *querySeriesEnd, p))
case debugPprofCmd.FullCommand():
os.Exit(debugPprof(*debugPprofServer))
@ -122,7 +135,7 @@ func main() {
os.Exit(debugAll(*debugAllServer))
case queryLabelsCmd.FullCommand():
os.Exit(QueryLabels(*queryLabelsServer, *queryLabelsName))
os.Exit(QueryLabels(*queryLabelsServer, *queryLabelsName, p))
case testRulesCmd.FullCommand():
os.Exit(RulesUnitTest(*testRulesFiles...))
@ -316,7 +329,7 @@ func CheckMetrics() int {
}
// QueryInstant performs an instant query against a Prometheus server.
func QueryInstant(url string, query string) int {
func QueryInstant(url, query string, p printer) int {
config := api.Config{
Address: url,
}
@ -339,13 +352,13 @@ func QueryInstant(url string, query string) int {
return 1
}
fmt.Println(val.String())
p.printValue(val)
return 0
}
// QueryRange performs a range query against a Prometheus server.
func QueryRange(url, query, start, end string, step time.Duration) int {
func QueryRange(url, query, start, end string, step time.Duration, p printer) int {
config := api.Config{
Address: url,
}
@ -400,12 +413,12 @@ func QueryRange(url, query, start, end string, step time.Duration) int {
return 1
}
fmt.Println(val.String())
p.printValue(val)
return 0
}
// QuerySeries queries for a series against a Prometheus server.
func QuerySeries(url *url.URL, matchers []string, start string, end string) int {
func QuerySeries(url *url.URL, matchers []string, start, end string, p printer) int {
config := api.Config{
Address: url.String(),
}
@ -454,14 +467,12 @@ func QuerySeries(url *url.URL, matchers []string, start string, end string) int
return 1
}
for _, v := range val {
fmt.Println(v)
}
p.printSeries(val)
return 0
}
// QueryLabels queries for label values against a Prometheus server.
func QueryLabels(url *url.URL, name string) int {
func QueryLabels(url *url.URL, name string, p printer) int {
config := api.Config{
Address: url.String(),
}
@ -484,9 +495,7 @@ func QueryLabels(url *url.URL, name string) int {
return 1
}
for _, v := range val {
fmt.Println(v)
}
p.printLabelValues(val)
return 0
}
@ -557,3 +566,37 @@ func debugAll(url string) int {
}
return w.Write()
}
type printer interface {
printValue(v model.Value)
printSeries(v []model.LabelSet)
printLabelValues(v model.LabelValues)
}
type promqlPrinter struct{}
func (p *promqlPrinter) printValue(v model.Value) {
fmt.Println(v)
}
func (p *promqlPrinter) printSeries(val []model.LabelSet) {
for _, v := range val {
fmt.Println(v)
}
}
func (j *promqlPrinter) printLabelValues(val model.LabelValues) {
for _, v := range val {
fmt.Println(v)
}
}
type jsonPrinter struct{}
func (j *jsonPrinter) printValue(v model.Value) {
json.NewEncoder(os.Stdout).Encode(v)
}
func (j *jsonPrinter) printSeries(v []model.LabelSet) {
json.NewEncoder(os.Stdout).Encode(v)
}
func (j *jsonPrinter) printLabelValues(v model.LabelValues) {
json.NewEncoder(os.Stdout).Encode(v)
}

View file

@ -26,7 +26,8 @@ func TestQueryRange(t *testing.T) {
s, getURL := mockServer(200, `{"status": "success", "data": {"resultType": "matrix", "result": []}}`)
defer s.Close()
exitCode := QueryRange(s.URL, "up", "0", "300", 0)
p := &promqlPrinter{}
exitCode := QueryRange(s.URL, "up", "0", "300", 0, p)
expectedPath := "/api/v1/query_range"
if getURL().Path != expectedPath {
t.Errorf("unexpected URL path %s (wanted %s)", getURL().Path, expectedPath)
@ -43,7 +44,7 @@ func TestQueryRange(t *testing.T) {
t.Error()
}
exitCode = QueryRange(s.URL, "up", "0", "300", 10*time.Millisecond)
exitCode = QueryRange(s.URL, "up", "0", "300", 10*time.Millisecond, p)
if getURL().Path != expectedPath {
t.Errorf("unexpected URL path %s (wanted %s)", getURL().Path, expectedPath)
}