mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-12 22:37:27 -08:00
[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:
parent
b82f930238
commit
6a69471bc2
|
@ -15,6 +15,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -29,6 +30,7 @@ import (
|
||||||
"github.com/prometheus/client_golang/api"
|
"github.com/prometheus/client_golang/api"
|
||||||
"github.com/prometheus/client_golang/api/prometheus/v1"
|
"github.com/prometheus/client_golang/api/prometheus/v1"
|
||||||
config_util "github.com/prometheus/common/config"
|
config_util "github.com/prometheus/common/config"
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
"github.com/prometheus/common/version"
|
"github.com/prometheus/common/version"
|
||||||
"github.com/prometheus/prometheus/config"
|
"github.com/prometheus/prometheus/config"
|
||||||
"github.com/prometheus/prometheus/pkg/rulefmt"
|
"github.com/prometheus/prometheus/pkg/rulefmt"
|
||||||
|
@ -57,6 +59,7 @@ func main() {
|
||||||
checkMetricsCmd := checkCmd.Command("metrics", checkMetricsUsage)
|
checkMetricsCmd := checkCmd.Command("metrics", checkMetricsUsage)
|
||||||
|
|
||||||
queryCmd := app.Command("query", "Run query against a Prometheus server.")
|
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.")
|
queryInstantCmd := queryCmd.Command("instant", "Run instant query.")
|
||||||
queryServer := queryInstantCmd.Arg("server", "Prometheus server to query.").Required().String()
|
queryServer := queryInstantCmd.Arg("server", "Prometheus server to query.").Required().String()
|
||||||
queryExpr := queryInstantCmd.Arg("expr", "PromQL query expression.").Required().String()
|
queryExpr := queryInstantCmd.Arg("expr", "PromQL query expression.").Required().String()
|
||||||
|
@ -93,7 +96,17 @@ func main() {
|
||||||
"The unit test file.",
|
"The unit test file.",
|
||||||
).Required().ExistingFiles()
|
).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():
|
case checkConfigCmd.FullCommand():
|
||||||
os.Exit(CheckConfig(*configFiles...))
|
os.Exit(CheckConfig(*configFiles...))
|
||||||
|
|
||||||
|
@ -104,13 +117,13 @@ func main() {
|
||||||
os.Exit(CheckMetrics())
|
os.Exit(CheckMetrics())
|
||||||
|
|
||||||
case queryInstantCmd.FullCommand():
|
case queryInstantCmd.FullCommand():
|
||||||
os.Exit(QueryInstant(*queryServer, *queryExpr))
|
os.Exit(QueryInstant(*queryServer, *queryExpr, p))
|
||||||
|
|
||||||
case queryRangeCmd.FullCommand():
|
case queryRangeCmd.FullCommand():
|
||||||
os.Exit(QueryRange(*queryRangeServer, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep))
|
os.Exit(QueryRange(*queryRangeServer, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep, p))
|
||||||
|
|
||||||
case querySeriesCmd.FullCommand():
|
case querySeriesCmd.FullCommand():
|
||||||
os.Exit(QuerySeries(*querySeriesServer, *querySeriesMatch, *querySeriesBegin, *querySeriesEnd))
|
os.Exit(QuerySeries(*querySeriesServer, *querySeriesMatch, *querySeriesBegin, *querySeriesEnd, p))
|
||||||
|
|
||||||
case debugPprofCmd.FullCommand():
|
case debugPprofCmd.FullCommand():
|
||||||
os.Exit(debugPprof(*debugPprofServer))
|
os.Exit(debugPprof(*debugPprofServer))
|
||||||
|
@ -122,7 +135,7 @@ func main() {
|
||||||
os.Exit(debugAll(*debugAllServer))
|
os.Exit(debugAll(*debugAllServer))
|
||||||
|
|
||||||
case queryLabelsCmd.FullCommand():
|
case queryLabelsCmd.FullCommand():
|
||||||
os.Exit(QueryLabels(*queryLabelsServer, *queryLabelsName))
|
os.Exit(QueryLabels(*queryLabelsServer, *queryLabelsName, p))
|
||||||
|
|
||||||
case testRulesCmd.FullCommand():
|
case testRulesCmd.FullCommand():
|
||||||
os.Exit(RulesUnitTest(*testRulesFiles...))
|
os.Exit(RulesUnitTest(*testRulesFiles...))
|
||||||
|
@ -316,7 +329,7 @@ func CheckMetrics() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryInstant performs an instant query against a Prometheus server.
|
// 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{
|
config := api.Config{
|
||||||
Address: url,
|
Address: url,
|
||||||
}
|
}
|
||||||
|
@ -339,13 +352,13 @@ func QueryInstant(url string, query string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(val.String())
|
p.printValue(val)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryRange performs a range query against a Prometheus server.
|
// 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{
|
config := api.Config{
|
||||||
Address: url,
|
Address: url,
|
||||||
}
|
}
|
||||||
|
@ -400,12 +413,12 @@ func QueryRange(url, query, start, end string, step time.Duration) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(val.String())
|
p.printValue(val)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// QuerySeries queries for a series against a Prometheus server.
|
// 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{
|
config := api.Config{
|
||||||
Address: url.String(),
|
Address: url.String(),
|
||||||
}
|
}
|
||||||
|
@ -454,14 +467,12 @@ func QuerySeries(url *url.URL, matchers []string, start string, end string) int
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range val {
|
p.printSeries(val)
|
||||||
fmt.Println(v)
|
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryLabels queries for label values against a Prometheus server.
|
// 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{
|
config := api.Config{
|
||||||
Address: url.String(),
|
Address: url.String(),
|
||||||
}
|
}
|
||||||
|
@ -484,9 +495,7 @@ func QueryLabels(url *url.URL, name string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range val {
|
p.printLabelValues(val)
|
||||||
fmt.Println(v)
|
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,3 +566,37 @@ func debugAll(url string) int {
|
||||||
}
|
}
|
||||||
return w.Write()
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ func TestQueryRange(t *testing.T) {
|
||||||
s, getURL := mockServer(200, `{"status": "success", "data": {"resultType": "matrix", "result": []}}`)
|
s, getURL := mockServer(200, `{"status": "success", "data": {"resultType": "matrix", "result": []}}`)
|
||||||
defer s.Close()
|
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"
|
expectedPath := "/api/v1/query_range"
|
||||||
if getURL().Path != expectedPath {
|
if getURL().Path != expectedPath {
|
||||||
t.Errorf("unexpected URL path %s (wanted %s)", 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()
|
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 {
|
if getURL().Path != expectedPath {
|
||||||
t.Errorf("unexpected URL path %s (wanted %s)", getURL().Path, expectedPath)
|
t.Errorf("unexpected URL path %s (wanted %s)", getURL().Path, expectedPath)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue