influxdata / influxdata/kapacitor
[Feature Request] stateDuration node should increment and emit "duration" on interval
- Dominant language
- Go
- Stars
- 2.4k
- Forks
- 479
- Avg merge
- 4d 16h
- Merged PRs (30d)
- 4
Description
## Summary
The stateDuration node allows you to create a new field representing the duration that a given state has been true. The current implementation depends entirely on incoming data for the node to emit a new metric. This means that this node cannot be used to accurately track durations at the resolution of the given unit if the data write frequency is less than that unit.
## Example
Here is a stub of a TICK script to alert when door is open for over 3 seconds:
#### TICK
```
var data = stream|from()...
var state = data
|eval(lambda: "door_closed" == FALSE)
.as('state')
.keep()
.quiet()
var stateDuration = state
|stateDuration(lambda: "state")
.unit(1s)
.as('duration')
stateDuration
|alert()
.topic(topic)
.info(lambda: "duration" > 3)
```
#### Data
This following data has a write frequency of 1 minute updates if the data isn't changing. Data changes are written immediately. You can see that at 16:12:52 the door_closed changed to false. It remained in this state until 16:12:57, which is 5 seconds.
```
time door_closed
---- -----------
2018-01-13T16:14:42.398-09:00 true
2018-01-13T16:13:42.398-09:00 true
2018-01-13T16:12:57.398-09:00 true
2018-01-13T16:12:52.398-09:00 false
2018-01-13T16:12:42.398-09:00 true
2018-01-13T16:11:42.398-09:00 true
```
### Problem behavior
Clearly the door was open for longer than 3 seconds, but kapacitor remains oblivious because the stateDuration node only emits when it receives data, and the next data value it received reset the stateDuration because the door was closed.
### Expected/Desired behavior
If the state that a stateDuration node is processing becomes true, it should emit a metric on the interval specified by the .unit() attribute so that any downstream processing has an up to date duration field to work with.
## Possible workarounds
Of course one could make a rule for themselves to not try to detect a state change at resolutions below the underlying write frequency of the points the state is based on. But in my current data collection set up it is not convenient to adjust the write frequency for just this one data point. And it's certainly not convenient to have a unique write frequency for each point I'm interested in detecting state changes in.
Alternatively I might be able to join the stream with a batch query of the latest value at the interval of the state change resolution I want to detect. This could be written as a template that allows for the resolution duration to be specified. The downsides to this is that I suspect it will also suffer from limited accuracy. For example if I have a stateDuration at the resolution of 1 minute, and the state changes just after the regular batch minute update, then I may have to, in the worst case, wait nearly an entire additional minute before the duration above the threshold is emitted, assuming no other data comes in. This also strikes me as being unnecessarily inefficient when the stateDuration node already has everything it needs to know for this.
Please let me know if you have any questions
Thank you
Contributor guide
Assessment
This issue has not been assessed yet.