diff --git a/pkg/loki/runtime_config_test.go b/pkg/loki/runtime_config_test.go index 0ed35de32f..46ab13aa89 100644 --- a/pkg/loki/runtime_config_test.go +++ b/pkg/loki/runtime_config_test.go @@ -11,6 +11,7 @@ import ( "github.com/cortexproject/cortex/pkg/util/runtimeconfig" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/model" "github.com/prometheus/prometheus/pkg/labels" "github.com/stretchr/testify/require" @@ -45,10 +46,10 @@ overrides: require.Equal(t, 2*30*24*time.Hour, overrides.RetentionPeriod("29")) // overrides require.Equal(t, []validation.StreamRetention(nil), overrides.StreamRetention("1")) require.Equal(t, []validation.StreamRetention{ - {Period: 48 * time.Hour, Priority: 10, Selector: `{app="foo"}`, Matchers: []*labels.Matcher{ + {Period: model.Duration(48 * time.Hour), Priority: 10, Selector: `{app="foo"}`, Matchers: []*labels.Matcher{ labels.MustNewMatcher(labels.MatchEqual, "app", "foo"), }}, - {Period: 24 * time.Hour, Priority: 5, Selector: `{namespace="bar", cluster=~"fo.*|b.+|[1-2]"}`, Matchers: []*labels.Matcher{ + {Period: model.Duration(24 * time.Hour), Priority: 5, Selector: `{namespace="bar", cluster=~"fo.*|b.+|[1-2]"}`, Matchers: []*labels.Matcher{ labels.MustNewMatcher(labels.MatchEqual, "namespace", "bar"), labels.MustNewMatcher(labels.MatchRegexp, "cluster", "fo.*|b.+|[1-2]"), }}, @@ -78,7 +79,7 @@ overrides: period: 5h priority: 10 `)) - require.Equal(t, "invalid override for tenant 29: retention period must be >= 24h was 5h0m0s", err.Error()) + require.Equal(t, "invalid override for tenant 29: retention period must be >= 24h was 5h", err.Error()) } func newTestOverrides(t *testing.T, yaml string) *validation.Overrides { diff --git a/pkg/storage/stores/shipper/compactor/retention/expiration.go b/pkg/storage/stores/shipper/compactor/retention/expiration.go index 037c38b267..cbc8f8f51b 100644 --- a/pkg/storage/stores/shipper/compactor/retention/expiration.go +++ b/pkg/storage/stores/shipper/compactor/retention/expiration.go @@ -58,7 +58,7 @@ Outer: matchedRule = streamRetention } if found { - return now.Sub(ref.Through) > matchedRule.Period + return now.Sub(ref.Through) > time.Duration(matchedRule.Period) } return now.Sub(ref.Through) > globalRetention } diff --git a/pkg/storage/stores/shipper/compactor/retention/expiration_test.go b/pkg/storage/stores/shipper/compactor/retention/expiration_test.go index 8956fe9a3c..c14acf5914 100644 --- a/pkg/storage/stores/shipper/compactor/retention/expiration_test.go +++ b/pkg/storage/stores/shipper/compactor/retention/expiration_test.go @@ -32,12 +32,12 @@ func Test_expirationChecker_Expired(t *testing.T) { }, perStream: map[string][]validation.StreamRetention{ "1": { - {Period: 2 * time.Hour, Priority: 10, Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")}}, - {Period: 2 * time.Hour, Priority: 1, Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchRegexp, "foo", "ba.+")}}, + {Period: model.Duration(2 * time.Hour), Priority: 10, Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")}}, + {Period: model.Duration(2 * time.Hour), Priority: 1, Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchRegexp, "foo", "ba.+")}}, }, "2": { - {Period: 1 * time.Hour, Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")}}, - {Period: 2 * time.Hour, Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchRegexp, "foo", "ba.")}}, + {Period: model.Duration(1 * time.Hour), Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")}}, + {Period: model.Duration(2 * time.Hour), Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchRegexp, "foo", "ba.")}}, }, }, }) diff --git a/pkg/storage/stores/shipper/compactor/retention/retention_test.go b/pkg/storage/stores/shipper/compactor/retention/retention_test.go index d3bba96f23..4f2dae2e48 100644 --- a/pkg/storage/stores/shipper/compactor/retention/retention_test.go +++ b/pkg/storage/stores/shipper/compactor/retention/retention_test.go @@ -78,7 +78,7 @@ func Test_Retention(t *testing.T) { }, perStream: map[string][]validation.StreamRetention{ "1": { - {Period: 5 * time.Hour, Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "buzz")}}, + {Period: model.Duration(5 * time.Hour), Matchers: []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "buzz")}}, }, }, }, diff --git a/pkg/validation/limits.go b/pkg/validation/limits.go index 92ebfd1273..d97cef3dfa 100644 --- a/pkg/validation/limits.go +++ b/pkg/validation/limits.go @@ -65,7 +65,7 @@ type Limits struct { RulerMaxRuleGroupsPerTenant int `yaml:"ruler_max_rule_groups_per_tenant" json:"ruler_max_rule_groups_per_tenant"` // Global and per tenant retention - RetentionPeriod time.Duration `yaml:"retention_period" json:"retention_period"` + RetentionPeriod model.Duration `yaml:"retention_period" json:"retention_period"` StreamRetention []StreamRetention `yaml:"retention_stream" json:"retention_stream"` // Config for overrides, convenient if it goes here. @@ -74,10 +74,10 @@ type Limits struct { } type StreamRetention struct { - Period time.Duration `yaml:"period"` - Priority int `yaml:"priority"` - Selector string `yaml:"selector"` - Matchers []*labels.Matcher `yaml:"-"` // populated during validation. + Period model.Duration `yaml:"period" json:"period"` + Priority int `yaml:"priority" json:"priority"` + Selector string `yaml:"selector" json:"selector"` + Matchers []*labels.Matcher `yaml:"-" json:"-"` // populated during validation. } // RegisterFlags adds the flags required to config this to the given FlagSet @@ -124,7 +124,8 @@ func (l *Limits) RegisterFlags(f *flag.FlagSet) { f.IntVar(&l.RulerMaxRuleGroupsPerTenant, "ruler.max-rule-groups-per-tenant", 0, "Maximum number of rule groups per-tenant. 0 to disable.") f.StringVar(&l.PerTenantOverrideConfig, "limits.per-user-override-config", "", "File name of per-user overrides.") - f.DurationVar(&l.RetentionPeriod, "store.retention", 31*24*time.Hour, "How long before chunks will be deleted from the store. (requires compactor retention enabled).") + _ = l.RetentionPeriod.Set("744h") + f.Var(&l.RetentionPeriod, "store.retention", "How long before chunks will be deleted from the store. (requires compactor retention enabled).") _ = l.PerTenantOverridePeriod.Set("10s") f.Var(&l.PerTenantOverridePeriod, "limits.per-user-override-period", "Period with this to reload the overrides.") @@ -152,7 +153,7 @@ func (l *Limits) Validate() error { if err != nil { return fmt.Errorf("invalid labels matchers: %w", err) } - if rule.Period < 24*time.Hour { + if time.Duration(rule.Period) < 24*time.Hour { return fmt.Errorf("retention period must be >= 24h was %s", rule.Period) } // populate matchers during validation @@ -355,7 +356,7 @@ func (o *Overrides) RulerMaxRuleGroupsPerTenant(userID string) int { // RetentionPeriod returns the retention period for a given user. func (o *Overrides) RetentionPeriod(userID string) time.Duration { - return o.getOverridesForUser(userID).RetentionPeriod + return time.Duration(o.getOverridesForUser(userID).RetentionPeriod) } // RetentionPeriod returns the retention period for a given user.