Calculating the Total Time Spent In A State



Published: 2022-09-06 10:48:18 +0000
Categories: Flux,

Language

Flux

Description

Flux's stdlib provides the function StateDuration() which adds a column with an incrementing counter for as long as the data matches the provided predicate (i.e. indicates a specific state).

However, this counter resets when the state changes, so the duration column only tells you how long each instance of the state lasted and because the counter is added to each row, you cannot simply sum() it to calculate the total time spent in that state (say a switch being on)

However, it's possible to calculate the total amount of time spent in a state using the elapsed()function with a map().

This snippet details how to define a set of predicate based states for a stream of data and then calculate the total time spent in each of those states

Snippet

// Note that elapsed() calculates backwards
// the value in the column elapsed is the number of seconds
// since the last point, not the number of seconds until the 
// next
//
// so when manually checking, work bottom-up, not top-down

from(bucket: "mybucket")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r._measurement == "foo")

  // Use map() to add a column indicating the current state
  |> map(fn: (r) => ({ r with
    state: if r._value > 1000 then
                "ON"
            else 
                "OFF"
  })

  // Use elapsed() to calculate the time between each point
  |> elapsed()

  // Group by state - add other columns (e.g. host) if you
  // need them
  |> group(columns: ["state"])

  // Calculate the time spent in that duration
  |> sum(column: "elapsed")

Usage Example

import "array"

// define some data
rows = [
    // Slow
    {_time: 2022-09-06T10:00:18Z, _field: "speed", _value: 30},
    {_time: 2022-09-06T10:00:19Z, _field: "speed", _value: 35},

    // Moderate
    {_time: 2022-09-06T10:00:20Z, _field: "speed", _value: 50},
    {_time: 2022-09-06T10:00:21Z, _field: "speed", _value: 52},
    {_time: 2022-09-06T10:00:22Z, _field: "speed", _value: 55},
    {_time: 2022-09-06T10:00:27Z, _field: "speed", _value: 55},
    {_time: 2022-09-06T10:00:28Z, _field: "speed", _value: 70},

    // Fast
    {_time: 2022-09-06T10:00:30Z, _field: "speed", _value: 80},
    {_time: 2022-09-06T10:00:35Z, _field: "speed", _value: 85},
    {_time: 2022-09-06T10:00:40Z, _field: "speed", _value: 95},
    {_time: 2022-09-06T10:00:42Z, _field: "speed", _value: 100},
    {_time: 2022-09-06T10:00:43Z, _field: "speed", _value: 105},
    {_time: 2022-09-06T10:00:45Z, _field: "speed", _value: 110},

    // V fast
    {_time: 2022-09-06T10:00:46Z, _field: "speed", _value: 115},
    {_time: 2022-09-06T10:00:50Z, _field: "speed", _value: 120},

    // Fast
    {_time: 2022-09-06T10:00:52Z, _field: "speed", _value: 109},
    {_time: 2022-09-06T10:00:53Z, _field: "speed", _value: 102},
    {_time: 2022-09-06T10:00:55Z, _field: "speed", _value: 95},
    {_time: 2022-09-06T10:00:57Z, _field: "speed", _value: 90},
    {_time: 2022-09-06T10:00:59Z, _field: "speed", _value: 85},
    {_time: 2022-09-06T10:01:05Z, _field: "speed", _value: 75}

]

// Calculate time spent in each speed grouping
array.from(rows: rows)
  |> map(fn: (r) => ({ r with
    pace: if r._value <= 40 then
                "Slow"
            else if r._value > 40 and r._value <= 70 then
                "Moderate"
            else if r._value > 70 and r._value <= 110 then
                "Fast"
            else
                "Clarkson"
  }))
  |> elapsed()
  |> group(columns: ["pace"])
  |> sum(column: "elapsed")

// Result:
//
// 0    5     Clarkson
// 1    32    Fast
// 2    9     Moderate
// 3    1     Slow

// Or, calculate time spent accelerating or decelerating
array.from(rows: rows)
  // Calculate difference between each row
  |> difference()
  // Set a state based on this
  |> map(fn: (r) => ({ r with

    state: if r._value < 0 then
                "decelerating"
            else if r._value > 0 then
                "accelerating"
            else
                "stable"
  }))
  |> elapsed()
  |> group(columns: ["state"])
  |> sum(column: "elapsed")

// Result:
//
// 0    26    accelerating
// 1    15    decelerating
// 2    5    stable

Keywords

influxdb, flux, stateduration, total, predicate, elapsed,

Latest Posts


Copyright © 2022 Ben Tasker | Sitemap | Privacy Policy
Available at snippets.bentasker.co.uk, http://phecoopwm6x7azx26ctuqcp6673bbqkrqfeoiz2wwk36sady5tqbdpqd.onion and http://snippets.bentasker.i2p
hit counter github.com/bentasker