use the default time retention value only when no size retention is set (#5216)

fixes https://github.com/prometheus/prometheus/issues/5213

Now that we have time and size base retention time bases should not have a default value. A default is set only when both - time and size flags are not set.

This change will not affect current installations that rely on the default time based value, and will avoid confusions when only the size retention is set and it is expected that the default time based setting would be no longer in place.

Signed-off-by: Krasi Georgiev <kgeorgie@redhat.com>
This commit is contained in:
Krasi Georgiev 2019-02-19 13:53:43 +02:00 committed by GitHub
parent 41dee81554
commit a3c41f4256
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 71 deletions

View File

@ -187,13 +187,13 @@ func main() {
Hidden().PlaceHolder("<bytes>").BytesVar(&cfg.tsdb.WALSegmentSize)
a.Flag("storage.tsdb.retention", "[DEPRECATED] How long to retain samples in storage. This flag has been deprecated, use \"storage.tsdb.retention.time\" instead").
Default(defaultRetentionString).SetValue(&oldFlagRetentionDuration)
SetValue(&oldFlagRetentionDuration)
a.Flag("storage.tsdb.retention.time", "How long to retain samples in storage. Overrides \"storage.tsdb.retention\" if this flag is set to anything other than default.").
Default(defaultRetentionString).SetValue(&newFlagRetentionDuration)
a.Flag("storage.tsdb.retention.time", "How long to retain samples in storage. When this flag is set it overrides \"storage.tsdb.retention\". If neither this flag nor \"storage.tsdb.retention\" nor \"storage.tsdb.retention.size\" is set, the retention time defaults to "+defaultRetentionString+".").
SetValue(&newFlagRetentionDuration)
a.Flag("storage.tsdb.retention.size", "[EXPERIMENTAL] Maximum number of bytes that can be stored for blocks. Units supported: KB, MB, GB, TB, PB. This flag is experimental and can be changed in future releases.").
Default("0").BytesVar(&cfg.tsdb.MaxBytes)
BytesVar(&cfg.tsdb.MaxBytes)
a.Flag("storage.tsdb.no-lockfile", "Do not create lockfile in data directory.").
Default("false").BoolVar(&cfg.tsdb.NoLockfile)
@ -245,6 +245,8 @@ func main() {
os.Exit(2)
}
logger := promlog.New(&cfg.promlogConfig)
cfg.web.ExternalURL, err = computeExternalURL(cfg.prometheusURL, cfg.web.ListenAddress)
if err != nil {
fmt.Fprintln(os.Stderr, errors.Wrapf(err, "parse external URL %q", cfg.prometheusURL))
@ -265,36 +267,46 @@ func main() {
// RoutePrefix must always be at least '/'.
cfg.web.RoutePrefix = "/" + strings.Trim(cfg.web.RoutePrefix, "/")
cfg.tsdb.RetentionDuration = chooseRetention(oldFlagRetentionDuration, newFlagRetentionDuration)
// Check for overflows. This limits our max retention to ~292.5y.
if cfg.tsdb.RetentionDuration < 0 {
cfg.tsdb.RetentionDuration = math.MaxInt64
}
if cfg.tsdb.MaxBlockDuration == 0 {
cfg.tsdb.MaxBlockDuration = cfg.tsdb.RetentionDuration / 10
// Prevent blocks from getting too big.
monthLong, err := model.ParseDuration("31d")
if err != nil {
panic(err)
{ // Time retention settings.
if oldFlagRetentionDuration != 0 {
level.Warn(logger).Log("deprecation_notice", "'storage.tsdb.retention' flag is deprecated use 'storage.tsdb.retention.time' instead.")
cfg.tsdb.RetentionDuration = oldFlagRetentionDuration
}
if cfg.tsdb.MaxBlockDuration > monthLong {
cfg.tsdb.MaxBlockDuration = monthLong
// When the new flag is set it takes precedence.
if newFlagRetentionDuration != 0 {
cfg.tsdb.RetentionDuration = newFlagRetentionDuration
}
if cfg.tsdb.RetentionDuration == 0 && cfg.tsdb.MaxBytes == 0 {
cfg.tsdb.RetentionDuration = defaultRetentionDuration
level.Info(logger).Log("msg", "no time or size retention was set so using the default time retention", "duration", defaultRetentionDuration)
}
// Check for overflows. This limits our max retention to ~292.5y.
if cfg.tsdb.RetentionDuration < 0 {
cfg.tsdb.RetentionDuration = math.MaxInt64
}
}
{ // Max block size settings.
if cfg.tsdb.MaxBlockDuration == 0 {
maxBlockDuration, err := model.ParseDuration("31d")
if err != nil {
panic(err)
}
// When the time retention is set and not too big use to define the max block duration.
if cfg.tsdb.RetentionDuration != 0 && cfg.tsdb.RetentionDuration/10 < maxBlockDuration {
maxBlockDuration = cfg.tsdb.RetentionDuration / 10
}
cfg.tsdb.MaxBlockDuration = maxBlockDuration
}
}
promql.LookbackDelta = time.Duration(cfg.lookbackDelta)
promql.SetDefaultEvaluationInterval(time.Duration(config.DefaultGlobalConfig.EvaluationInterval))
logger := promlog.New(&cfg.promlogConfig)
if oldFlagRetentionDuration != defaultRetentionDuration {
level.Warn(logger).Log("deprecation_notice", `"storage.tsdb.retention" flag is deprecated use "storage.tsdb.retention.time" instead.`)
}
// Above level 6, the k8s client would log bearer tokens in clear-text.
klog.ClampLevel(6)
klog.SetLogger(log.With(logger, "component", "k8s_client_runtime"))
@ -633,6 +645,14 @@ func main() {
return fmt.Errorf("opening storage failed: %s", err)
}
level.Info(logger).Log("msg", "TSDB started")
level.Debug(logger).Log("msg", "TSDB options",
"MinBlockDuration", cfg.tsdb.MinBlockDuration,
"MaxBlockDuration", cfg.tsdb.MaxBlockDuration,
"MaxBytes", cfg.tsdb.MaxBytes,
"NoLockfile", cfg.tsdb.NoLockfile,
"RetentionDuration", cfg.tsdb.RetentionDuration,
"WALSegmentSize", cfg.tsdb.WALSegmentSize,
)
startTimeMargin := int64(2 * time.Duration(cfg.tsdb.MinBlockDuration).Seconds() * 1000)
localStorage.Set(db, startTimeMargin)
@ -799,19 +819,3 @@ func sendAlerts(s sender, externalURL string) rules.NotifyFunc {
}
}
}
// chooseRetention is some roundabout code to support both RetentionDuration and Retention (for different flags).
// If Retention is 15d, then it means that the default value is set and the value of RetentionDuration is used.
func chooseRetention(oldFlagDuration, newFlagDuration model.Duration) model.Duration {
retention := oldFlagDuration
if retention == defaultRetentionDuration {
retention = newFlagDuration
}
// Further newFlag takes precedence if it's set to anything other than default.
if newFlagDuration != defaultRetentionDuration {
retention = newFlagDuration
}
return retention
}

View File

@ -25,7 +25,6 @@ import (
"testing"
"time"
"github.com/prometheus/common/model"
"github.com/prometheus/prometheus/notifier"
"github.com/prometheus/prometheus/pkg/labels"
"github.com/prometheus/prometheus/rules"
@ -285,31 +284,3 @@ func TestWALSegmentSizeBounds(t *testing.T) {
}
}
}
func TestChooseRetention(t *testing.T) {
retention1, err := model.ParseDuration("20d")
testutil.Ok(t, err)
retention2, err := model.ParseDuration("30d")
testutil.Ok(t, err)
cases := []struct {
oldFlagRetention model.Duration
newFlagRetention model.Duration
chosen model.Duration
}{
// Both are default (unset flags).
{defaultRetentionDuration, defaultRetentionDuration, defaultRetentionDuration},
// Old flag is set and new flag is unset.
{retention1, defaultRetentionDuration, retention1},
// Old flag is unset and new flag is set.
{defaultRetentionDuration, retention2, retention2},
// Both flags are set.
{retention1, retention2, retention2},
}
for _, tc := range cases {
retention := chooseRetention(tc.oldFlagRetention, tc.newFlagRetention)
testutil.Equals(t, tc.chosen, retention)
}
}