-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
Add the shared state to the global scope to get previous data #8447
Conversation
While the code looks good, I'm not sure this is actually a good thing to do. There are multiple reasons IMO:
@ssoroka what is your opinion on this? |
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.
Code review, will respond to the other comments separately.
Generally they are as most inputs place them in order and Telegraf keeps them in order, but you're right that it's not a guarantee. It depends on the setup. Other than the complexity, I think storing a set of metrics should still work.
I considered that, but it might be better for avoiding bugs to make it explicit.
Processing over multiple metrics with batches doesn't really work (where do you draw that batch border, what if you need a metric outside that grouping?). In the future all aggregators are probably going to be reimplemented as processors (likely transparently), as processors + state are exactly aggregators. |
|
||
// Store the pair (key, value) into the shared state. If the value is None, the pair (key, value) will be | ||
// removed from the shared state if it exists | ||
func (s *State) Store(key string, value starlark.Value) { |
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.
Should there be a configurable capacity limit here to prevent OOMs?
I can foresee cases where the state store usage might blow up, for example if the name is defined based on tag values and the cardinality unexpectedly increases.
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.
that's a good question. I'm not sure if we should handle this or just add a warning to watch out for this.
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.
One alternative is to just the ability to check the size of the state and clear it if it exceeds a threshold. This could be implemented as additional built-in Starlark functions or just a configuration setting.
Running into an OOM is unlikely but for some of my use cases I need to trust that there is some reasonable guaranteed upper bound for memory usage when dealing with high-volume, high-cardinality data.
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 could see how it might be difficult to manage this in Starlark itself.. I'll give some thought to that.
@ssoroka well we currently have the global scope locked as Daniel didn't want the plugin to be stateful to avoid all those nasty hard-to-debug problems. This now adds a state to the plugin. Fair enough, there are plenty of use-cases for it.
I don't see how this helps. We still have a state. We can do the same with inserting
That's 1 line of code... |
All the plugins have state, everything in the plugin struct is stateful.
I like this too, but it's maybe a little less obvious that something special is happening with this variable as opposed to other global variables. There's another consideration that I want to soon be persisting plugin state externally to Telegraf, and it would be interesting if this plugin could take advantage of that. If it's a global var I need to reach into the plugin to get the values, but if it's functions they can easily hook into an external state store/load interface. I'm not sure what you're saying with your example. Here's the same code with Store/Load: def apply(metric):
counter = Load("counter") || 0 # we should change this to support defaults, like Load("counter", 0)
cache = Load("cache") || [] # prefer Load("cache", [])
metric.fields["lala"] = counter
metrics.fields["bubu"] = len(cache)
Store("counter", counter + 1)
Store("cache", cache.append(deepcopy(metric)))
return metric
I count the state global version at 11 lines and the Store/Load funcs at 9; I don't see a huge difference. |
Thanks for adding the shared state, I found it useful in #8903 . I think this common question in the Starlark Processor README.md should be updated to reflect the newly available shared state:
Maybe add: A shared global dictionary named Thanks. |
@thatsafunnyname Makes sense indeed, feel free to create a dedicated ticket for it |
For influxdata#8907 . After influxdata#8447 , this common question in the Starlark Processor README.md should be updated to reflect the newly available shared state.
Required for all PRs:
Fix for #7793
Motivation
We would like to have a way to compare the current metric with the previous one
Modifications:
README.md