mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-12 14:27:27 -08:00
Merge pull request #11487 from FUSAKLA/fus-promtool-http-config
Promtool: add http config support to query commands
This commit is contained in:
commit
8a8f594b16
|
@ -45,6 +45,7 @@ import (
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
promconfig "github.com/prometheus/common/config"
|
||||||
"github.com/prometheus/common/expfmt"
|
"github.com/prometheus/common/expfmt"
|
||||||
|
|
||||||
"github.com/prometheus/prometheus/config"
|
"github.com/prometheus/prometheus/config"
|
||||||
|
@ -74,6 +75,12 @@ const (
|
||||||
var lintOptions = []string{lintOptionAll, lintOptionDuplicateRules, lintOptionNone}
|
var lintOptions = []string{lintOptionAll, lintOptionDuplicateRules, lintOptionNone}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
var (
|
||||||
|
httpRoundTripper = api.DefaultRoundTripper
|
||||||
|
serverURL *url.URL
|
||||||
|
httpConfigFilePath string
|
||||||
|
)
|
||||||
|
|
||||||
app := kingpin.New(filepath.Base(os.Args[0]), "Tooling for the Prometheus monitoring system.").UsageWriter(os.Stdout)
|
app := kingpin.New(filepath.Base(os.Args[0]), "Tooling for the Prometheus monitoring system.").UsageWriter(os.Stdout)
|
||||||
app.Version(version.Print("promtool"))
|
app.Version(version.Print("promtool"))
|
||||||
app.HelpFlag.Short('h')
|
app.HelpFlag.Short('h')
|
||||||
|
@ -124,14 +131,15 @@ func main() {
|
||||||
|
|
||||||
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")
|
queryCmdFmt := queryCmd.Flag("format", "Output format of the query.").Short('o').Default("promql").Enum("promql", "json")
|
||||||
|
queryCmd.Flag("http.config.file", "HTTP client configuration file for promtool to connect to Prometheus.").PlaceHolder("<filename>").ExistingFileVar(&httpConfigFilePath)
|
||||||
|
|
||||||
queryInstantCmd := queryCmd.Command("instant", "Run instant query.")
|
queryInstantCmd := queryCmd.Command("instant", "Run instant query.")
|
||||||
queryInstantServer := queryInstantCmd.Arg("server", "Prometheus server to query.").Required().URL()
|
queryInstantCmd.Arg("server", "Prometheus server to query.").Required().URLVar(&serverURL)
|
||||||
queryInstantExpr := queryInstantCmd.Arg("expr", "PromQL query expression.").Required().String()
|
queryInstantExpr := queryInstantCmd.Arg("expr", "PromQL query expression.").Required().String()
|
||||||
queryInstantTime := queryInstantCmd.Flag("time", "Query evaluation time (RFC3339 or Unix timestamp).").String()
|
queryInstantTime := queryInstantCmd.Flag("time", "Query evaluation time (RFC3339 or Unix timestamp).").String()
|
||||||
|
|
||||||
queryRangeCmd := queryCmd.Command("range", "Run range query.")
|
queryRangeCmd := queryCmd.Command("range", "Run range query.")
|
||||||
queryRangeServer := queryRangeCmd.Arg("server", "Prometheus server to query.").Required().URL()
|
queryRangeCmd.Arg("server", "Prometheus server to query.").Required().URLVar(&serverURL)
|
||||||
queryRangeExpr := queryRangeCmd.Arg("expr", "PromQL query expression.").Required().String()
|
queryRangeExpr := queryRangeCmd.Arg("expr", "PromQL query expression.").Required().String()
|
||||||
queryRangeHeaders := queryRangeCmd.Flag("header", "Extra headers to send to server.").StringMap()
|
queryRangeHeaders := queryRangeCmd.Flag("header", "Extra headers to send to server.").StringMap()
|
||||||
queryRangeBegin := queryRangeCmd.Flag("start", "Query range start time (RFC3339 or Unix timestamp).").String()
|
queryRangeBegin := queryRangeCmd.Flag("start", "Query range start time (RFC3339 or Unix timestamp).").String()
|
||||||
|
@ -139,7 +147,7 @@ func main() {
|
||||||
queryRangeStep := queryRangeCmd.Flag("step", "Query step size (duration).").Duration()
|
queryRangeStep := queryRangeCmd.Flag("step", "Query step size (duration).").Duration()
|
||||||
|
|
||||||
querySeriesCmd := queryCmd.Command("series", "Run series query.")
|
querySeriesCmd := queryCmd.Command("series", "Run series query.")
|
||||||
querySeriesServer := querySeriesCmd.Arg("server", "Prometheus server to query.").Required().URL()
|
querySeriesCmd.Arg("server", "Prometheus server to query.").Required().URLVar(&serverURL)
|
||||||
querySeriesMatch := querySeriesCmd.Flag("match", "Series selector. Can be specified multiple times.").Required().Strings()
|
querySeriesMatch := querySeriesCmd.Flag("match", "Series selector. Can be specified multiple times.").Required().Strings()
|
||||||
querySeriesBegin := querySeriesCmd.Flag("start", "Start time (RFC3339 or Unix timestamp).").String()
|
querySeriesBegin := querySeriesCmd.Flag("start", "Start time (RFC3339 or Unix timestamp).").String()
|
||||||
querySeriesEnd := querySeriesCmd.Flag("end", "End time (RFC3339 or Unix timestamp).").String()
|
querySeriesEnd := querySeriesCmd.Flag("end", "End time (RFC3339 or Unix timestamp).").String()
|
||||||
|
@ -153,7 +161,7 @@ func main() {
|
||||||
debugAllServer := debugAllCmd.Arg("server", "Prometheus server to get all debug information from.").Required().String()
|
debugAllServer := debugAllCmd.Arg("server", "Prometheus server to get all debug information from.").Required().String()
|
||||||
|
|
||||||
queryLabelsCmd := queryCmd.Command("labels", "Run labels query.")
|
queryLabelsCmd := queryCmd.Command("labels", "Run labels query.")
|
||||||
queryLabelsServer := queryLabelsCmd.Arg("server", "Prometheus server to query.").Required().URL()
|
queryLabelsCmd.Arg("server", "Prometheus server to query.").Required().URLVar(&serverURL)
|
||||||
queryLabelsName := queryLabelsCmd.Arg("name", "Label name to provide label values for.").Required().String()
|
queryLabelsName := queryLabelsCmd.Arg("name", "Label name to provide label values for.").Required().String()
|
||||||
queryLabelsBegin := queryLabelsCmd.Flag("start", "Start time (RFC3339 or Unix timestamp).").String()
|
queryLabelsBegin := queryLabelsCmd.Flag("start", "Start time (RFC3339 or Unix timestamp).").String()
|
||||||
queryLabelsEnd := queryLabelsCmd.Flag("end", "End time (RFC3339 or Unix timestamp).").String()
|
queryLabelsEnd := queryLabelsCmd.Flag("end", "End time (RFC3339 or Unix timestamp).").String()
|
||||||
|
@ -200,7 +208,8 @@ func main() {
|
||||||
importFilePath := openMetricsImportCmd.Arg("input file", "OpenMetrics file to read samples from.").Required().String()
|
importFilePath := openMetricsImportCmd.Arg("input file", "OpenMetrics file to read samples from.").Required().String()
|
||||||
importDBPath := openMetricsImportCmd.Arg("output directory", "Output directory for generated blocks.").Default(defaultDBPath).String()
|
importDBPath := openMetricsImportCmd.Arg("output directory", "Output directory for generated blocks.").Default(defaultDBPath).String()
|
||||||
importRulesCmd := importCmd.Command("rules", "Create blocks of data for new recording rules.")
|
importRulesCmd := importCmd.Command("rules", "Create blocks of data for new recording rules.")
|
||||||
importRulesURL := importRulesCmd.Flag("url", "The URL for the Prometheus API with the data where the rule will be backfilled from.").Default("http://localhost:9090").URL()
|
importRulesCmd.Flag("http.config.file", "HTTP client configuration file for promtool to connect to Prometheus.").PlaceHolder("<filename>").ExistingFileVar(&httpConfigFilePath)
|
||||||
|
importRulesCmd.Flag("url", "The URL for the Prometheus API with the data where the rule will be backfilled from.").Default("http://localhost:9090").URLVar(&serverURL)
|
||||||
importRulesStart := importRulesCmd.Flag("start", "The time to start backfilling the new rule from. Must be a RFC3339 formatted date or Unix timestamp. Required.").
|
importRulesStart := importRulesCmd.Flag("start", "The time to start backfilling the new rule from. Must be a RFC3339 formatted date or Unix timestamp. Required.").
|
||||||
Required().String()
|
Required().String()
|
||||||
importRulesEnd := importRulesCmd.Flag("end", "If an end time is provided, all recording rules in the rule files provided will be backfilled to the end time. Default will backfill up to 3 hours ago. Must be a RFC3339 formatted date or Unix timestamp.").String()
|
importRulesEnd := importRulesCmd.Flag("end", "If an end time is provided, all recording rules in the rule files provided will be backfilled to the end time. Default will backfill up to 3 hours ago. Must be a RFC3339 formatted date or Unix timestamp.").String()
|
||||||
|
@ -224,6 +233,22 @@ func main() {
|
||||||
p = &promqlPrinter{}
|
p = &promqlPrinter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if httpConfigFilePath != "" {
|
||||||
|
if serverURL != nil && serverURL.User.Username() != "" {
|
||||||
|
kingpin.Fatalf("Cannot set base auth in the server URL and use a http.config.file at the same time")
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
httpConfig, _, err := config_util.LoadHTTPConfigFile(httpConfigFilePath)
|
||||||
|
if err != nil {
|
||||||
|
kingpin.Fatalf("Failed to load HTTP config file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
httpRoundTripper, err = promconfig.NewRoundTripperFromConfig(*httpConfig, "promtool", config_util.WithUserAgent("promtool/"+version.Version))
|
||||||
|
if err != nil {
|
||||||
|
kingpin.Fatalf("Failed to create a new HTTP round tripper: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var noDefaultScrapePort bool
|
var noDefaultScrapePort bool
|
||||||
for _, f := range *featureList {
|
for _, f := range *featureList {
|
||||||
opts := strings.Split(f, ",")
|
opts := strings.Split(f, ",")
|
||||||
|
@ -258,13 +283,13 @@ func main() {
|
||||||
os.Exit(CheckMetrics(*checkMetricsExtended))
|
os.Exit(CheckMetrics(*checkMetricsExtended))
|
||||||
|
|
||||||
case queryInstantCmd.FullCommand():
|
case queryInstantCmd.FullCommand():
|
||||||
os.Exit(QueryInstant(*queryInstantServer, *queryInstantExpr, *queryInstantTime, p))
|
os.Exit(QueryInstant(serverURL, httpRoundTripper, *queryInstantExpr, *queryInstantTime, p))
|
||||||
|
|
||||||
case queryRangeCmd.FullCommand():
|
case queryRangeCmd.FullCommand():
|
||||||
os.Exit(QueryRange(*queryRangeServer, *queryRangeHeaders, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep, p))
|
os.Exit(QueryRange(serverURL, httpRoundTripper, *queryRangeHeaders, *queryRangeExpr, *queryRangeBegin, *queryRangeEnd, *queryRangeStep, p))
|
||||||
|
|
||||||
case querySeriesCmd.FullCommand():
|
case querySeriesCmd.FullCommand():
|
||||||
os.Exit(QuerySeries(*querySeriesServer, *querySeriesMatch, *querySeriesBegin, *querySeriesEnd, p))
|
os.Exit(QuerySeries(serverURL, httpRoundTripper, *querySeriesMatch, *querySeriesBegin, *querySeriesEnd, p))
|
||||||
|
|
||||||
case debugPprofCmd.FullCommand():
|
case debugPprofCmd.FullCommand():
|
||||||
os.Exit(debugPprof(*debugPprofServer))
|
os.Exit(debugPprof(*debugPprofServer))
|
||||||
|
@ -276,7 +301,7 @@ func main() {
|
||||||
os.Exit(debugAll(*debugAllServer))
|
os.Exit(debugAll(*debugAllServer))
|
||||||
|
|
||||||
case queryLabelsCmd.FullCommand():
|
case queryLabelsCmd.FullCommand():
|
||||||
os.Exit(QueryLabels(*queryLabelsServer, *queryLabelsMatch, *queryLabelsName, *queryLabelsBegin, *queryLabelsEnd, p))
|
os.Exit(QueryLabels(serverURL, httpRoundTripper, *queryLabelsMatch, *queryLabelsName, *queryLabelsBegin, *queryLabelsEnd, p))
|
||||||
|
|
||||||
case testRulesCmd.FullCommand():
|
case testRulesCmd.FullCommand():
|
||||||
os.Exit(RulesUnitTest(
|
os.Exit(RulesUnitTest(
|
||||||
|
@ -303,7 +328,7 @@ func main() {
|
||||||
os.Exit(backfillOpenMetrics(*importFilePath, *importDBPath, *importHumanReadable, *importQuiet, *maxBlockDuration))
|
os.Exit(backfillOpenMetrics(*importFilePath, *importDBPath, *importHumanReadable, *importQuiet, *maxBlockDuration))
|
||||||
|
|
||||||
case importRulesCmd.FullCommand():
|
case importRulesCmd.FullCommand():
|
||||||
os.Exit(checkErr(importRules(*importRulesURL, *importRulesStart, *importRulesEnd, *importRulesOutputDir, *importRulesEvalInterval, *maxBlockDuration, *importRulesFiles...)))
|
os.Exit(checkErr(importRules(serverURL, httpRoundTripper, *importRulesStart, *importRulesEnd, *importRulesOutputDir, *importRulesEvalInterval, *maxBlockDuration, *importRulesFiles...)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,12 +820,13 @@ func checkMetricsExtended(r io.Reader) ([]metricStat, int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryInstant performs an instant query against a Prometheus server.
|
// QueryInstant performs an instant query against a Prometheus server.
|
||||||
func QueryInstant(url *url.URL, query, evalTime string, p printer) int {
|
func QueryInstant(url *url.URL, roundTripper http.RoundTripper, query, evalTime string, p printer) int {
|
||||||
if url.Scheme == "" {
|
if url.Scheme == "" {
|
||||||
url.Scheme = "http"
|
url.Scheme = "http"
|
||||||
}
|
}
|
||||||
config := api.Config{
|
config := api.Config{
|
||||||
Address: url.String(),
|
Address: url.String(),
|
||||||
|
RoundTripper: roundTripper,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new client.
|
// Create new client.
|
||||||
|
@ -835,12 +861,13 @@ func QueryInstant(url *url.URL, query, evalTime string, p printer) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryRange performs a range query against a Prometheus server.
|
// QueryRange performs a range query against a Prometheus server.
|
||||||
func QueryRange(url *url.URL, headers map[string]string, query, start, end string, step time.Duration, p printer) int {
|
func QueryRange(url *url.URL, roundTripper http.RoundTripper, headers map[string]string, query, start, end string, step time.Duration, p printer) int {
|
||||||
if url.Scheme == "" {
|
if url.Scheme == "" {
|
||||||
url.Scheme = "http"
|
url.Scheme = "http"
|
||||||
}
|
}
|
||||||
config := api.Config{
|
config := api.Config{
|
||||||
Address: url.String(),
|
Address: url.String(),
|
||||||
|
RoundTripper: roundTripper,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(headers) > 0 {
|
if len(headers) > 0 {
|
||||||
|
@ -848,7 +875,7 @@ func QueryRange(url *url.URL, headers map[string]string, query, start, end strin
|
||||||
for key, value := range headers {
|
for key, value := range headers {
|
||||||
req.Header.Add(key, value)
|
req.Header.Add(key, value)
|
||||||
}
|
}
|
||||||
return http.DefaultTransport.RoundTrip(req)
|
return roundTripper.RoundTrip(req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,12 +935,13 @@ func QueryRange(url *url.URL, headers map[string]string, query, start, end strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, end string, p printer) int {
|
func QuerySeries(url *url.URL, roundTripper http.RoundTripper, matchers []string, start, end string, p printer) int {
|
||||||
if url.Scheme == "" {
|
if url.Scheme == "" {
|
||||||
url.Scheme = "http"
|
url.Scheme = "http"
|
||||||
}
|
}
|
||||||
config := api.Config{
|
config := api.Config{
|
||||||
Address: url.String(),
|
Address: url.String(),
|
||||||
|
RoundTripper: roundTripper,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new client.
|
// Create new client.
|
||||||
|
@ -944,12 +972,13 @@ func QuerySeries(url *url.URL, matchers []string, start, end string, p printer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryLabels queries for label values against a Prometheus server.
|
// QueryLabels queries for label values against a Prometheus server.
|
||||||
func QueryLabels(url *url.URL, matchers []string, name, start, end string, p printer) int {
|
func QueryLabels(url *url.URL, roundTripper http.RoundTripper, matchers []string, name, start, end string, p printer) int {
|
||||||
if url.Scheme == "" {
|
if url.Scheme == "" {
|
||||||
url.Scheme = "http"
|
url.Scheme = "http"
|
||||||
}
|
}
|
||||||
config := api.Config{
|
config := api.Config{
|
||||||
Address: url.String(),
|
Address: url.String(),
|
||||||
|
RoundTripper: roundTripper,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new client.
|
// Create new client.
|
||||||
|
@ -1154,7 +1183,7 @@ func (j *jsonPrinter) printLabelValues(v model.LabelValues) {
|
||||||
|
|
||||||
// importRules backfills recording rules from the files provided. The output are blocks of data
|
// importRules backfills recording rules from the files provided. The output are blocks of data
|
||||||
// at the outputDir location.
|
// at the outputDir location.
|
||||||
func importRules(url *url.URL, start, end, outputDir string, evalInterval, maxBlockDuration time.Duration, files ...string) error {
|
func importRules(url *url.URL, roundTripper http.RoundTripper, start, end, outputDir string, evalInterval, maxBlockDuration time.Duration, files ...string) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var stime, etime time.Time
|
var stime, etime time.Time
|
||||||
var err error
|
var err error
|
||||||
|
@ -1184,7 +1213,8 @@ func importRules(url *url.URL, start, end, outputDir string, evalInterval, maxBl
|
||||||
maxBlockDuration: maxBlockDuration,
|
maxBlockDuration: maxBlockDuration,
|
||||||
}
|
}
|
||||||
client, err := api.NewClient(api.Config{
|
client, err := api.NewClient(api.Config{
|
||||||
Address: url.String(),
|
Address: url.String(),
|
||||||
|
RoundTripper: roundTripper,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("new api client error: %w", err)
|
return fmt.Errorf("new api client error: %w", err)
|
||||||
|
|
|
@ -56,14 +56,14 @@ func TestQueryRange(t *testing.T) {
|
||||||
require.Equal(t, nil, err)
|
require.Equal(t, nil, err)
|
||||||
|
|
||||||
p := &promqlPrinter{}
|
p := &promqlPrinter{}
|
||||||
exitCode := QueryRange(urlObject, map[string]string{}, "up", "0", "300", 0, p)
|
exitCode := QueryRange(urlObject, http.DefaultTransport, map[string]string{}, "up", "0", "300", 0, p)
|
||||||
require.Equal(t, "/api/v1/query_range", getRequest().URL.Path)
|
require.Equal(t, "/api/v1/query_range", getRequest().URL.Path)
|
||||||
form := getRequest().Form
|
form := getRequest().Form
|
||||||
require.Equal(t, "up", form.Get("query"))
|
require.Equal(t, "up", form.Get("query"))
|
||||||
require.Equal(t, "1", form.Get("step"))
|
require.Equal(t, "1", form.Get("step"))
|
||||||
require.Equal(t, 0, exitCode)
|
require.Equal(t, 0, exitCode)
|
||||||
|
|
||||||
exitCode = QueryRange(urlObject, map[string]string{}, "up", "0", "300", 10*time.Millisecond, p)
|
exitCode = QueryRange(urlObject, http.DefaultTransport, map[string]string{}, "up", "0", "300", 10*time.Millisecond, p)
|
||||||
require.Equal(t, "/api/v1/query_range", getRequest().URL.Path)
|
require.Equal(t, "/api/v1/query_range", getRequest().URL.Path)
|
||||||
form = getRequest().Form
|
form = getRequest().Form
|
||||||
require.Equal(t, "up", form.Get("query"))
|
require.Equal(t, "up", form.Get("query"))
|
||||||
|
@ -79,7 +79,7 @@ func TestQueryInstant(t *testing.T) {
|
||||||
require.Equal(t, nil, err)
|
require.Equal(t, nil, err)
|
||||||
|
|
||||||
p := &promqlPrinter{}
|
p := &promqlPrinter{}
|
||||||
exitCode := QueryInstant(urlObject, "up", "300", p)
|
exitCode := QueryInstant(urlObject, http.DefaultTransport, "up", "300", p)
|
||||||
require.Equal(t, "/api/v1/query", getRequest().URL.Path)
|
require.Equal(t, "/api/v1/query", getRequest().URL.Path)
|
||||||
form := getRequest().Form
|
form := getRequest().Form
|
||||||
require.Equal(t, "up", form.Get("query"))
|
require.Equal(t, "up", form.Get("query"))
|
||||||
|
|
Loading…
Reference in a new issue