diff --git a/cmd/mimir/config-descriptor.json b/cmd/mimir/config-descriptor.json index 863f1afb19c..5d3d47d9d7e 100644 --- a/cmd/mimir/config-descriptor.json +++ b/cmd/mimir/config-descriptor.json @@ -12642,6 +12642,17 @@ "fieldFlag": "ruler.independent-rule-evaluation-concurrency-min-duration-percentage", "fieldType": "float", "fieldCategory": "experimental" + }, + { + "kind": "field", + "name": "rule_evaluation_write_enabled", + "required": false, + "desc": "False to disable writing the result of rule evaluation to ingesters. This option can be used for testing purposes.", + "fieldValue": null, + "fieldDefaultValue": true, + "fieldFlag": "ruler.rule-evaluation-write-enabled", + "fieldType": "boolean", + "fieldCategory": "experimental" } ], "fieldValue": null, diff --git a/cmd/mimir/help-all.txt.tmpl b/cmd/mimir/help-all.txt.tmpl index 29a7dca13aa..2fdf53cb160 100644 --- a/cmd/mimir/help-all.txt.tmpl +++ b/cmd/mimir/help-all.txt.tmpl @@ -2783,6 +2783,8 @@ Usage of ./cmd/mimir/mimir: The prefix for the keys in the store. Should end with a /. (default "rulers/") -ruler.ring.store string Backend storage to use for the ring. Supported values are: consul, etcd, inmemory, memberlist, multi. (default "memberlist") + -ruler.rule-evaluation-write-enabled + [experimental] False to disable writing the result of rule evaluation to ingesters. This option can be used for testing purposes. (default true) -ruler.rule-path string Directory to store temporary rule files loaded by the Prometheus rule managers. This directory is not required to be persisted between restarts. (default "./data-ruler/") -ruler.sync-rules-on-changes-enabled diff --git a/docs/sources/mimir/configure/configuration-parameters/index.md b/docs/sources/mimir/configure/configuration-parameters/index.md index 4522035db6b..eacc5bae044 100644 --- a/docs/sources/mimir/configure/configuration-parameters/index.md +++ b/docs/sources/mimir/configure/configuration-parameters/index.md @@ -2118,6 +2118,11 @@ tenant_federation: # group runtime duration must exceed 50.0% of the evaluation interval. # CLI flag: -ruler.independent-rule-evaluation-concurrency-min-duration-percentage [independent_rule_evaluation_concurrency_min_duration_percentage: | default = 50] + +# (experimental) False to disable writing the result of rule evaluation to +# ingesters. This option can be used for testing purposes. +# CLI flag: -ruler.rule-evaluation-write-enabled +[rule_evaluation_write_enabled: | default = true] ``` ### ruler_storage diff --git a/pkg/ruler/compat.go b/pkg/ruler/compat.go index 724d3f8f06d..ffe9c5cd906 100644 --- a/pkg/ruler/compat.go +++ b/pkg/ruler/compat.go @@ -141,6 +141,47 @@ func (t *PusherAppendable) Appender(ctx context.Context) storage.Appender { } } +type noopAppender struct{} + +func (a *noopAppender) Append(_ storage.SeriesRef, l labels.Labels, t int64, v float64) (storage.SeriesRef, error) { + return 0, nil +} + +func (a *noopAppender) AppendExemplar(_ storage.SeriesRef, _ labels.Labels, _ exemplar.Exemplar) (storage.SeriesRef, error) { + return 0, errors.New("exemplars are unsupported") +} + +func (a *noopAppender) UpdateMetadata(_ storage.SeriesRef, _ labels.Labels, _ metadata.Metadata) (storage.SeriesRef, error) { + return 0, errors.New("metadata updates are unsupported") +} + +func (a *noopAppender) AppendHistogram(_ storage.SeriesRef, l labels.Labels, t int64, h *histogram.Histogram, fh *histogram.FloatHistogram) (storage.SeriesRef, error) { + return 0, nil +} + +func (a *noopAppender) AppendCTZeroSample(_ storage.SeriesRef, _ labels.Labels, _, _ int64) (storage.SeriesRef, error) { + return 0, errors.New("CT zero samples are unsupported") +} + +func (a *noopAppender) Commit() error { + return nil +} + +func (a *noopAppender) Rollback() error { + return nil +} + +type noopAppendable struct{} + +func newNoopAppendable() *noopAppendable { + return &noopAppendable{} +} + +// Appender returns a storage.Appender. +func (t *noopAppendable) Appender(ctx context.Context) storage.Appender { + return &noopAppender{} +} + // RulesLimits defines limits used by Ruler. type RulesLimits interface { EvaluationDelay(userID string) time.Duration @@ -267,7 +308,7 @@ type ManagerFactory func(ctx context.Context, userID string, notifier *notifier. func DefaultTenantManagerFactory( cfg Config, - p Pusher, + pusher Pusher, queryable storage.Queryable, queryFunc rules.QueryFunc, concurrencyController MultiTenantRuleConcurrencyController, @@ -319,8 +360,15 @@ func DefaultTenantManagerFactory( // Wrap the queryable with our custom logic. wrappedQueryable := WrapQueryableWithReadConsistency(queryable, logger) + var appendeable storage.Appendable + if cfg.RuleEvaluationWriteEnabled { + appendeable = NewPusherAppendable(pusher, userID, totalWrites, failedWrites) + } else { + appendeable = newNoopAppendable() + } + return rules.NewManager(&rules.ManagerOptions{ - Appendable: NewPusherAppendable(p, userID, totalWrites, failedWrites), + Appendable: appendeable, Queryable: wrappedQueryable, QueryFunc: wrappedQueryFunc, Context: user.InjectOrgID(ctx, userID), diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index 63aad28a47c..4a1867a7ddc 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -140,6 +140,8 @@ type Config struct { MaxIndependentRuleEvaluationConcurrency int64 `yaml:"max_independent_rule_evaluation_concurrency" category:"experimental"` IndependentRuleEvaluationConcurrencyMinDurationPercentage float64 `yaml:"independent_rule_evaluation_concurrency_min_duration_percentage" category:"experimental"` + + RuleEvaluationWriteEnabled bool `yaml:"rule_evaluation_write_enabled" category:"experimental"` } // Validate config and returns error on failure @@ -200,6 +202,8 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet, logger log.Logger) { f.Int64Var(&cfg.MaxIndependentRuleEvaluationConcurrency, "ruler.max-independent-rule-evaluation-concurrency", 0, "Number of rules rules that don't have dependencies that we allow to be evaluated concurrently across all tenants. 0 to disable.") f.Float64Var(&cfg.IndependentRuleEvaluationConcurrencyMinDurationPercentage, "ruler.independent-rule-evaluation-concurrency-min-duration-percentage", 50.0, "Minimum threshold of the interval to last rule group runtime duration to allow a rule to be evaluated concurrency. By default, the rule group runtime duration must exceed 50.0% of the evaluation interval.") + f.BoolVar(&cfg.RuleEvaluationWriteEnabled, "ruler.rule-evaluation-write-enabled", true, "False to disable writing the result of rule evaluation to ingesters. This option can be used for testing purposes.") + cfg.RingCheckPeriod = 5 * time.Second }