New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactored limits to be able to define them dynamically when Cortex is vendored in another project #1549
Refactored limits to be able to define them dynamically when Cortex is vendored in another project #1549
Conversation
Can you say a bit more about what has been done in the 800 lines of changes? |
Exact usecase is being able to manage limits in Loki using same code as cortex. Loki uses some of the limits from Cortex and few additional ones specific to Loki. |
For instance, it looks like you changed the package name "validation" to "limits". |
Actually, I wrote a new package with the name "limits" because most of its use case was managing and accessing limits. I had copied parts of code from the previous package so it looks like just a rename.
Sure will do and will make sure I take care of them going forward. Sorry about that. |
This isn't about the name, it's about you explaining what you did so it can be reviewed. |
4daad2a
to
db44840
Compare
@bboreham renamed and refactored the code to make the changes minimal. Please let me know if it looks good or whether I can do any more improvements to it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@bboreham @tomwilkie Can you please have a look at this and suggest any changes if required to get another approval? |
As discussed offline, not super happy with the amount of strings here. Quick sketch of an alternative: package foo
type Limits interface {
RegisterFlags()
UnmarhsalYAML()
}
type Overrides struct {
factory func() Limits
defaults Limits
overrides map[string]Limits
}
func (o Overrides) register() {]}
o.defaults = o.factory()
o.defaults.RegisterFlags()
}
func (o *Overrides) getFloat64(userID string, f func(*Limits) float64) float64 {
o.overridesMtx.RLock()
defer o.overridesMtx.RUnlock()
override, ok := o.overrides[userID]
if !ok {
return f(&o.Defaults)
}
return f(override)
}
func loop() {
// load the overrides file in the map above.
}
// Cortex
type CortexLimits struct {
IngestionRate float64 `yaml:"ingestion_rate"`
...
}
type CortexOverrider struct {
Overrides
}
func (o *CortexOverrider) IngestionRate(userID string) float64 {
return o.getFloat64(userID, func(l *Limits) float64 {
cl := l.(CortexLimits)
return l.IngestionRate
})
}
// Loki
type LokiLimits struct {
....
}
type LokiOverrider astruct {
Overrides
} |
8e4a1c0
to
8ab3339
Compare
@@ -73,7 +76,172 @@ func (l *Limits) UnmarshalYAML(unmarshal func(interface{}) error) error { | |||
// We want to set c to the defaults and then overwrite it with the input. | |||
// To make unmarshal fill the plain data struct rather than calling UnmarshalYAML | |||
// again, we have to hide it using a type indirection. See prometheus/config. | |||
*l = defaultLimits | |||
if defaultLimits != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this values were getting reset to 0 while loading cortex config which had just per tenant overrides config path set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did this not happen before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sandlis explained offline:
- we init the flags, which sets up the default in a Limits struct in
cortex
pkg. - we then load YAML, which will overwrite them with 0s, as
defaultLimits
has not been inited. - we Parse the flags, which set only ones we've specifices
- we then set this
defaultLimits
to the half-zero'd struct.
…g in Cortex Added OverridesManager which would store default limits and per tenant overrides as an interface Factory method for creating OverridesManager accepts overrides reload config, method to load overrides from yaml file and default limit Sample and Labels validation methods now accept any type which implement required methods to get required limits for validation Signed-off-by: Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
Signed-off-by: Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
Signed-off-by: Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
45c8c9f
to
735da12
Compare
Signed-off-by: Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM besides comment. Will take another pass though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
pkg/util/validation/override.go
Outdated
if err != nil { | ||
return nil, err | ||
// NewOverridesManager creates an instance of OverridesManager and starts reload overrides loop based on config | ||
func NewOverridesManager(perTenantOverridePeriod time.Duration, overridesReloadPath string, overridesLoader OverridesLoader, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be nicer as a config struct, not individual args.
Signed-off-by: Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
@tomwilkie Thanks for the review! Done the suggested changes. |
} | ||
|
||
return overridesAsInterface, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this take a "factory" for the Limits
type? Then have the code to make a map vs the defaults would be in override.go.
I think this is possible with yaml.v3
and Node
: https://godoc.org/gopkg.in/yaml.v3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline, Node.Decode
doesn't honour KnownFields
: go-yaml/yaml#460
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is looking much better. Just a couple of nits, should be able to merge really soon now.
…ug in yamlv3 decoder is fixed Signed-off-by: Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
This would be useful to define limits specific to Loki while still being able to use the same code for managing limits and per tenant overwrites.
Changes include:
Signed-off-by: Sandeep Sukhani sandeep.d.sukhani@gmail.com