diff --git a/internal/metricdata/prometheus.go b/internal/metricdata/prometheus.go
index d93a3c5..0d3848f 100644
--- a/internal/metricdata/prometheus.go
+++ b/internal/metricdata/prometheus.go
@@ -326,7 +326,6 @@ func (pdb *PrometheusDataRepository) LoadData(
Timestep: metricConfig.Timestep,
Series: make([]schema.Series, 0),
}
- jobData[metric][scope] = jobMetric
}
step := int64(metricConfig.Timestep)
steps := int64(to.Sub(from).Seconds()) / step
@@ -335,6 +334,10 @@ func (pdb *PrometheusDataRepository) LoadData(
jobMetric.Series = append(jobMetric.Series,
pdb.RowToSeries(from, step, steps, row))
}
+ // only add metric if at least one host returned data
+ if !ok && len(jobMetric.Series) > 0{
+ jobData[metric][scope] = jobMetric
+ }
// sort by hostname to get uniform coloring
sort.Slice(jobMetric.Series, func(i, j int) bool {
return (jobMetric.Series[i].Hostname < jobMetric.Series[j].Hostname)
diff --git a/web/frontend/src/Analysis.root.svelte b/web/frontend/src/Analysis.root.svelte
index 2e6f5b5..1cfadc9 100644
--- a/web/frontend/src/Analysis.root.svelte
+++ b/web/frontend/src/Analysis.root.svelte
@@ -1,10 +1,11 @@
+
+{#if data.length > 0}
+
+{:else}
+ Cannot render histogram: No data!
+{/if}
+
+
diff --git a/web/frontend/src/plots/MetricPlot.svelte b/web/frontend/src/plots/MetricPlot.svelte
index 1565cde..7915c68 100644
--- a/web/frontend/src/plots/MetricPlot.svelte
+++ b/web/frontend/src/plots/MetricPlot.svelte
@@ -26,16 +26,17 @@
import { getContext, onMount, onDestroy } from 'svelte'
import { Card } from 'sveltestrap'
+ export let metric
+ export let scope = 'node'
+ export let resources = []
export let width
export let height
export let timestep
export let series
+ export let useStatsSeries = null
export let statisticsSeries = null
export let cluster
export let subCluster
- export let metric
- export let useStatsSeries = null
- export let scope = 'node'
export let isShared = false
export let forNode = false
@@ -54,6 +55,70 @@
const backgroundColors = { normal: 'rgba(255, 255, 255, 1.0)', caution: 'rgba(255, 128, 0, 0.3)', alert: 'rgba(255, 0, 0, 0.3)' }
const thresholds = findThresholds(metricConfig, scope, typeof subCluster == 'string' ? cluster.subClusters.find(sc => sc.name == subCluster) : subCluster)
+ // converts the legend into a simple tooltip
+ function legendAsTooltipPlugin({ className, style = { backgroundColor:"rgba(255, 249, 196, 0.92)", color: "black" } } = {}) {
+ let legendEl;
+ const dataSize = series.length
+
+ function init(u, opts) {
+ legendEl = u.root.querySelector(".u-legend");
+
+ legendEl.classList.remove("u-inline");
+ className && legendEl.classList.add(className);
+
+ uPlot.assign(legendEl.style, {
+ textAlign: "left",
+ pointerEvents: "none",
+ display: "none",
+ position: "absolute",
+ left: 0,
+ top: 0,
+ zIndex: 100,
+ boxShadow: "2px 2px 10px rgba(0,0,0,0.5)",
+ ...style
+ });
+
+ // conditional hide series color markers:
+ if (useStatsSeries === true || // Min/Max/Avg Self-Explanatory
+ dataSize === 1 || // Only one Y-Dataseries
+ dataSize > 6 ){ // More than 6 Y-Dataseries
+ const idents = legendEl.querySelectorAll(".u-marker");
+ for (let i = 0; i < idents.length; i++)
+ idents[i].style.display = "none";
+ }
+
+ const overEl = u.over;
+ overEl.style.overflow = "visible";
+
+ // move legend into plot bounds
+ overEl.appendChild(legendEl);
+
+ // show/hide tooltip on enter/exit
+ overEl.addEventListener("mouseenter", () => {legendEl.style.display = null;});
+ overEl.addEventListener("mouseleave", () => {legendEl.style.display = "none";});
+
+ // let tooltip exit plot
+ // overEl.style.overflow = "visible";
+ }
+
+ function update(u) {
+ const { left, top } = u.cursor;
+ const width = u.over.querySelector(".u-legend").offsetWidth;
+ legendEl.style.transform = "translate(" + (left - width - 15) + "px, " + (top + 15) + "px)";
+ }
+
+ if (dataSize <= 12 || useStatsSeries === true) {
+ return {
+ hooks: {
+ init: init,
+ setCursor: update,
+ }
+ }
+ } else { // Setting legend-opts show/live as object with false here will not work ...
+ return {}
+ }
+ }
+
function backgroundColor() {
if (clusterCockpitConfig.plot_general_colorBackground == false
|| !thresholds
@@ -94,7 +159,7 @@
? (statisticsSeries.max.reduce((max, x) => Math.max(max, x), thresholds.normal) || thresholds.normal)
: (series.reduce((max, series) => Math.max(max, series.statistics?.max), thresholds.normal) || thresholds.normal)
: null
- const plotSeries = [{}]
+ const plotSeries = [{label: 'Runtime', value: (u, ts, sidx, didx) => didx == null ? null : formatTime(ts)}]
const plotData = [new Array(longestSeries)]
if (forNode === true) {
@@ -113,14 +178,17 @@
plotData.push(statisticsSeries.min)
plotData.push(statisticsSeries.max)
plotData.push(statisticsSeries.mean)
+
if (forNode === true) { // timestamp 0 with null value for reversed time axis
if (plotData[1].length != 0) plotData[1].push(null)
if (plotData[2].length != 0) plotData[2].push(null)
if (plotData[3].length != 0) plotData[3].push(null)
}
- plotSeries.push({ scale: 'y', width: lineWidth, stroke: 'red' })
- plotSeries.push({ scale: 'y', width: lineWidth, stroke: 'green' })
- plotSeries.push({ scale: 'y', width: lineWidth, stroke: 'black' })
+
+ plotSeries.push({ label: 'min', scale: 'y', width: lineWidth, stroke: 'red' })
+ plotSeries.push({ label: 'max', scale: 'y', width: lineWidth, stroke: 'green' })
+ plotSeries.push({ label: 'mean', scale: 'y', width: lineWidth, stroke: 'black' })
+
plotBands = [
{ series: [2,3], fill: 'rgba(0,255,0,0.1)' },
{ series: [3,1], fill: 'rgba(255,0,0,0.1)' }
@@ -130,6 +198,9 @@
plotData.push(series[i].data)
if (forNode === true && plotData[1].length != 0) plotData[1].push(null) // timestamp 0 with null value for reversed time axis
plotSeries.push({
+ label: scope === 'node' ? resources[i].hostname :
+ // scope === 'accelerator' ? resources[0].accelerators[i] :
+ scope + ' #' + (i+1),
scale: 'y',
width: lineWidth,
stroke: lineColor(i, series.length)
@@ -140,6 +211,9 @@
const opts = {
width,
height,
+ plugins: [
+ legendAsTooltipPlugin()
+ ],
series: plotSeries,
axes: [
{
@@ -193,8 +267,11 @@
x: { time: false },
y: maxY ? { range: [0., maxY * 1.1] } : {}
},
- cursor: { show: false },
- legend: { show: false, live: false }
+ legend : { // Display legend until max 12 Y-dataseries
+ show: (series.length <= 12 || useStatsSeries === true) ? true : false,
+ live: (series.length <= 12 || useStatsSeries === true) ? true : false
+ },
+ cursor: { drag: { x: true, y: true } }
}
// console.log(opts)
@@ -265,16 +342,21 @@
}