promtool: Add feature flags for promql features (#16443)

These are supported in the main prometheus binary but the feature flags
weren't supported in promtool.

Fixes #16412.

Signed-off-by: David Leadbeater <dgl@dgl.cx>
This commit is contained in:
David Leadbeater 2025-04-17 19:29:44 +10:00 committed by GitHub
parent dcb790c9b6
commit e647f7954f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 32 additions and 6 deletions

View File

@ -61,6 +61,8 @@ import (
"github.com/prometheus/prometheus/util/documentcli"
)
var promqlEnableDelayedNameRemoval = false
func init() {
// This can be removed when the legacy global mode is fully deprecated.
//nolint:staticcheck
@ -304,7 +306,7 @@ func main() {
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. Currently unused.").Default("").Strings()
featureList := app.Flag("enable-feature", "Comma separated feature names to enable. Valid options: promql-experimental-functions, promql-delayed-name-removal. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details").Default("").Strings()
documentationCmd := app.Command("write-documentation", "Generate command line documentation. Internal use.").Hidden()
@ -338,10 +340,14 @@ func main() {
opts := strings.Split(f, ",")
for _, o := range opts {
switch o {
case "promql-experimental-functions":
parser.EnableExperimentalFunctions = true
case "promql-delayed-name-removal":
promqlEnableDelayedNameRemoval = true
case "":
continue
default:
fmt.Printf(" WARNING: --enable-feature is currently a no-op")
fmt.Printf(" WARNING: Unknown feature passed to --enable-feature: %s", o)
}
}
}
@ -399,8 +405,9 @@ func main() {
}
os.Exit(RulesUnitTestResult(results,
promqltest.LazyLoaderOpts{
EnableAtModifier: true,
EnableNegativeOffset: true,
EnableAtModifier: true,
EnableNegativeOffset: true,
EnableDelayedNameRemoval: promqlEnableDelayedNameRemoval,
},
*testRulesRun,
*testRulesDiff,

View File

@ -558,6 +558,16 @@ func TestCheckRules(t *testing.T) {
})
}
func TestCheckRulesWithFeatureFlag(t *testing.T) {
// As opposed to TestCheckRules calling CheckRules directly we run promtool
// so the feature flag parsing can be tested.
args := []string{"-test.main", "--enable-feature=promql-experimental-functions", "check", "rules", "testdata/features.yml"}
tool := exec.Command(promtoolPath, args...)
err := tool.Run()
require.NoError(t, err)
}
func TestCheckRulesWithRuleFiles(t *testing.T) {
t.Run("rules-good", func(t *testing.T) {
t.Parallel()

6
cmd/promtool/testdata/features.yml vendored Normal file
View File

@ -0,0 +1,6 @@
groups:
- name: features
rules:
- record: x
# We don't expect anything from this, just want to check the function parses.
expr: sort_by_label(up, "instance")

View File

@ -15,7 +15,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">--version</code> | Show application version. |
| <code class="text-nowrap">--experimental</code> | Enable experimental commands. |
| <code class="text-nowrap">--enable-feature</code> <code class="text-nowrap">...<code class="text-nowrap"> | Comma separated feature names to enable. Currently unused. |
| <code class="text-nowrap">--enable-feature</code> <code class="text-nowrap">...<code class="text-nowrap"> | Comma separated feature names to enable. Valid options: promql-experimental-functions, promql-delayed-name-removal. See https://prometheus.io/docs/prometheus/latest/feature_flags/ for more details |

View File

@ -1501,6 +1501,9 @@ type LazyLoaderOpts struct {
// Prometheus v2.33). They can still be disabled here for legacy and
// other uses.
EnableAtModifier, EnableNegativeOffset bool
// Currently defaults to false, matches the "promql-delayed-name-removal"
// feature flag.
EnableDelayedNameRemoval bool
}
// NewLazyLoader returns an initialized empty LazyLoader.
@ -1563,7 +1566,7 @@ func (ll *LazyLoader) clear() error {
NoStepSubqueryIntervalFn: func(int64) int64 { return durationMilliseconds(ll.SubqueryInterval) },
EnableAtModifier: ll.opts.EnableAtModifier,
EnableNegativeOffset: ll.opts.EnableNegativeOffset,
EnableDelayedNameRemoval: true,
EnableDelayedNameRemoval: ll.opts.EnableDelayedNameRemoval,
}
ll.queryEngine = promql.NewEngine(opts)