diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2021-04-05 16:07:25 +0200 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2021-05-02 14:45:14 +0200 |
commit | bf3b70d813fc35e4e5096271b2256aaec2371709 (patch) | |
tree | 01bae817883fef01acfeb9bad41be5bd06622245 /src/munin-plot.js | |
parent | c7dfdd60fda6279817795dfe062df4f0b9fcbdfa (diff) |
Refactor code to process data in one place
This gets rid of the two invocations of Plotly.d3.csv() function that
processed data slightly differently.
Diffstat (limited to 'src/munin-plot.js')
-rw-r--r-- | src/munin-plot.js | 267 |
1 files changed, 133 insertions, 134 deletions
diff --git a/src/munin-plot.js b/src/munin-plot.js index dd3e56d..6261234 100644 --- a/src/munin-plot.js +++ b/src/munin-plot.js @@ -226,13 +226,138 @@ $(document).ready(function () { } // load graph data into the plot - function loadGraph(plot, legend, graph) { + function loadGraph(plot, traces, layout) { + // range of the x axis + let url = 'data/' + plot.graph.name + if (plot.layout) { + const [amin, amax] = plot.layout.xaxis.range + url += '?start=' + amin.substring(0, 16).replace(' ', 'T') + '&end=' + amax.substring(0, 16).replace(' ', 'T') + } + Plotly.d3.csv(url, function (data) { + // clear traces + Object.keys(plot.tracebyfield).forEach(function (field) { + plot.tracebyfield[field].x = [] + plot.tracebyfield[field].y = [] + }) + // load new data + data.forEach(function (row) { + Object.keys(plot.tracebyfield).forEach(function (field) { + plot.tracebyfield[field].x.push(row.time) + plot.tracebyfield[field].y.push(row[field] ? Number(row[field]) : null) + }) + }) + if (traces) { + // initial plot creation + plot.innerHTML = '' + Plotly.react(plot, traces, layout, config) + updateLegend(plot) + updatedata = true + // handle plot zoom changes + plot.on('plotly_relayout', function (data) { + if (data['xaxis.range[0]'] && data['xaxis.range[1]']) { + updatedata = true + setDateRange(data['xaxis.range[0]'], data['xaxis.range[1]']) + // update the legend values + updateLegend(plot) + } + }) + // after any changes, save the current list of graphs + saveCurrentGraphs() + } else { + plot.layout.datarevision += 1 + Plotly.react(plot, plot.data, plot.layout) + } + }) + } + + // check if the axis match the data range and load more data as needed + function checkDataUpdates() { + try { + if (updatedata) { + updatedata = false + // go over all plots + $('.myplot').each(function () { + const plot = this + if (plot.layout) { + loadGraph(plot) + } + }) + } + } finally { + setTimeout(checkDataUpdates, 1000) + } + } + setTimeout(checkDataUpdates, 1000) + + // every minute check if we should load new data + function checkNewData() { + setTimeout(checkNewData, 60000) + $('.myplot').each(function (index, plot) { + // if any plot has incomplete data, reload the data + if (plot.layout) { + if (moment().format('YYYY-MM-DD HH:mm') < plot.layout.xaxis.range[1]) { updatedata = true } + } + }) + } + setTimeout(checkNewData, 60000) + + function addGraph(graph, size = 'sm') { + const clone = $('#template>:first-child').clone() + const plot = clone.find('.myplot')[0] + const legend = clone.find('.mylegend') + plot.graph = graph + // update graph title + clone.find('.graphtitle').text(graph.host + ' / ') + .append($('<b>').text(graph.graph_title)) + .tooltip({title: graph.graph_info || ''}) + // tooltip for drag handle + clone.find('.draghandle').tooltip({placement: 'right'}) + // set the size changing actions + clone.find('.sizesm').tooltip({placement: 'right'}).click(function () { + clone.find('.sizeactive').removeClass('sizeactive') + $(this).addClass('sizeactive') + $(plot).addClass('plot-sm').removeClass('plot-md plot-lg') + legend.addClass('legend-sm').removeClass('legend-md legend-lg') + Plotly.relayout(plot, {}) + saveCurrentGraphs() + }) + clone.find('.sizemd').tooltip({placement: 'right'}).click(function () { + clone.find('.sizeactive').removeClass('sizeactive') + $(this).addClass('sizeactive') + $(plot).addClass('plot-md').removeClass('plot-sm plot-lg') + legend.addClass('legend-md').removeClass('legend-sm legend-lg') + Plotly.relayout(plot, {}) + saveCurrentGraphs() + }) + clone.find('.sizelg').tooltip({placement: 'right'}).click(function () { + clone.find('.sizeactive').removeClass('sizeactive') + $(this).addClass('sizeactive') + $(plot).addClass('plot-lg').removeClass('plot-sm plot-md') + legend.addClass('legend-lg').removeClass('legend-sm legend-md') + Plotly.relayout(plot, {}) + saveCurrentGraphs() + }) + // configure the close button + clone.find('.closegraph').tooltip({placement: 'right'}).click(function () { + $(this).tooltip('dispose') + clone.hide(400, function () { + Plotly.purge(plot) + $(this).remove() + // after any changes, save the current list of graphs + saveCurrentGraphs() + }) + }) + // set the wanted size + $(plot).addClass('plot-' + size) + legend.addClass('legend-' + size) + clone.find('.sizeactive').removeClass('sizeactive') + clone.find('.size' + size).addClass('sizeactive') // prepare the graph configuration const layout = JSON.parse(JSON.stringify(baseLayout)) - if (graph.graph_vlabel) { - layout.yaxis.title = graph.graph_vlabel + if (plot.graph.graph_vlabel) { + layout.yaxis.title = plot.graph.graph_vlabel } - if (graph.graph_args && graph.graph_args.match(/--logarithmic/)) { + if (plot.graph.graph_args && plot.graph.graph_args.match(/--logarithmic/)) { layout.yaxis.type = 'log' layout.yaxis.exponentformat = 'E' } @@ -246,11 +371,11 @@ $(document).ready(function () { const tracebyfield = {} plot.tracebyfield = tracebyfield let stackgroup = 0 - for (let i = 0; i < graph.fields.length; i++) { - const field = graph.fields[i] + for (let i = 0; i < plot.graph.fields.length; i++) { + const field = plot.graph.fields[i] const color = field.colour ? '#' + field.colour : defaultColors[i % defaultColors.length] if (field.draw === 'AREA' || field.draw === 'STACK' || field.draw === 'AREASTACK') { - if (!field.draw.match(/STACK/) && (!graph.fields[i + 1] || graph.fields[i + 1].draw.match(/STACK/))) { + if (!field.draw.match(/STACK/) && (!plot.graph.fields[i + 1] || plot.graph.fields[i + 1].draw.match(/STACK/))) { stackgroup += 1 } const trace = { @@ -365,133 +490,7 @@ $(document).ready(function () { } }) // fetch the data and plot it - // TODO: probably skip this initial load??? - Plotly.d3.csv('data/' + graph.name, function (data) { - for (let i = 0; i < data.length; i++) { - const row = data[i] - Object.keys(tracebyfield).forEach(function (field) { - tracebyfield[field].x.push(row.time) - tracebyfield[field].y.push(Number(row[field])) - }) - } - plot.innerHTML = '' - Plotly.react(plot, traces, layout, config) - updateLegend(plot) - updatedata = true - // handle plot zoom changes - plot.on('plotly_relayout', function (data) { - if (data['xaxis.range[0]'] && data['xaxis.range[1]']) { - updatedata = true - setDateRange(data['xaxis.range[0]'], data['xaxis.range[1]']) - // update the legend values - updateLegend(plot) - } - }) - // after any changes, save the current list of graphs - saveCurrentGraphs() - }) - } - - // check if the axis match the data range and load more data as needed - function checkDataUpdates() { - try { - if (updatedata) { - updatedata = false - // go over all plots - $('.myplot').each(function () { - const plot = this - if (plot.layout) { - // range of the x axis - const [amin, amax] = plot.layout.xaxis.range - const url = 'data/' + plot.graph.name + '?start=' + amin.substring(0, 16).replace(' ', 'T') + '&end=' + amax.substring(0, 16).replace(' ', 'T') - Plotly.d3.csv(url, function (data) { - Object.keys(plot.tracebyfield).forEach(function (field) { - plot.tracebyfield[field].x = [] - plot.tracebyfield[field].y = [] - }) - data.forEach(function (row) { - Object.keys(plot.tracebyfield).forEach(function (field) { - plot.tracebyfield[field].x.push(row.time) - plot.tracebyfield[field].y.push(row[field] ? Number(row[field]) : null) - }) - }) - plot.layout.datarevision += 1 - Plotly.react(plot, plot.data, plot.layout) - }) - } - }) - } - } finally { - setTimeout(checkDataUpdates, 1000) - } - } - setTimeout(checkDataUpdates, 1000) - - // every minute check if we should load new data - function checkNewData() { - setTimeout(checkNewData, 60000) - $('.myplot').each(function (index, plot) { - // if any plot has incomplete data, reload the data - if (plot.layout) { - if (moment().format('YYYY-MM-DD HH:mm') < plot.layout.xaxis.range[1]) { updatedata = true } - } - }) - } - setTimeout(checkNewData, 60000) - - function addGraph(graph, size = 'sm') { - const clone = $('#template>:first-child').clone() - const plot = clone.find('.myplot')[0] - const legend = clone.find('.mylegend') - plot.graph = graph - // update graph title - clone.find('.graphtitle').text(graph.host + ' / ') - .append($('<b>').text(graph.graph_title)) - .tooltip({title: graph.graph_info || ''}) - // tooltip for drag handle - clone.find('.draghandle').tooltip({placement: 'right'}) - // set the size changing actions - clone.find('.sizesm').tooltip({placement: 'right'}).click(function () { - clone.find('.sizeactive').removeClass('sizeactive') - $(this).addClass('sizeactive') - $(plot).addClass('plot-sm').removeClass('plot-md plot-lg') - legend.addClass('legend-sm').removeClass('legend-md legend-lg') - Plotly.relayout(plot, {}) - saveCurrentGraphs() - }) - clone.find('.sizemd').tooltip({placement: 'right'}).click(function () { - clone.find('.sizeactive').removeClass('sizeactive') - $(this).addClass('sizeactive') - $(plot).addClass('plot-md').removeClass('plot-sm plot-lg') - legend.addClass('legend-md').removeClass('legend-sm legend-lg') - Plotly.relayout(plot, {}) - saveCurrentGraphs() - }) - clone.find('.sizelg').tooltip({placement: 'right'}).click(function () { - clone.find('.sizeactive').removeClass('sizeactive') - $(this).addClass('sizeactive') - $(plot).addClass('plot-lg').removeClass('plot-sm plot-md') - legend.addClass('legend-lg').removeClass('legend-sm legend-md') - Plotly.relayout(plot, {}) - saveCurrentGraphs() - }) - // configure the close button - clone.find('.closegraph').tooltip({placement: 'right'}).click(function () { - $(this).tooltip('dispose') - clone.hide(400, function () { - Plotly.purge(plot) - $(this).remove() - // after any changes, save the current list of graphs - saveCurrentGraphs() - }) - }) - // set the wanted size - $(plot).addClass('plot-' + size) - legend.addClass('legend-' + size) - clone.find('.sizeactive').removeClass('sizeactive') - clone.find('.size' + size).addClass('sizeactive') - // load the graph data - loadGraph(plot, legend, graph) + loadGraph(plot, traces, layout) // enable tooltips on legend clone.find('.mylegend *[title]').tooltip({placement: 'bottom', container: 'body'}) // show the graph |