Search code examples
prometheuspromql

Prometheus: How can I multiply a vector by the average of another vector


Situation

I have a counter with values from a power meter (KWh since it was installed). On my Grafana dashboard I like to show how much money was spend on electric power during the given time range.

Doing this with a fixed price per KWh is easy: increase(loxone_values{control="Stromverbrauch Zähler"}[$__range]) * 0.22

I can show the last value with a "Stat" in Grafana and get the amount of money spend.

Problem

Obviously this fails if the price per KWh changes, which is does every hour in my case. I have a second metric that holds the current price. I like to multiply the KWh by the average price.

I think I can do this with group_left but failed to construct a working query.

My first approach increase(loxone_values{control="Stromverbrauch Zähler"}[$__range]) * group_left avg(loxone_values{control="Strompreis aktuell"}) which gives a parse error.

It looks like group_left needs something to match the vectors. But there is no common tag (beside instance but that might change in the future).

Anyway I gave that a try but increase(loxone_values{control="Stromverbrauch Zähler"}[$__range]) * on (instance) group_left avg(loxone_values{control="Strompreis aktuell"}) gives me an empty result.


Solution

  • This should do it:

    increase(loxone_values{control="Stromverbrauch Zähler"}[$__range]) * scalar(avg(loxone_values{control="Strompreis aktuell"}))

    Explanation:

    You can multiply an instant vector by an instant vector with exactly the same labels and label values or by a scalar. The result(s) of increase(loxone_values{control="Stromverbrauch Zähler"}[$__range]) must have labels, whereas avg(loxone_values{control="Strompreis aktuell"}) will return one instant vector with no labels. Using scalar converts the instant vector to a scalar and all results of increase(loxone_values{control="Stromverbrauch Zähler"}[$__range]) will be multiplied by that, irrelevant of their labels.