Plotly in grafana, avoid clashing plot and legend

38 Views Asked by At

I have a grafana dashboard giving my an overview of the electricity usage in my house, from the grid and produced by solar panels. One of the plots is the cumultative production over the day. I made it initially as a grafana time series plot. On the time series plot, it was not possible to get the xaxis fixed for a certain time interval, so I had to give it a lot of air as the plot slid across the panel over the day. So I have recreated the plot using plotly for grafana. This works well, but I have some issues with how the legend is showing. The figure shows the time series panel on the top left and the plotly one at the bottom: (there is a thick cloud layer and even some snow on the panels today, so not much production)

enter image description here

This is not too bad, but I would like to have the plotly panel the same size as the present time series panel, if I do this, it gets messed up:

enter image description here

Is it possible to make the lines on the legend shorter so it could still fit in the same vertical size (preferably), or can I somehow make the graph area auto shrink to give space to the legend?

In case it helps, the data query from a postgresql database, the time field is the time stamp for the measurement, ppv_total is the momentary power production. as I get a datapoint each 5 min, I divide by 12 to get a kWh estimate, the now()::date+time::time is to move all the last days measurement into todays timeframe.

select to_char(time::date,'YYYY-mm-dd') as parameter, now()::date+time::time as time,
sum(ppv_total/12) over (partition by time::date order by time) as " "
from pv where pv.time > now()::date - interval '7 days'
order by time;

The result from this query is then handeled as a time series in grafana, basically doing a pivot table having the values from "parameter" as new column headers. A snippet of the table looks like this:

grafana time series table

This is then run through this script ("data" is the input from grafana).

let dataset = []
for (set =1; set<9; set++){
  let x = [];
  let y = [];
  data.series[0].fields[set].values.forEach(function (item, index) {
    if (item > ''){ // must get rid of empty values
        y.push(item/1000); // I want kWh, having production in Watt
        x.push(data.series[0].fields[0].values[index]);
    }
  }); 
  if (set == 8){ // Todays line should stand out
    line={width:4,
    color: "yellow"};
  }else{
    line={width:1};
  }
  let serie = {
  x : x,
  y : y,
  name : data.series[0].fields[set].labels.parameter,
  line: line
  };
  dataset.push(serie)
}
return {
  data : dataset,
  config : {
    displayModeBar: false
  }
}

The layout object as defined in grafana is:

{
  "yaxis": {
    "gridcolor": "#344",
    "autorange": true,
    "color": "#444",
    "type": "linear",
    "range": [
      -0.3900152777777779,
      7.49179027777778
    ]
  },
  "xaxis": {
    "type": "date",
    "gridwidth": 1,
    "gridcolor": "#444",
    "autorange": true,
    "color": "#444",
    "range": [
      "2024-03-26 07:49:19",
      "2024-03-26 19:40:08"
    ]
  },
  "annotations": [
    {
      "showarrow": false,
      "text": "kWh",
      "textangle": -90,
      "x": -0.03,
      "xanchor": "right",
      "xref": "paper",
      "y": 0.5,
      "yanchor": "right",
      "yref": "paper"
    }
  ],
  "font": {
    "color": "darkgrey"
  },
  "hovermode": "closest",
  "margin": {
    "b": 10,
    "t": 15,
    "r": 10,
    "l": 40
  },
  "paper_bgcolor": "rgba(0,0,0,0)",
  "plot_bgcolor": "rgba(0,0,0,0)",
  "legend": {
    "orientation": "h",
    "yanchor": "bottom",
    "y": -0.5,
    "xanchor": "mid",
    "x": 0,
    "entrywidth": 20
  }
}
1

There are 1 best solutions below

0
EricLavault On BEST ANSWER
  • Is it possible to make the lines on the legend shorter so it could still fit in the same vertical size ?

    No, in fact we can set the legend's itemwidth but the default is already at its minimum :

    itemwidth - number greater than or equal to 30. Sets the width (in px) of the legend item symbols (the part other than the title.text).


  • or can I somehow make the graph area auto shrink to give space to the legend?

    Yes, by tweaking the layout :

    • The bottom margin sets the room for the legend but the grafana setting (10) is way too small, increase that value and ensure the layout margin' autoexpand is enabled.
    • Set the legend entrywidth to 0 to size the entry based on the text width.
    • Set the legend yanchor to "middle" instead of "bottom".
    • Set the xaxis tickformat to "%H:%M" to remove the date Mar 26, 2024 on the first tick.

    Assuming you can return only the changes compared to grafana settings (override), in your script you would have something like this :

    return {
      data: dataset,
      config: {
        displayModeBar: false
      },
      layout: {
        margin: {
          b: 50,  // increase as needed
          t: 15,
          r: 10,
          l: 40,
          autoexpand: true,
        },
        xaxis: {
          title: '',
          tickformat: "%H:%M",
        },
        legend:{
          "yanchor": "middle",
          "entrywidth": 0
        }
      }
    }
    

    You could also play with the legend font size but I'm not sure it will do the trick because the height of the symbols (line/marker, a symbol having a minimum height too) is independent of the text font size.