From dcfa1b96c6f8c306286e1ec486aae1e8cfbdca34 Mon Sep 17 00:00:00 2001 From: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:16:09 +0100 Subject: [PATCH 1/5] config: validate TSDB retention settings during config parsing Move retention validation from tsdb/db.go into a TSDBRetentionConfig UnmarshalYAML method so that invalid values are rejected at config load/reload time rather than at apply time. - Reject negative retention size values. - Reject retention percentage values above 100. - Simplify ApplyConfig to assign retention values unconditionally, enabling setting a value back to 0 to disable it. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> --- config/config.go | 16 ++++++++++++++++ config/config_test.go | 16 ++++++++++++++++ .../testdata/tsdb_retention_percentage.bad.yml | 4 ++++ .../tsdb_retention_percentage_negative.bad.yml | 4 ++++ config/testdata/tsdb_retention_size.bad.yml | 4 ++++ config/testdata/tsdb_retention_time.bad.yml | 4 ++++ tsdb/db.go | 18 ++++++------------ 7 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 config/testdata/tsdb_retention_percentage.bad.yml create mode 100644 config/testdata/tsdb_retention_percentage_negative.bad.yml create mode 100644 config/testdata/tsdb_retention_size.bad.yml create mode 100644 config/testdata/tsdb_retention_time.bad.yml diff --git a/config/config.go b/config/config.go index 0ebebc26d5..9da37c48b0 100644 --- a/config/config.go +++ b/config/config.go @@ -1097,6 +1097,22 @@ type TSDBRetentionConfig struct { Percentage uint `yaml:"percentage,omitempty"` } +// UnmarshalYAML implements the yaml.Unmarshaler interface. +func (t *TSDBRetentionConfig) UnmarshalYAML(unmarshal func(any) error) error { + *t = TSDBRetentionConfig{} + type plain TSDBRetentionConfig + if err := unmarshal((*plain)(t)); err != nil { + return err + } + if t.Size < 0 { + return fmt.Errorf("'storage.tsdb.retention.size' must be greater than or equal to 0, got %v", t.Size) + } + if t.Percentage > 100 { + return fmt.Errorf("'storage.tsdb.retention.percentage' must be in the range [0, 100], got %v", t.Percentage) + } + return nil +} + // TSDBConfig configures runtime reloadable configuration options. type TSDBConfig struct { // OutOfOrderTimeWindow sets how long back in time an out-of-order sample can be inserted diff --git a/config/config_test.go b/config/config_test.go index 43c56a501f..91e29259ef 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -2626,6 +2626,22 @@ var expectedErrors = []struct { filename: "stackit_endpoint.bad.yml", errMsg: "invalid endpoint", }, + { + filename: "tsdb_retention_time.bad.yml", + errMsg: `not a valid duration string: "-1h"`, + }, + { + filename: "tsdb_retention_size.bad.yml", + errMsg: `'storage.tsdb.retention.size' must be greater than or equal to 0`, + }, + { + filename: "tsdb_retention_percentage.bad.yml", + errMsg: `'storage.tsdb.retention.percentage' must be in the range [0, 100]`, + }, + { + filename: "tsdb_retention_percentage_negative.bad.yml", + errMsg: "cannot unmarshal !!int `-1` into uint", + }, } func TestBadConfigs(t *testing.T) { diff --git a/config/testdata/tsdb_retention_percentage.bad.yml b/config/testdata/tsdb_retention_percentage.bad.yml new file mode 100644 index 0000000000..cb57abe0c0 --- /dev/null +++ b/config/testdata/tsdb_retention_percentage.bad.yml @@ -0,0 +1,4 @@ +storage: + tsdb: + retention: + percentage: 101 diff --git a/config/testdata/tsdb_retention_percentage_negative.bad.yml b/config/testdata/tsdb_retention_percentage_negative.bad.yml new file mode 100644 index 0000000000..2eeb60c091 --- /dev/null +++ b/config/testdata/tsdb_retention_percentage_negative.bad.yml @@ -0,0 +1,4 @@ +storage: + tsdb: + retention: + percentage: -1 diff --git a/config/testdata/tsdb_retention_size.bad.yml b/config/testdata/tsdb_retention_size.bad.yml new file mode 100644 index 0000000000..ecae64aae6 --- /dev/null +++ b/config/testdata/tsdb_retention_size.bad.yml @@ -0,0 +1,4 @@ +storage: + tsdb: + retention: + size: -1GB diff --git a/config/testdata/tsdb_retention_time.bad.yml b/config/testdata/tsdb_retention_time.bad.yml new file mode 100644 index 0000000000..465b3cf5da --- /dev/null +++ b/config/testdata/tsdb_retention_time.bad.yml @@ -0,0 +1,4 @@ +storage: + tsdb: + retention: + time: -1h diff --git a/tsdb/db.go b/tsdb/db.go index a5abc8fed9..ff1d6876d6 100644 --- a/tsdb/db.go +++ b/tsdb/db.go @@ -1277,18 +1277,12 @@ func (db *DB) ApplyConfig(conf *config.Config) error { // Update retention configuration if provided. if conf.StorageConfig.TSDBConfig.Retention != nil { db.retentionMtx.Lock() - if conf.StorageConfig.TSDBConfig.Retention.Time > 0 { - db.opts.RetentionDuration = int64(conf.StorageConfig.TSDBConfig.Retention.Time) - db.metrics.retentionDuration.Set((time.Duration(db.opts.RetentionDuration) * time.Millisecond).Seconds()) - } - if conf.StorageConfig.TSDBConfig.Retention.Size > 0 { - db.opts.MaxBytes = int64(conf.StorageConfig.TSDBConfig.Retention.Size) - db.metrics.maxBytes.Set(float64(db.opts.MaxBytes)) - } - if conf.StorageConfig.TSDBConfig.Retention.Percentage > 0 { - db.opts.MaxPercentage = conf.StorageConfig.TSDBConfig.Retention.Percentage - db.metrics.maxPercentage.Set(float64(db.opts.MaxPercentage)) - } + db.opts.RetentionDuration = int64(conf.StorageConfig.TSDBConfig.Retention.Time) + db.metrics.retentionDuration.Set((time.Duration(db.opts.RetentionDuration) * time.Millisecond).Seconds()) + db.opts.MaxBytes = int64(conf.StorageConfig.TSDBConfig.Retention.Size) + db.metrics.maxBytes.Set(float64(db.opts.MaxBytes)) + db.opts.MaxPercentage = conf.StorageConfig.TSDBConfig.Retention.Percentage + db.metrics.maxPercentage.Set(float64(db.opts.MaxPercentage)) db.retentionMtx.Unlock() } } else { From bf3c217bbdaec1163588384270d872e024f41738 Mon Sep 17 00:00:00 2001 From: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:36:05 +0100 Subject: [PATCH 2/5] config: apply retention CLI flags as defaults and update UI on reload Introduce DefaultTSDBRetentionConfig, populated from CLI flags before any config file is loaded, so that retention falls back to CLI flags when the config file has no storage.tsdb section. Config.UnmarshalYAML always injects a non-nil TSDBConfig with those defaults, removing the need for nil checks in main.go. ApplyConfig in web.go now propagates retention settings on each config reload so the runtime info endpoint stays up to date. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> --- cmd/prometheus/main.go | 37 ++++++++++++++++------------------- config/config.go | 15 ++++++++++++++ config/config_default_test.go | 7 ++++--- config/config_test.go | 4 ++++ config/config_windows_test.go | 5 +++-- web/web.go | 22 +++++++++++++++------ 6 files changed, 59 insertions(+), 31 deletions(-) diff --git a/cmd/prometheus/main.go b/cmd/prometheus/main.go index debff1f6af..dfafd0902a 100644 --- a/cmd/prometheus/main.go +++ b/cmd/prometheus/main.go @@ -666,6 +666,18 @@ func main() { os.Exit(2) } + // Set TSDB retention defaults from CLI flags before any config file is loaded. + // This makes CLI flags act as the default when no retention section is present. + cliRetentionDuration := cfg.tsdb.RetentionDuration + cliMaxBytes := cfg.tsdb.MaxBytes + if cliRetentionDuration == 0 && cliMaxBytes == 0 { + cliRetentionDuration = defaultRetentionDuration + } + config.DefaultTSDBRetentionConfig = config.TSDBRetentionConfig{ + Time: cliRetentionDuration, + Size: cliMaxBytes, + } + // Throw error for invalid config before starting other components. var cfgFile *config.Config if cfgFile, err = config.LoadFile(cfg.configFile, agentMode, promslog.NewNopLogger()); err != nil { @@ -707,21 +719,11 @@ func main() { logger.Warn("The option --storage.tsdb.block-reload-interval is set to a value less than 1s. Setting it to 1s to avoid overload.") cfg.tsdb.BlockReloadInterval = model.Duration(1 * time.Second) } - if cfgFile.StorageConfig.TSDBConfig != nil { - cfg.tsdb.OutOfOrderTimeWindow = cfgFile.StorageConfig.TSDBConfig.OutOfOrderTimeWindow - cfg.tsdb.StaleSeriesCompactionThreshold = cfgFile.StorageConfig.TSDBConfig.StaleSeriesCompactionThreshold - if cfgFile.StorageConfig.TSDBConfig.Retention != nil { - if cfgFile.StorageConfig.TSDBConfig.Retention.Time > 0 { - cfg.tsdb.RetentionDuration = cfgFile.StorageConfig.TSDBConfig.Retention.Time - } - if cfgFile.StorageConfig.TSDBConfig.Retention.Size > 0 { - cfg.tsdb.MaxBytes = cfgFile.StorageConfig.TSDBConfig.Retention.Size - } - if cfgFile.StorageConfig.TSDBConfig.Retention.Percentage > 0 { - cfg.tsdb.MaxPercentage = cfgFile.StorageConfig.TSDBConfig.Retention.Percentage - } - } - } + cfg.tsdb.OutOfOrderTimeWindow = cfgFile.StorageConfig.TSDBConfig.OutOfOrderTimeWindow + cfg.tsdb.StaleSeriesCompactionThreshold = cfgFile.StorageConfig.TSDBConfig.StaleSeriesCompactionThreshold + cfg.tsdb.RetentionDuration = cfgFile.StorageConfig.TSDBConfig.Retention.Time + cfg.tsdb.MaxBytes = cfgFile.StorageConfig.TSDBConfig.Retention.Size + cfg.tsdb.MaxPercentage = cfgFile.StorageConfig.TSDBConfig.Retention.Percentage // Set Go runtime parameters before we get too far into initialization. updateGoGC(cfgFile, logger) @@ -773,11 +775,6 @@ func main() { cfg.web.RoutePrefix = "/" + strings.Trim(cfg.web.RoutePrefix, "/") if !agentMode { - if cfg.tsdb.RetentionDuration == 0 && cfg.tsdb.MaxBytes == 0 && cfg.tsdb.MaxPercentage == 0 { - cfg.tsdb.RetentionDuration = defaultRetentionDuration - logger.Info("No time, size or percentage retention was set so using the default time retention", "duration", defaultRetentionDuration) - } - // Check for overflows. This limits our max retention to 100y. if cfg.tsdb.RetentionDuration < 0 { y, err := model.ParseDuration("100y") diff --git a/config/config.go b/config/config.go index 9da37c48b0..2ccca31b4f 100644 --- a/config/config.go +++ b/config/config.go @@ -278,6 +278,9 @@ var ( } ) +// DefaultTSDBRetentionConfig is the default TSDB retention configuration. +var DefaultTSDBRetentionConfig TSDBRetentionConfig + // Config is the top-level configuration for Prometheus's config files. type Config struct { GlobalConfig GlobalConfig `yaml:"global"` @@ -405,6 +408,13 @@ func (c *Config) UnmarshalYAML(unmarshal func(any) error) error { c.Runtime = DefaultRuntimeConfig } + // If no storage.tsdb section is present, TSDBConfig is nil and its + // UnmarshalYAML never runs. Inject the default retention here. + if c.StorageConfig.TSDBConfig == nil { + retention := DefaultTSDBRetentionConfig + c.StorageConfig.TSDBConfig = &TSDBConfig{Retention: &retention} + } + for _, rf := range c.RuleFiles { if !patRulePath.MatchString(rf) { return fmt.Errorf("invalid rule file path %q", rf) @@ -1143,6 +1153,11 @@ func (t *TSDBConfig) UnmarshalYAML(unmarshal func(any) error) error { t.OutOfOrderTimeWindow = time.Duration(t.OutOfOrderTimeWindowFlag).Milliseconds() + if t.Retention == nil { + retention := DefaultTSDBRetentionConfig + t.Retention = &retention + } + return nil } diff --git a/config/config_default_test.go b/config/config_default_test.go index 91c290ae4e..ec7a112824 100644 --- a/config/config_default_test.go +++ b/config/config_default_test.go @@ -20,9 +20,10 @@ const ruleFilesConfigFile = "testdata/rules_abs_path.good.yml" var ruleFilesExpectedConf = &Config{ loaded: true, - GlobalConfig: DefaultGlobalConfig, - Runtime: DefaultRuntimeConfig, - OTLPConfig: DefaultOTLPConfig, + GlobalConfig: DefaultGlobalConfig, + Runtime: DefaultRuntimeConfig, + OTLPConfig: DefaultOTLPConfig, + StorageConfig: StorageConfig{TSDBConfig: &TSDBConfig{Retention: &TSDBRetentionConfig{}}}, RuleFiles: []string{ "testdata/first.rules", "testdata/rules/second.rules", diff --git a/config/config_test.go b/config/config_test.go index 91e29259ef..dbc221329d 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -2716,6 +2716,10 @@ func TestGlobalConfig(t *testing.T) { require.NoError(t, err) exp := DefaultConfig exp.loaded = true + // TSDBConfig is always injected by Config.UnmarshalYAML even when no + // storage.tsdb section is present, so the expected config must include it. + retention := DefaultTSDBRetentionConfig + exp.StorageConfig.TSDBConfig = &TSDBConfig{Retention: &retention} require.Equal(t, exp, *c) }) diff --git a/config/config_windows_test.go b/config/config_windows_test.go index 72a56ff41a..e7627f562a 100644 --- a/config/config_windows_test.go +++ b/config/config_windows_test.go @@ -18,8 +18,9 @@ const ruleFilesConfigFile = "testdata/rules_abs_path_windows.good.yml" var ruleFilesExpectedConf = &Config{ loaded: true, - GlobalConfig: DefaultGlobalConfig, - Runtime: DefaultRuntimeConfig, + GlobalConfig: DefaultGlobalConfig, + Runtime: DefaultRuntimeConfig, + StorageConfig: StorageConfig{TSDBConfig: &TSDBConfig{Retention: &TSDBRetentionConfig{}}}, RuleFiles: []string{ "testdata\\first.rules", "testdata\\rules\\second.rules", diff --git a/web/web.go b/web/web.go index 90eaf13afe..c4fcfdb2c4 100644 --- a/web/web.go +++ b/web/web.go @@ -253,6 +253,11 @@ func (h *Handler) ApplyConfig(conf *config.Config) error { defer h.mtx.Unlock() h.config = conf + if conf.StorageConfig.TSDBConfig != nil && conf.StorageConfig.TSDBConfig.Retention != nil { + h.options.TSDBRetentionDuration = conf.StorageConfig.TSDBConfig.Retention.Time + h.options.TSDBMaxBytes = conf.StorageConfig.TSDBConfig.Retention.Size + h.options.TSDBMaxPercentage = conf.StorageConfig.TSDBConfig.Retention.Percentage + } return nil } @@ -866,20 +871,25 @@ func (h *Handler) runtimeInfo() (api_v1.RuntimeInfo, error) { status.Hostname = hostname status.ServerTime = time.Now().UTC() - if h.options.TSDBRetentionDuration != 0 { - status.StorageRetention = h.options.TSDBRetentionDuration.String() + h.mtx.RLock() + tsdbRetentionDuration := h.options.TSDBRetentionDuration + tsdbMaxBytes := h.options.TSDBMaxBytes + tsdbMaxPercentage := h.options.TSDBMaxPercentage + h.mtx.RUnlock() + if tsdbRetentionDuration != 0 { + status.StorageRetention = tsdbRetentionDuration.String() } - if h.options.TSDBMaxBytes != 0 { + if tsdbMaxBytes != 0 { if status.StorageRetention != "" { status.StorageRetention += " or " } - status.StorageRetention += h.options.TSDBMaxBytes.String() + status.StorageRetention += tsdbMaxBytes.String() } - if h.options.TSDBMaxPercentage != 0 { + if tsdbMaxPercentage != 0 { if status.StorageRetention != "" { status.StorageRetention += " or " } - status.StorageRetention = status.StorageRetention + strconv.FormatUint(uint64(h.options.TSDBMaxPercentage), 10) + "%" + status.StorageRetention = status.StorageRetention + strconv.FormatUint(uint64(tsdbMaxPercentage), 10) + "%" } metrics, err := h.gatherer.Gather() From 3675a5e56c86ef09f8bb35d93a05012c381b1445 Mon Sep 17 00:00:00 2001 From: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:41:34 +0100 Subject: [PATCH 3/5] tsdb: fix unit mismatch in retention duration on config reload conf.StorageConfig.TSDBConfig.Retention.Time is model.Duration which is type-aliased to time.Duration (nanoseconds), but RetentionDuration is int64 in milliseconds. The missing division by time.Millisecond caused the metric prometheus_tsdb_retention_limit_seconds to be reported 1e6 times too large after a config reload. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> --- tsdb/db.go | 2 +- tsdb/db_test.go | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/tsdb/db.go b/tsdb/db.go index ff1d6876d6..0e92c2b70e 100644 --- a/tsdb/db.go +++ b/tsdb/db.go @@ -1277,7 +1277,7 @@ func (db *DB) ApplyConfig(conf *config.Config) error { // Update retention configuration if provided. if conf.StorageConfig.TSDBConfig.Retention != nil { db.retentionMtx.Lock() - db.opts.RetentionDuration = int64(conf.StorageConfig.TSDBConfig.Retention.Time) + db.opts.RetentionDuration = int64(time.Duration(conf.StorageConfig.TSDBConfig.Retention.Time) / time.Millisecond) db.metrics.retentionDuration.Set((time.Duration(db.opts.RetentionDuration) * time.Millisecond).Seconds()) db.opts.MaxBytes = int64(conf.StorageConfig.TSDBConfig.Retention.Size) db.metrics.maxBytes.Set(float64(db.opts.MaxBytes)) diff --git a/tsdb/db_test.go b/tsdb/db_test.go index bd868d945a..be914cd87d 100644 --- a/tsdb/db_test.go +++ b/tsdb/db_test.go @@ -1743,7 +1743,7 @@ func TestRuntimeRetentionConfigChange(t *testing.T) { StorageConfig: config.StorageConfig{ TSDBConfig: &config.TSDBConfig{ Retention: &config.TSDBRetentionConfig{ - Time: model.Duration(shorterRetentionDuration), + Time: model.Duration(time.Duration(shorterRetentionDuration) * time.Millisecond), }, }, }, @@ -1772,6 +1772,31 @@ func TestRuntimeRetentionConfigChange(t *testing.T) { require.Positive(t, int(prom_testutil.ToFloat64(db.metrics.timeRetentionCount)), "time retention count should be incremented") } +// TestApplyConfigRetentionDurationMetricUnit verifies that after a config +// reload the prometheus_tsdb_retention_limit_seconds metric reports the +// retention in seconds. +func TestApplyConfigRetentionDurationMetricUnit(t *testing.T) { + oneHourMs := int64(time.Hour / time.Millisecond) + db := newTestDB(t, withOpts(&Options{RetentionDuration: oneHourMs})) + + cfg := &config.Config{ + StorageConfig: config.StorageConfig{ + TSDBConfig: &config.TSDBConfig{ + Retention: &config.TSDBRetentionConfig{ + Time: model.Duration(time.Hour), + }, + }, + }, + } + require.NoError(t, db.ApplyConfig(cfg)) + + require.Equal(t, oneHourMs, db.getRetentionDuration()) + + gotSeconds := prom_testutil.ToFloat64(db.metrics.retentionDuration) + wantSeconds := time.Hour.Seconds() + require.Equal(t, wantSeconds, gotSeconds) +} + func TestNotMatcherSelectsLabelsUnsetSeries(t *testing.T) { db := newTestDB(t) From 8edc676cbe73b348386ce5db0272dff72ccead76 Mon Sep 17 00:00:00 2001 From: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:59:21 +0100 Subject: [PATCH 4/5] config: inject TSDBConfig defaults in Load for empty config bodies When the config body is empty, UnmarshalYAML is never called, so the TSDBConfig nil injection added there never ran. Replicate the same guard in Load, which is the entry point that already handles this case for other defaults via DefaultConfig. Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> --- config/config.go | 7 +++++++ config/config_test.go | 2 ++ 2 files changed, 9 insertions(+) diff --git a/config/config.go b/config/config.go index 2ccca31b4f..cb45347e41 100644 --- a/config/config.go +++ b/config/config.go @@ -83,6 +83,13 @@ func Load(s string, logger *slog.Logger) (*Config, error) { return nil, err } + // When the config body is empty, UnmarshalYAML is never called, so + // TSDBConfig may still be nil. + if cfg.StorageConfig.TSDBConfig == nil { + retention := DefaultTSDBRetentionConfig + cfg.StorageConfig.TSDBConfig = &TSDBConfig{Retention: &retention} + } + b := labels.NewScratchBuilder(0) cfg.GlobalConfig.ExternalLabels.Range(func(v labels.Label) { newV := os.Expand(v.Value, func(s string) string { diff --git a/config/config_test.go b/config/config_test.go index dbc221329d..a845fac719 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -2665,6 +2665,8 @@ func TestEmptyConfig(t *testing.T) { require.NoError(t, err) exp := DefaultConfig exp.loaded = true + retention := DefaultTSDBRetentionConfig + exp.StorageConfig.TSDBConfig = &TSDBConfig{Retention: &retention} require.Equal(t, exp, *c) require.Equal(t, 75, c.Runtime.GoGC) } From 1064c26da2177be7200584e7ab0548604c9d4d14 Mon Sep 17 00:00:00 2001 From: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:37:01 +0100 Subject: [PATCH 5/5] Log retention changes Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com> --- cmd/prometheus/main.go | 25 +++++++++++++++++++++++-- config/config.go | 6 +++--- docs/configuration/configuration.md | 4 ++-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/cmd/prometheus/main.go b/cmd/prometheus/main.go index dfafd0902a..b036b0d316 100644 --- a/cmd/prometheus/main.go +++ b/cmd/prometheus/main.go @@ -1020,8 +1020,29 @@ func main() { reloaders := []reloader{ { - name: "db_storage", - reloader: localStorage.ApplyConfig, + name: "db_storage", + reloader: func() func(*config.Config) error { + lastTSDBRetention := config.TSDBRetentionConfig{} + return func(cfg *config.Config) error { + err := localStorage.ApplyConfig(cfg) + if err != nil || agentMode || cfg.StorageConfig.TSDBConfig == nil || cfg.StorageConfig.TSDBConfig.Retention == nil { + return err + } + + curr := cfg.StorageConfig.TSDBConfig.Retention + if *curr == lastTSDBRetention { + return nil + } + + logger.Info("TSDB retention updated", + "duration", curr.Time, + "size", curr.Size, + "percentage", curr.Percentage, + ) + lastTSDBRetention = *curr + return nil + } + }(), }, { name: "remote_storage", reloader: remoteStorage.ApplyConfig, diff --git a/config/config.go b/config/config.go index cb45347e41..469ffe10a6 100644 --- a/config/config.go +++ b/config/config.go @@ -283,10 +283,10 @@ var ( // For backwards compatibility. LabelNamePreserveMultipleUnderscores: true, } -) -// DefaultTSDBRetentionConfig is the default TSDB retention configuration. -var DefaultTSDBRetentionConfig TSDBRetentionConfig + // DefaultTSDBRetentionConfig is the default TSDB retention configuration. + DefaultTSDBRetentionConfig TSDBRetentionConfig +) // Config is the top-level configuration for Prometheus's config files. type Config struct { diff --git a/docs/configuration/configuration.md b/docs/configuration/configuration.md index 060319ae92..4792d4fed2 100644 --- a/docs/configuration/configuration.md +++ b/docs/configuration/configuration.md @@ -3686,9 +3686,9 @@ with this feature. # or when a compaction completes, whichever comes first. [ retention: ] : # How long to retain samples in storage. If neither this option nor the size option - # is set, the retention time defaults to 15d. Units Supported: y, w, d, h, m, s, ms. + # is set, the retention time defaults to 15d. Setting this to 0 disables time-based retention. # This option takes precedence over the deprecated command-line flag --storage.tsdb.retention.time. - [ time: | default = 15d ] + [ time: ] # Maximum number of bytes that can be stored for blocks. A unit is required, # supported units: B, KB, MB, GB, TB, PB, EB. Ex: "512MB". Based on powers-of-2, so 1KB is 1024B.