diff --git a/docs/sources/alerting/set-up/configure-alert-state-history/index.md b/docs/sources/alerting/set-up/configure-alert-state-history/index.md index 5ce753a6ad7..a70fafe75e2 100644 --- a/docs/sources/alerting/set-up/configure-alert-state-history/index.md +++ b/docs/sources/alerting/set-up/configure-alert-state-history/index.md @@ -47,9 +47,6 @@ The example below instructs Grafana to write alert state history to a local Loki enabled = true backend = "loki" loki_remote_url = "http://localhost:3100" - -[feature_toggles] -enable = alertStateHistoryLokiSecondary, alertStateHistoryLokiPrimary, alertStateHistoryLokiOnly ``` diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 769d8fb18e6..dfe52db3d81 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -139,9 +139,6 @@ Experimental features might be changed or removed without prior notice. | `influxqlStreamingParser` | Enable streaming JSON parser for InfluxDB datasource InfluxQL query language | | `lokiLogsDataplane` | Changes logs responses from Loki to be compliant with the dataplane specification. | | `disableSSEDataplane` | Disables dataplane specific processing in server side expressions. | -| `alertStateHistoryLokiSecondary` | Enable Grafana to write alert state history to an external Loki instance in addition to Grafana annotations. | -| `alertStateHistoryLokiPrimary` | Enable a remote Loki instance as the primary source for state history reads. | -| `alertStateHistoryLokiOnly` | Disable Grafana alerts from emitting annotations when a remote Loki instance is available. | | `extraThemes` | Enables extra themes | | `lokiPredefinedOperations` | Adds predefined query operations to Loki query editor | | `awsDatasourcesTempCredentials` | Support temporary security credentials in AWS plugins for Grafana Cloud customers | diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 6d37f696ff4..afaabea3c96 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -150,18 +150,6 @@ export interface FeatureToggles { */ disableSSEDataplane?: boolean; /** - * Enable Grafana to write alert state history to an external Loki instance in addition to Grafana annotations. - */ - alertStateHistoryLokiSecondary?: boolean; - /** - * Enable a remote Loki instance as the primary source for state history reads. - */ - alertStateHistoryLokiPrimary?: boolean; - /** - * Disable Grafana alerts from emitting annotations when a remote Loki instance is available. - */ - alertStateHistoryLokiOnly?: boolean; - /** * Writes error logs to the request logger * @default true */ diff --git a/pkg/services/annotations/annotationsimpl/annotations.go b/pkg/services/annotations/annotationsimpl/annotations.go index 3f7eed0056b..496b782be8f 100644 --- a/pkg/services/annotations/annotationsimpl/annotations.go +++ b/pkg/services/annotations/annotationsimpl/annotations.go @@ -41,7 +41,7 @@ func ProvideService( write := xormStore var read readStore - historianStore := loki.NewLokiHistorianStore(cfg.UnifiedAlerting.StateHistory, features, db, ruleStore, log.New("annotations.loki"), tracer) + historianStore := loki.NewLokiHistorianStore(cfg.UnifiedAlerting.StateHistory, db, ruleStore, log.New("annotations.loki"), tracer) if historianStore != nil { l.Debug("Using composite read store") read = NewCompositeStore(log.New("annotations.composite"), xormStore, historianStore) diff --git a/pkg/services/annotations/annotationsimpl/loki/historian_store.go b/pkg/services/annotations/annotationsimpl/loki/historian_store.go index 5bc4e02d303..707e9c6bebb 100644 --- a/pkg/services/annotations/annotationsimpl/loki/historian_store.go +++ b/pkg/services/annotations/annotationsimpl/loki/historian_store.go @@ -12,8 +12,6 @@ import ( "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/services/annotations/accesscontrol" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/services/ngalert" "github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/log" @@ -58,8 +56,8 @@ type LokiHistorianStore struct { ruleStore RuleStore } -func NewLokiHistorianStore(cfg setting.UnifiedAlertingStateHistorySettings, ft featuremgmt.FeatureToggles, db db.DB, ruleStore RuleStore, log log.Logger, tracer tracing.Tracer) *LokiHistorianStore { - if !useStore(cfg, ft) { +func NewLokiHistorianStore(cfg setting.UnifiedAlertingStateHistorySettings, db db.DB, ruleStore RuleStore, log log.Logger, tracer tracing.Tracer) *LokiHistorianStore { + if !useStore(cfg) { return nil } lokiCfg, err := historian.NewLokiConfig(cfg) @@ -294,22 +292,16 @@ func buildHistoryQuery(query *annotations.ItemQuery, dashboards map[string]int64 return historyQuery } -func useStore(cfg setting.UnifiedAlertingStateHistorySettings, ft featuremgmt.FeatureToggles) bool { +func useStore(cfg setting.UnifiedAlertingStateHistorySettings) bool { if !cfg.Enabled { return false } - // Override config based on feature toggles. - // We pass in a no-op logger here since this function is also called during ngalert init, - // and we don't want to log the same info twice. - ngalert.ApplyStateHistoryFeatureToggles(&cfg, ft, log.NewNopLogger()) - backend, err := historian.ParseBackendType(cfg.Backend) if err != nil { return false } // We should only query Loki if annotations do not exist in the database. - // To be doubly sure, ensure that the feature toggle to only use Loki is enabled. - return backend == historian.BackendTypeLoki && ft.IsEnabledGlobally(featuremgmt.FlagAlertStateHistoryLokiOnly) + return backend == historian.BackendTypeLoki } diff --git a/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go b/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go index 67ebca32918..feeaca62eee 100644 --- a/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go +++ b/pkg/services/annotations/annotationsimpl/loki/historian_store_test.go @@ -872,7 +872,7 @@ func TestUseStore(t *testing.T) { cfg := setting.UnifiedAlertingStateHistorySettings{ Enabled: false, } - use := useStore(cfg, featuremgmt.WithFeatures()) + use := useStore(cfg) require.False(t, use) }) @@ -882,7 +882,7 @@ func TestUseStore(t *testing.T) { Enabled: true, Backend: "invalid-backend", } - use := useStore(cfg, featuremgmt.WithFeatures()) + use := useStore(cfg) require.False(t, use) }) @@ -892,7 +892,7 @@ func TestUseStore(t *testing.T) { Backend: "multiple", MultiPrimary: "invalid-backend", } - use := useStore(cfg, featuremgmt.WithFeatures()) + use := useStore(cfg) require.False(t, use) }) @@ -903,7 +903,7 @@ func TestUseStore(t *testing.T) { MultiPrimary: "annotations", MultiSecondaries: []string{"annotations", "invalid-backend"}, } - use := useStore(cfg, featuremgmt.WithFeatures()) + use := useStore(cfg) require.False(t, use) }) }) @@ -913,7 +913,7 @@ func TestUseStore(t *testing.T) { Enabled: true, Backend: "annotations", } - use := useStore(cfg, featuremgmt.WithFeatures()) + use := useStore(cfg) require.False(t, use) }) @@ -924,7 +924,7 @@ func TestUseStore(t *testing.T) { Backend: "multiple", MultiPrimary: "loki", } - use := useStore(cfg, featuremgmt.WithFeatures()) + use := useStore(cfg) require.False(t, use) }) @@ -935,7 +935,7 @@ func TestUseStore(t *testing.T) { MultiPrimary: "annotations", MultiSecondaries: []string{"loki"}, } - use := useStore(cfg, featuremgmt.WithFeatures()) + use := useStore(cfg) require.False(t, use) }) }) @@ -946,12 +946,7 @@ func TestUseStore(t *testing.T) { Enabled: true, Backend: "loki", } - features := featuremgmt.WithFeatures( - featuremgmt.FlagAlertStateHistoryLokiOnly, - featuremgmt.FlagAlertStateHistoryLokiPrimary, - featuremgmt.FlagAlertStateHistoryLokiSecondary, - ) - use := useStore(cfg, features) + use := useStore(cfg) require.True(t, use) }) }) diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 527c8e69ec5..548e97d2838 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -235,24 +235,6 @@ var ( Stage: FeatureStageExperimental, Owner: grafanaObservabilityMetricsSquad, }, - { - Name: "alertStateHistoryLokiSecondary", - Description: "Enable Grafana to write alert state history to an external Loki instance in addition to Grafana annotations.", - Stage: FeatureStageExperimental, - Owner: grafanaAlertingSquad, - }, - { - Name: "alertStateHistoryLokiPrimary", - Description: "Enable a remote Loki instance as the primary source for state history reads.", - Stage: FeatureStageExperimental, - Owner: grafanaAlertingSquad, - }, - { - Name: "alertStateHistoryLokiOnly", - Description: "Disable Grafana alerts from emitting annotations when a remote Loki instance is available.", - Stage: FeatureStageExperimental, - Owner: grafanaAlertingSquad, - }, { Name: "unifiedRequestLog", Description: "Writes error logs to the request logger", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index da3238069fb..ee68232fc9e 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -29,9 +29,6 @@ prometheusRunQueriesInParallel,GA,@grafana/oss-big-tent,false,false,false lokiLogsDataplane,experimental,@grafana/observability-logs,false,false,false dataplaneFrontendFallback,GA,@grafana/observability-metrics,false,false,true disableSSEDataplane,experimental,@grafana/observability-metrics,false,false,false -alertStateHistoryLokiSecondary,experimental,@grafana/alerting-squad,false,false,false -alertStateHistoryLokiPrimary,experimental,@grafana/alerting-squad,false,false,false -alertStateHistoryLokiOnly,experimental,@grafana/alerting-squad,false,false,false unifiedRequestLog,GA,@grafana/grafana-backend-group,false,false,false renderAuthJWT,preview,@grafana/grafana-as-code,false,false,false refactorVariablesTimeRange,preview,@grafana/dashboards-squad,false,false,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 9a1a7fc945e..9da3b939f04 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -127,18 +127,6 @@ const ( // Disables dataplane specific processing in server side expressions. FlagDisableSSEDataplane = "disableSSEDataplane" - // FlagAlertStateHistoryLokiSecondary - // Enable Grafana to write alert state history to an external Loki instance in addition to Grafana annotations. - FlagAlertStateHistoryLokiSecondary = "alertStateHistoryLokiSecondary" - - // FlagAlertStateHistoryLokiPrimary - // Enable a remote Loki instance as the primary source for state history reads. - FlagAlertStateHistoryLokiPrimary = "alertStateHistoryLokiPrimary" - - // FlagAlertStateHistoryLokiOnly - // Disable Grafana alerts from emitting annotations when a remote Loki instance is available. - FlagAlertStateHistoryLokiOnly = "alertStateHistoryLokiOnly" - // FlagUnifiedRequestLog // Writes error logs to the request logger FlagUnifiedRequestLog = "unifiedRequestLog" diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 76c1e9604ab..c1851bad562 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -75,7 +75,8 @@ "metadata": { "name": "alertStateHistoryLokiOnly", "resourceVersion": "1743693517832", - "creationTimestamp": "2023-03-30T18:53:21Z" + "creationTimestamp": "2023-03-30T18:53:21Z", + "deletionTimestamp": "2025-04-07T14:33:12Z" }, "spec": { "description": "Disable Grafana alerts from emitting annotations when a remote Loki instance is available.", @@ -87,7 +88,8 @@ "metadata": { "name": "alertStateHistoryLokiPrimary", "resourceVersion": "1743693517832", - "creationTimestamp": "2023-03-30T18:53:21Z" + "creationTimestamp": "2023-03-30T18:53:21Z", + "deletionTimestamp": "2025-04-07T14:33:12Z" }, "spec": { "description": "Enable a remote Loki instance as the primary source for state history reads.", @@ -99,7 +101,8 @@ "metadata": { "name": "alertStateHistoryLokiSecondary", "resourceVersion": "1743693517832", - "creationTimestamp": "2023-03-30T18:53:21Z" + "creationTimestamp": "2023-03-30T18:53:21Z", + "deletionTimestamp": "2025-04-07T14:33:12Z" }, "spec": { "description": "Enable Grafana to write alert state history to an external Loki instance in addition to Grafana annotations.", diff --git a/pkg/services/ngalert/ngalert.go b/pkg/services/ngalert/ngalert.go index a01a3913752..69ef8ff5c90 100644 --- a/pkg/services/ngalert/ngalert.go +++ b/pkg/services/ngalert/ngalert.go @@ -398,9 +398,6 @@ func (ng *AlertNG) init() error { RecordingWriter: ng.RecordingWriter, } - // There are a set of feature toggles available that act as short-circuits for common configurations. - // If any are set, override the config accordingly. - ApplyStateHistoryFeatureToggles(&ng.Cfg.UnifiedAlerting.StateHistory, ng.FeatureToggles, ng.Log) history, err := configureHistorianBackend(initCtx, ng.Cfg.UnifiedAlerting.StateHistory, ng.annotationsRepo, ng.dashboardService, ng.store, ng.Metrics.GetHistorianMetrics(), ng.Log, ng.tracer, ac.NewRuleService(ng.accesscontrol)) if err != nil { return err @@ -704,51 +701,6 @@ func configureHistorianBackend(ctx context.Context, cfg setting.UnifiedAlertingS return nil, fmt.Errorf("unrecognized state history backend: %s", backend) } -// ApplyStateHistoryFeatureToggles edits state history configuration to comply with currently active feature toggles. -func ApplyStateHistoryFeatureToggles(cfg *setting.UnifiedAlertingStateHistorySettings, ft featuremgmt.FeatureToggles, logger log.Logger) { - backend, _ := historian.ParseBackendType(cfg.Backend) - // These feature toggles represent specific, common backend configurations. - // If all toggles are enabled, we listen to the state history config as written. - // If any of them are disabled, we ignore the configured backend and treat the toggles as an override. - // If multiple toggles are disabled, we go with the most "restrictive" one. - if !ft.IsEnabledGlobally(featuremgmt.FlagAlertStateHistoryLokiSecondary) { - // If we cannot even treat Loki as a secondary, we must use annotations only. - if backend == historian.BackendTypeMultiple || backend == historian.BackendTypeLoki { - logger.Info("Forcing Annotation backend due to state history feature toggles") - cfg.Backend = historian.BackendTypeAnnotations.String() - cfg.MultiPrimary = "" - cfg.MultiSecondaries = make([]string, 0) - } - return - } - if !ft.IsEnabledGlobally(featuremgmt.FlagAlertStateHistoryLokiPrimary) { - // If we're using multiple backends, Loki must be the secondary. - if backend == historian.BackendTypeMultiple { - logger.Info("Coercing Loki to a secondary backend due to state history feature toggles") - cfg.MultiPrimary = historian.BackendTypeAnnotations.String() - cfg.MultiSecondaries = []string{historian.BackendTypeLoki.String()} - } - // If we're using loki, we are only allowed to use it as a secondary. Dual write to it, plus annotations. - if backend == historian.BackendTypeLoki { - logger.Info("Coercing Loki to dual writes with a secondary backend due to state history feature toggles") - cfg.Backend = historian.BackendTypeMultiple.String() - cfg.MultiPrimary = historian.BackendTypeAnnotations.String() - cfg.MultiSecondaries = []string{historian.BackendTypeLoki.String()} - } - return - } - if !ft.IsEnabledGlobally(featuremgmt.FlagAlertStateHistoryLokiOnly) { - // If we're not allowed to use Loki only, make it the primary but keep the annotation writes. - if backend == historian.BackendTypeLoki { - logger.Info("Forcing dual writes to Loki and Annotations due to state history feature toggles") - cfg.Backend = historian.BackendTypeMultiple.String() - cfg.MultiPrimary = historian.BackendTypeLoki.String() - cfg.MultiSecondaries = []string{historian.BackendTypeAnnotations.String()} - } - return - } -} - func createRemoteAlertmanager(cfg remote.AlertmanagerConfig, kvstore kvstore.KVStore, decryptFn remote.DecryptFn, autogenFn remote.AutogenFn, m *metrics.RemoteAlertmanager, tracer tracing.Tracer) (*remote.Alertmanager, error) { return remote.NewAlertmanager(cfg, notifier.NewFileStore(cfg.OrgID, kvstore), decryptFn, autogenFn, m, tracer) } diff --git a/pkg/tests/alertmanager/alertmanager_scenario.go b/pkg/tests/alertmanager/alertmanager_scenario.go index 719cccef4ab..7855a111e40 100644 --- a/pkg/tests/alertmanager/alertmanager_scenario.go +++ b/pkg/tests/alertmanager/alertmanager_scenario.go @@ -269,9 +269,6 @@ func (s *AlertmanagerScenario) NewGrafanaService(name string, peers []string, pe flags := map[string]string{} ft := []string{ - "alertStateHistoryLokiSecondary", - "alertStateHistoryLokiPrimary", - "alertStateHistoryLokiOnly", "alertingAlertmanagerExtraDedupStage", } if stopOnExtraDedup {