mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-12 22:37:27 -08:00
Merge pull request #11411 from robskillington/add-promql-cmds-to-promtool
Add PromQL format and label matcher set/delete commands to promtool
This commit is contained in:
commit
52b1ddc050
|
@ -58,6 +58,7 @@ import (
|
||||||
"github.com/prometheus/prometheus/notifier"
|
"github.com/prometheus/prometheus/notifier"
|
||||||
_ "github.com/prometheus/prometheus/plugins" // Register plugins.
|
_ "github.com/prometheus/prometheus/plugins" // Register plugins.
|
||||||
"github.com/prometheus/prometheus/promql"
|
"github.com/prometheus/prometheus/promql"
|
||||||
|
"github.com/prometheus/prometheus/promql/parser"
|
||||||
"github.com/prometheus/prometheus/scrape"
|
"github.com/prometheus/prometheus/scrape"
|
||||||
"github.com/prometheus/prometheus/util/documentcli"
|
"github.com/prometheus/prometheus/util/documentcli"
|
||||||
)
|
)
|
||||||
|
@ -91,6 +92,8 @@ func main() {
|
||||||
|
|
||||||
checkCmd := app.Command("check", "Check the resources for validity.")
|
checkCmd := app.Command("check", "Check the resources for validity.")
|
||||||
|
|
||||||
|
experimental := app.Flag("experimental", "Enable experimental commands.").Bool()
|
||||||
|
|
||||||
sdCheckCmd := checkCmd.Command("service-discovery", "Perform service discovery for the given job name and report the results, including relabeling.")
|
sdCheckCmd := checkCmd.Command("service-discovery", "Perform service discovery for the given job name and report the results, including relabeling.")
|
||||||
sdConfigFile := sdCheckCmd.Arg("config-file", "The prometheus config file.").Required().ExistingFile()
|
sdConfigFile := sdCheckCmd.Arg("config-file", "The prometheus config file.").Required().ExistingFile()
|
||||||
sdJobName := sdCheckCmd.Arg("job", "The job to run service discovery for.").Required().String()
|
sdJobName := sdCheckCmd.Arg("job", "The job to run service discovery for.").Required().String()
|
||||||
|
@ -245,6 +248,22 @@ func main() {
|
||||||
"A list of one or more files containing recording rules to be backfilled. All recording rules listed in the files will be backfilled. Alerting rules are not evaluated.",
|
"A list of one or more files containing recording rules to be backfilled. All recording rules listed in the files will be backfilled. Alerting rules are not evaluated.",
|
||||||
).Required().ExistingFiles()
|
).Required().ExistingFiles()
|
||||||
|
|
||||||
|
promQLCmd := app.Command("promql", "PromQL formatting and editing. Requires the --experimental flag.")
|
||||||
|
|
||||||
|
promQLFormatCmd := promQLCmd.Command("format", "Format PromQL query to pretty printed form.")
|
||||||
|
promQLFormatQuery := promQLFormatCmd.Arg("query", "PromQL query.").Required().String()
|
||||||
|
|
||||||
|
promQLLabelsCmd := promQLCmd.Command("label-matchers", "Edit label matchers contained within an existing PromQL query.")
|
||||||
|
promQLLabelsSetCmd := promQLLabelsCmd.Command("set", "Set a label matcher in the query.")
|
||||||
|
promQLLabelsSetType := promQLLabelsSetCmd.Flag("type", "Type of the label matcher to set.").Short('t').Default("=").Enum("=", "!=", "=~", "!~")
|
||||||
|
promQLLabelsSetQuery := promQLLabelsSetCmd.Arg("query", "PromQL query.").Required().String()
|
||||||
|
promQLLabelsSetName := promQLLabelsSetCmd.Arg("name", "Name of the label matcher to set.").Required().String()
|
||||||
|
promQLLabelsSetValue := promQLLabelsSetCmd.Arg("value", "Value of the label matcher to set.").Required().String()
|
||||||
|
|
||||||
|
promQLLabelsDeleteCmd := promQLLabelsCmd.Command("delete", "Delete a label from the query.")
|
||||||
|
promQLLabelsDeleteQuery := promQLLabelsDeleteCmd.Arg("query", "PromQL query.").Required().String()
|
||||||
|
promQLLabelsDeleteName := promQLLabelsDeleteCmd.Arg("name", "Name of the label to delete.").Required().String()
|
||||||
|
|
||||||
featureList := app.Flag("enable-feature", "Comma separated feature names to enable (only PromQL related and no-default-scrape-port). See https://prometheus.io/docs/prometheus/latest/feature_flags/ for the options and more details.").Default("").Strings()
|
featureList := app.Flag("enable-feature", "Comma separated feature names to enable (only PromQL related and no-default-scrape-port). See https://prometheus.io/docs/prometheus/latest/feature_flags/ for the options and more details.").Default("").Strings()
|
||||||
|
|
||||||
documentationCmd := app.Command("write-documentation", "Generate command line documentation. Internal use.").Hidden()
|
documentationCmd := app.Command("write-documentation", "Generate command line documentation. Internal use.").Hidden()
|
||||||
|
@ -364,8 +383,28 @@ func main() {
|
||||||
|
|
||||||
case importRulesCmd.FullCommand():
|
case importRulesCmd.FullCommand():
|
||||||
os.Exit(checkErr(importRules(serverURL, httpRoundTripper, *importRulesStart, *importRulesEnd, *importRulesOutputDir, *importRulesEvalInterval, *maxBlockDuration, *importRulesFiles...)))
|
os.Exit(checkErr(importRules(serverURL, httpRoundTripper, *importRulesStart, *importRulesEnd, *importRulesOutputDir, *importRulesEvalInterval, *maxBlockDuration, *importRulesFiles...)))
|
||||||
|
|
||||||
case documentationCmd.FullCommand():
|
case documentationCmd.FullCommand():
|
||||||
os.Exit(checkErr(documentcli.GenerateMarkdown(app.Model(), os.Stdout)))
|
os.Exit(checkErr(documentcli.GenerateMarkdown(app.Model(), os.Stdout)))
|
||||||
|
|
||||||
|
case promQLFormatCmd.FullCommand():
|
||||||
|
checkExperimental(*experimental)
|
||||||
|
os.Exit(checkErr(formatPromQL(*promQLFormatQuery)))
|
||||||
|
|
||||||
|
case promQLLabelsSetCmd.FullCommand():
|
||||||
|
checkExperimental(*experimental)
|
||||||
|
os.Exit(checkErr(labelsSetPromQL(*promQLLabelsSetQuery, *promQLLabelsSetType, *promQLLabelsSetName, *promQLLabelsSetValue)))
|
||||||
|
|
||||||
|
case promQLLabelsDeleteCmd.FullCommand():
|
||||||
|
checkExperimental(*experimental)
|
||||||
|
os.Exit(checkErr(labelsDeletePromQL(*promQLLabelsDeleteQuery, *promQLLabelsDeleteName)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkExperimental(f bool) {
|
||||||
|
if !f {
|
||||||
|
fmt.Fprintln(os.Stderr, "This command is experimental and requires the --experimental flag to be set.")
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1375,3 +1414,79 @@ func checkTargetGroupsForScrapeConfig(targetGroups []*targetgroup.Group, scfg *c
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatPromQL(query string) error {
|
||||||
|
expr, err := parser.ParseExpr(query)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(expr.Pretty(0))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func labelsSetPromQL(query, labelMatchType, name, value string) error {
|
||||||
|
expr, err := parser.ParseExpr(query)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var matchType labels.MatchType
|
||||||
|
switch labelMatchType {
|
||||||
|
case parser.ItemType(parser.EQL).String():
|
||||||
|
matchType = labels.MatchEqual
|
||||||
|
case parser.ItemType(parser.NEQ).String():
|
||||||
|
matchType = labels.MatchNotEqual
|
||||||
|
case parser.ItemType(parser.EQL_REGEX).String():
|
||||||
|
matchType = labels.MatchRegexp
|
||||||
|
case parser.ItemType(parser.NEQ_REGEX).String():
|
||||||
|
matchType = labels.MatchNotRegexp
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid label match type: %s", labelMatchType)
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.Inspect(expr, func(node parser.Node, path []parser.Node) error {
|
||||||
|
if n, ok := node.(*parser.VectorSelector); ok {
|
||||||
|
var found bool
|
||||||
|
for i, l := range n.LabelMatchers {
|
||||||
|
if l.Name == name {
|
||||||
|
n.LabelMatchers[i].Type = matchType
|
||||||
|
n.LabelMatchers[i].Value = value
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
n.LabelMatchers = append(n.LabelMatchers, &labels.Matcher{
|
||||||
|
Type: matchType,
|
||||||
|
Name: name,
|
||||||
|
Value: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(expr.Pretty(0))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func labelsDeletePromQL(query, name string) error {
|
||||||
|
expr, err := parser.ParseExpr(query)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.Inspect(expr, func(node parser.Node, path []parser.Node) error {
|
||||||
|
if n, ok := node.(*parser.VectorSelector); ok {
|
||||||
|
for i, l := range n.LabelMatchers {
|
||||||
|
if l.Name == name {
|
||||||
|
n.LabelMatchers = append(n.LabelMatchers[:i], n.LabelMatchers[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(expr.Pretty(0))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ Tooling for the Prometheus monitoring system.
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| <code class="text-nowrap">-h</code>, <code class="text-nowrap">--help</code> | Show context-sensitive help (also try --help-long and --help-man). |
|
| <code class="text-nowrap">-h</code>, <code class="text-nowrap">--help</code> | Show context-sensitive help (also try --help-long and --help-man). |
|
||||||
| <code class="text-nowrap">--version</code> | Show application version. |
|
| <code class="text-nowrap">--version</code> | Show application version. |
|
||||||
|
| <code class="text-nowrap">--experimental</code> | Enable experimental commands. |
|
||||||
| <code class="text-nowrap">--enable-feature</code> | Comma separated feature names to enable (only PromQL related and no-default-scrape-port). See https://prometheus.io/docs/prometheus/latest/feature_flags/ for the options and more details. |
|
| <code class="text-nowrap">--enable-feature</code> | Comma separated feature names to enable (only PromQL related and no-default-scrape-port). See https://prometheus.io/docs/prometheus/latest/feature_flags/ for the options and more details. |
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ Tooling for the Prometheus monitoring system.
|
||||||
| push | Push to a Prometheus server. |
|
| push | Push to a Prometheus server. |
|
||||||
| test | Unit testing. |
|
| test | Unit testing. |
|
||||||
| tsdb | Run tsdb commands. |
|
| tsdb | Run tsdb commands. |
|
||||||
|
| promql | PromQL formatting and editing. Requires the --experimental flag. |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -609,3 +611,72 @@ Create blocks of data for new recording rules.
|
||||||
| rule-files | A list of one or more files containing recording rules to be backfilled. All recording rules listed in the files will be backfilled. Alerting rules are not evaluated. | Yes |
|
| rule-files | A list of one or more files containing recording rules to be backfilled. All recording rules listed in the files will be backfilled. Alerting rules are not evaluated. | Yes |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### `promtool promql`
|
||||||
|
|
||||||
|
PromQL formatting and editing. Requires the `--experimental` flag.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##### `promtool promql format`
|
||||||
|
|
||||||
|
Format PromQL query to pretty printed form.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### Arguments
|
||||||
|
|
||||||
|
| Argument | Description | Required |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| query | PromQL query. | Yes |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##### `promtool promql label-matchers`
|
||||||
|
|
||||||
|
Edit label matchers contained within an existing PromQL query.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##### `promtool promql label-matchers set`
|
||||||
|
|
||||||
|
Set a label matcher in the query.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### Flags
|
||||||
|
|
||||||
|
| Flag | Description | Default |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| <code class="text-nowrap">-t</code>, <code class="text-nowrap">--type</code> | Type of the label matcher to set. | `=` |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### Arguments
|
||||||
|
|
||||||
|
| Argument | Description | Required |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| query | PromQL query. | Yes |
|
||||||
|
| name | Name of the label matcher to set. | Yes |
|
||||||
|
| value | Value of the label matcher to set. | Yes |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##### `promtool promql label-matchers delete`
|
||||||
|
|
||||||
|
Delete a label from the query.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###### Arguments
|
||||||
|
|
||||||
|
| Argument | Description | Required |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| query | PromQL query. | Yes |
|
||||||
|
| name | Name of the label to delete. | Yes |
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alecthomas/kingpin/v2"
|
"github.com/alecthomas/kingpin/v2"
|
||||||
|
"github.com/grafana/regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenerateMarkdown generates the markdown documentation for an application from
|
// GenerateMarkdown generates the markdown documentation for an application from
|
||||||
|
@ -230,6 +231,7 @@ func writeSubcommands(writer io.Writer, level int, modelName string, commands []
|
||||||
if cmd.HelpLong != "" {
|
if cmd.HelpLong != "" {
|
||||||
help = cmd.HelpLong
|
help = cmd.HelpLong
|
||||||
}
|
}
|
||||||
|
help = formatHyphenatedWords(help)
|
||||||
if _, err := writer.Write([]byte(fmt.Sprintf("\n\n%s `%s %s`\n\n%s\n\n", strings.Repeat("#", level+1), modelName, cmd.FullCommand, help))); err != nil {
|
if _, err := writer.Write([]byte(fmt.Sprintf("\n\n%s `%s %s`\n\n%s\n\n", strings.Repeat("#", level+1), modelName, cmd.FullCommand, help))); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -250,3 +252,11 @@ func writeSubcommands(writer io.Writer, level int, modelName string, commands []
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatHyphenatedWords(input string) string {
|
||||||
|
hyphenRegex := regexp.MustCompile(`\B--\w+\b`)
|
||||||
|
replacer := func(s string) string {
|
||||||
|
return fmt.Sprintf("`%s`", s)
|
||||||
|
}
|
||||||
|
return hyphenRegex.ReplaceAllStringFunc(input, replacer)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue