14

I am in the processing of migrating my panels from using the SQL syntax (from InfluxDB version 1.X) to the new influx syntax (InfluxDB version 2).

There is an issue with the labels of the data. It includes the attributes that I used to filter it. For example, if I select data from a range that contains 2 days, it splits the data up. See the screenshot below:

enter image description here

This completely messes the chart up. The base code looks like this:

from(bucket: "main")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
      r._measurement == "POWER" and
      r._field == "value" and
      r.device == "living_room"
  )
  |> aggregateWindow(every: v.windowPeriod, fn: sum)

It should obviously just be "POWER" and "CURRENT".

I tried a dozen of different approaches, but cannot come up with a working solution.

For example, if I do:

from(bucket: "main")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
      r._measurement == "POWER" and
      r._field == "value" and
      r.device == "living_room"
  )
  |> aggregateWindow(every: v.windowPeriod, fn: sum)
  |> map(fn: (r) => ({ POWER: r._value }))

it says "Data does not have a time field".

I also tried using

from(bucket: "main")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
      r._measurement == "POWER" and
      r._field == "value" and
      r.device == "living_room"
  )
  |> aggregateWindow(every: v.windowPeriod, fn: sum)
  |> yield(name: "POWER")

that does not work either. I tried many other things without success.

How can I fix this?

TheNiceGuy
  • 3,462
  • 8
  • 34
  • 64

6 Answers6

20

After hours of trial and error, I was able to produce a working solution. I imagine that other users may stumble upon the same issue, I will therefore not delete the question and instead provide my solution.

I basically had to map the required fields and tags and assign the desired label, instead of just mapping the value that should be displayed (because then the date/time data is missing).

The solution looks like this:

from(bucket: "main")
  |> range(start: v.timeRangeStart, stop:v.timeRangeStop)
  |> filter(fn: (r) =>
      r._measurement == "POWER" and
      r._field == "value" and
      r.device == "living_room"
      )
  |> aggregateWindow(every: v.windowPeriod, fn: max)
  |> map(fn: (r) => ({ _value:r._value, _time:r._time, _field:"Power (W)" }))

Power (W) is the label/alias that is going to be used.

I wish that Influx would provide an easier way to alias the desired field. The current approach is not very intuitive.

TheNiceGuy
  • 3,462
  • 8
  • 34
  • 64
  • 2
    If you have multiple series you may want to include the tags or other fields from the query, if all you are trying to do is rename the field then you should use the "r with" operator to carry over the content and only rename the field. Example: |> map(fn: (r) => ({ r with _field:"Power (W)" })) – Jeremy Buentello Mar 06 '22 at 19:11
  • I tried doing the "r with..." version and this still returned back the original poster's issue. Not sure why, but specifying the fields and setting the _field (or alternatively doing the override method below) are the only ways I have been successful. – Gareth Arch Oct 27 '22 at 17:17
  • @Jeremy Buentello That does not work as mentioned in the above comment. – TheNiceGuy Jan 23 '23 at 16:28
  • @GarethArch How did you get it to work with the override methods from the answers below? I tried both of them and they just change the name for the label, but they will still not be properly grouped, or in other words, the amount of the displayed labels won't change, just their displayed name – TheNiceGuy Jan 23 '23 at 16:28
7

A bit similar to Sebastian Kollmar's suggestion, but I'm not sure if this is exactly what he meant - a colleague of mine came up with this:

figure1

With few or no changes, this will probably achieve what you were looking for.

Edit: my original interpretation of the question was that the goal was simply to get rid of the text within brackets in the legend. If the goal is more fundamentally to change how data is grouped, see my comment below

ffi
  • 353
  • 4
  • 11
  • I just tried this, but without success. Please see my comment under my original post – TheNiceGuy Jan 23 '23 at 16:16
  • Based on the screenshot in the question, it appears that your data has a "date" tag. This is not only redundant (date info is already in the timestamp), but also not advisable because it leads to runaway cardinality. And my guess is that this tag is what's causing your issue. Grafana draws each time series as one line, and values with different values for a given tag (e.g. "23.06.2021", "24.06.2021") are considered to belong to different time series. I suggest you get rid of the "date" tag entirely in your data. A quick and dirty solution is to add |> drop(columns: ["date"]) to your query. – ffi Jan 25 '23 at 11:06
2

Grafana can solve this issue, too. You can use the "property override" function with regex to override the label.

You can find information to regex in grafana here: https://grafana.com/docs/grafana/latest/variables/filter-variables-with-regex/

A solution for your label could be something like this:

/(POWER)/

(depending on your version of grafana. Tested on version 8.1.1)

1

I found that the critical thing is to make sure that the final table parsed to grafana only has columns with the data you want to plot. All Flux functions will add in columns "_start" and "_stop" which will appear in the the grafana label. So the best way to clean up the table is to rename the column to the label you want to appear in Grafana, and then use the keep function to delete unused columns. This is an example for plotting just one series "My_data" but can be extended to keep multiple series/labels.

from(bucket: "main")
    |> range(start: v.timeRangeStart , stop: v.timeRangeStop )
    |> filter(fn: (r) => r["entity_id"] == "My_data" )
    |> filter(fn: (r) => r["_field"] == "value")
    |> rename(columns: {_value: "My_data"})         //rename _value column to the name you want to appear in grafana
    |> keep(columns : ["_time","My_data"])          //delete all columns in table other than the series you want to plot
Marky0
  • 1,984
  • 2
  • 12
  • 28
0

I had a similar issue where I wanted to apply a Regex to extract part of the serie name.This post helped me a lot, here's my snippet in case it helps someone else. The idea is just to create an additional column that contains the final label and use it to have a clean displayed name. Note that you can skip the extra column (and the additional map) by inlining the regex.replaceAllString directly within the line where the _field is set. I kept it like this for readability.

import "regexp"

from(bucket: "MYBUCKET")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] =~ /This_Is.*EndOfMyMeasurement$/  )   
  |> filter(fn: (r) => r["_field"] == "value")
  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)  
  |> map(fn: (r) => ({ r with humanReadable: regexp.replaceAllString(r: /.*This_(.*)_Something_(.*)_(.*)_EndOfMyMeasurement/, v: r["_measurement"], t: "$1 $2 (something $3)") }))
  |> map(fn: (r) => ({ _value:r._value, _time:r._time, _field:r.humanReadable }))
  |> yield(name: "x")
kdrapel
  • 130
  • 1
  • 8
0

Thanks for your input - I was pulling my hair out with the same issue!! The Grafana Override is great solution until you start to get cleaver with dashboard variables and then the wheels fall off. With your help above i finally cracked it. I hope this helps others. My solution has 3 parts:-

  1. Drop unrequired columns
    drop(columns: ["Tag1", "master", "Tag2","sensor","Tag3 etc"])
  2. Make the dynamic values that are causing issues static:
    |> map(fn: (r) => ({ r with TheTagThatKeepChanging:"ThisNeverChanges" }))
  3. Set up the overrides in Grafana to give meaningful name and then SAVE the dashboard and reopen before you start changing any variable to dynamically update the query.
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129