uplot is used to dislay timeseries data from VictoriaMetrics database. For the backend Node-Red is used to forward and recieve the query with node-red-contrib-uibuilder.
It works basically and is very fast.
The problem is, when I try to zoom into the uplot graph, my browser (Chrome, Firefox, Edge) freezes. It seems to run out of memory.
Here are parts of my code, using svelte.
<script>
import { onMount } from "svelte";
import { query } from "../lib/uibStore";
import { transformToUplot } from "../lib/helper";
// import uPlot from "uplot";
import Browsebar from "../components/Browsebar.svelte";
import TimerangeSelect from "../components/TimerangeSelect.svelte";
let uplotdiv; //
let opts = {
title: "Temperaturen1",
id: "chart1",
class: "my-chart",
width: 1000,
height: 600,
series: [
{},
{
show: true, // initial toggled state (optional)
spanGaps: true,
label: "RT",
stroke: "red", // series style
scale: "Temperature",
value: (self, rawValue) => rawValue.toFixed(1) + "°C",
},
{
show: true,
spanGaps: true,
label: "KT",
stroke: "green",
scale: "Temperature",
value: (self, rawValue) => rawValue.toFixed(1) + "°C",
},
{
show: true,
spanGaps: true,
label: "VT",
stroke: "blue",
scale: "Temperature",
value: (self, rawValue) => rawValue.toFixed(1) + "°C",
},
],
scales: {
x: { time: true },
Temperature: {
auto: true,
// range: [-10, 20],
side: 3,
},
},
axes: [
{},
{
scale: "Temperature",
values: (self, ticks) => ticks.map((rawValue) => rawValue.toFixed(1) + "°C"),
},
],
cursor: { drag: { x: true, y: true } },
};
let plot; // = new uPlot(opts);
let uPlot;
let d = [[0], [0], [0], [0]];
let resolved = false;
$: uisend($query); //use uibilder.send, if query changes which occurs when timerange or nav index changes
//send a victoriametrics query to the backend, _q is part of query
function uisend(_q) {
// Example 'uvr_prozess_celsius{ort="1"}&start=-3d&step=60s'
uibuilder.send({ topic: "getVMetrics", payload: _q });
}
onMount(async () => {
uisend($query);
const uplotModule = await import("https://unpkg.com/uplot@1.6.22/dist/uPlot.esm.js");
uPlot = uplotModule.default;
plot = new uPlot(opts, [[0], [0], [0], [0]], uplotdiv);
});
uibuilder.onChange("msg", function (msg) {
// load Metrics via Node-Red's uibuilder, serverside
if (msg.topic === "getVMetrics") {
resolved = true;
if (msg.payload.data.result.length > 0) {
d = transformToUplot(msg.payload.data);
plot.setData(d);
}
}
});
</script>
<svelte:head>
<link rel="stylesheet" href="https://unpkg.com/uplot@1.6.22/dist/uPlot.min.css" />
</svelte:head>
<Browsebar>
<TimerangeSelect />
</Browsebar>
<hr />
<div bind:this={uplotdiv} />
{#if resolved}
<code>{$query}</code>
{:else}
<h4>lade Metriken... {$query}</h4>
{/if}
<hr />
Has anyone experienced freezing with uplot? What did you do?
Lucky me, I found the problem. It had to do with the way I transformed the victoriametrics data. On every timestamp I did Number(timestamp).toFixed(0). Without toFixed(0) it is working now. :)
//transform raw data from metrics query to the uplot format
export function transformToUplot(dt) {
let udata = []; //2d data array, conforming uPlot
let tsd = []; //timestamp array
//from first result take only the timestamps
for (let t of dt.result[0].values) {
// tsd.push(Number(t[0]).toFixed(0)); //this was bad!!!!, it lead to freezing
tsd.push(Number(t[0]));
}
udata.push(tsd);
//then the values
for (let r of dt.result) {
let sd = [];
for (let d of r.values) {
let val = Number(d[1]);
sd.push(val);
}
udata.push(sd);
}
return udata;
}
Thanks for your interest!