Plotting downtime data with stateDuration

  • What Grafana version and what operating system are you using? v10.2.3

  • What are you trying to achieve?

I have a service which reports uptime by setting an integer to 1 and downtime by setting that integer to 2. I want to calculate the aggregated downtime in the selected time period

  • How are you trying to achieve it?
    I am using a stat panel and my query looks like this,
from(bucket: "rb5009")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "interface")
  |> filter(fn: (r) => r["_field"] == "ifOperStatus")
  |> filter(fn: (r) => r["ifDescr"] == "wan1")
  |> aggregateWindow(createEmpty: true, fn: max, every: v.windowPeriod)
  |> stateDuration(fn: (r) => r._value == 2, unit: 1s)
  |> drop(columns: ["_value"])
  |> yield(name: "downtime")
  • What happened?

There are two problems.

  1. The accumulator in stateDuration keeps going up when there is a downtime and resets to -1 when there is no downtime. How do I aggregate on some thing like this? A plain aggregate/sum function will add all the individual values and report a very large number.
  2. It some times, flashes -1 even though there is downtime and the service did not report up time at all!
  • What did you expect to happen?

I expected it to show me total downtime in the selected time period.

  • Did you receive any errors in the Grafana UI or in related logs? If so, please tell us exactly what they were.
    No errors

  • Did you follow any online instructions? If so, what is the URL?
    stateDuration() function | Flux Documentation

How do I sum the downtime period? It accumulates the value internally so I can see stat for 1 downtime period correctly but aggregating on all downtimes is difficult.


I want to sum values at the end of all the peaks

This is it.

import "contrib/tomhollingworth/events"

from(bucket: "rb5009")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "interface")
  |> filter(fn: (r) => r["_field"] == "ifOperStatus")
  |> filter(fn: (r) => r["ifDescr"] == "wan1")
  |> events.duration(
    unit: 1s,
    columnName: "duration",
    timeColumn: "_time",
  )
  |> filter(fn: (r) => r._value == 2)
  |> aggregateWindow(every: v.windowPeriod, fn: sum, column: "duration", createEmpty: true)
  |> yield(name: "duration")

Next I need to look into limiting the unit to days instead of it going into weeks. X.Y days is nicer than 1.45 weeks

1 Like