SkyScanner.getInitializers().push( new Promise((resolve, reject) => { LN().load("/vue/ln.skyscanner.node.html"). then((template) => { skyScannerRoutes.push( { path: "/vue/nodes/:nodeID", component: { template: template, data: function () { return { node: null }; }, beforeRouteEnter: function (to, from, next) { next((vm) => { skyscanner.loadNode(to.params.nodeID, (node) => { vm.node = node; vm.$nextTick(() => { skyscanner.buildGraphs(node); loadGraphs(node); }); }, 10000); }); }, beforeRouteLeave: function (from, to, next) { clearTimeout(skyscanner.currentTimeout); next(); }, }, } ); resolve(); }); }) ); class ColorStack { constructor() { this.reset(); this.axColors = [ "#C0C0FF", "#C040FF", "#40C0FF", "#4040FF", "#C08080", "#80C080", "#808080" ] } reset() { this.resetRed() this.resetYellow(); this.resetGreen(); this.resetBlue(); this.currentAxColor = 0; } resetRed() { this.currentRed = 208; } resetYellow() { this.currentYellow = 208; } resetGreen() { this.currentGreen = 208; } resetBlue() { this.currentBlue = 208; } toHex02(n) { let sn = n.toString(16); if (sn.length < 2) sn = "0" + sn; return sn; } toRGB(r, g, b) { return "#" + this.toHex02(r) + this.toHex02(g) + this.toHex02(b); } popRed() { this.currentRed -= 16; return this.toRGB(this.currentRed, 0, 0); } popYellow() { this.currentYellow -= 16; return this.toRGB(this.currentYellow, this.currentYellow, 0); } popGreen() { this.currentGreen -= 16; return this.toRGB(0, this.currentGreen, 0); } popBlue() { this.currentBlue -= 16; return this.toRGB(0, 0, this.currentBlue); } popAxColor() { let axColor = this.axColors[this.currentAxColor]; this.currentAxColor = (this.currentAxColor + 1) % this.axColors.length; return axColor; } pop(checkState) { if (checkState == "CRITICAL") return this.popRed(); if (checkState == "WARN") return this.popYellow(); return this.popGreen(); } } class ColorStackContainer { constructor() { this.colorStacks = {}; } getColorStack(graphName) { if (!this.colorStacks.hasOwnProperty(graphName)) this.colorStacks[graphName] = new ColorStack(); return this.colorStacks[graphName]; } } var colorContainer = new ColorStackContainer(); function toSI(value, perfUnit) { if (perfUnit == "%"){ value = 100.0 * value; } if (value == 0) return value; let prefixes = { "12": "T", "9": "G", "6": "M", "3": "k", "0": " ", "-3": "m", "-6": "u", "-9": "n" } let lg10 = Math.log10(Math.abs(value)); let nPrefix = Math.floor(lg10 / 3) * 3; let nValue = value / Math.pow(10, nPrefix); let prefix = prefixes[nPrefix] || `E${nPrefix}`; return `${nValue}${prefix}`; } function loadGraphs(node) { for (group in node._graphs) { if (!node._graphs.hasOwnProperty(group)) continue; let dataSets = []; let yScales = []; let perfValueDict = {}; for (perfUnit in node._graphs[group]) { if (!node._graphs[group].hasOwnProperty(perfUnit)) continue; let axColor = colorContainer.getColorStack(group).popAxColor(); let _perfUnit = perfUnit; yScales.push({ display: true, id: perfUnit, scaleLabel: { display: true, labelString: perfUnit, fontColor: axColor, }, gridLines: { color: axColor, }, ticks: { callback: function (value, index, values) { try { return toSI(value, _perfUnit); } catch { return value; } } } }); for (perfName in node._graphs[group][perfUnit]) { if (!node._graphs[group][perfUnit].hasOwnProperty(perfName)) continue; let perfValue = node._graphs[group][perfUnit][perfName]; let color = colorContainer.getColorStack(group).pop(perfValue.CheckState); dataSets.push({ perfName: perfName, perfUnit: perfUnit, label: perfName + (perfUnit ? " [" + perfUnit + "]" : ""), data: [], borderColor: color, backgroundColor: color, fill: false, yAxisID: perfUnit, }); perfValueDict[perfName] = perfValue; } } let chart = getOrCreateChart(`chart-${group}`, yScales, dataSets); chart.options.title.text = `${group}`; chart.data.datasets.forEach((dataSet) => { console.log("dataSet: " + dataSet.perfName); loadChartLine(chart, dataSet, perfValueDict[dataSet.perfName]); }); chart.update(); } } function loadChartLine(chart, dataSet, perfValue) { console.log("loadChartLine()"); skyscanner.loadPerformanceGraph(perfValue.PerfPath, 3600, (perfData) => { console.log("loadPerformaceGraph(): callback"); let chartColor = perfValue.CheckState == "CRITICAL" ? '#C00000' : (perfValue.CheckState == "WARN") ? '#C0C000' : '#008000'; let perfName = perfValue.PerfName; dataSet.data.length = 0; $.each(perfData, function () { if (this.TimeStamp != 0) dataSet.data.push({ x: this.TimeStamp, y: this.Value }); }); chart.update(); }); } function getOrCreateChart(chartID, yAxes, datasets) { var gDiv = $("#" + CSS.escape(chartID)); var chart = null; if (!gDiv.length) { gDiv = $("
").attr("id", chartID).css("height", "400px"); var canvas = $("").appendTo(gDiv); chart = new Chart(canvas, { type: 'line', data: { datasets, }, options: { title: { display: true, text: '-' }, scales: { yAxes, xAxes: [{ type: 'time', time: { unit: "minute", tooltipFormat: "DD.MM.YYYY HH:mm", displayFormats: { minute: "DD.MM.YYYY HH:mm" }, parser: moment.unix } }] }, responsive: true, maintainAspectRatio: false, cubicInterpolationMode: "monotone", fill: false, tooltips: { callbacks: { label: function(tooltipItem, data) { let dataSet = data.datasets[tooltipItem.datasetIndex]; let value = tooltipItem.yLabel; if (dataSet.perfUnit == "%") { value = value * 100.0; } let label = dataSet.label || ''; if (label) { label += ': '; } label += toSI(value); return label; } } } } }); chart.data.labels.length = 0; gDiv.data("chart", chart); $("#graphs").append(gDiv); } else { chart = gDiv.data("chart"); } return chart; } function loadGraph(perfValue) { skyscanner.loadPerformanceGraph(perfValue.PerfPath, 3600, (perfData) => { var perfID = skyscanner.encodeID(perfValue.PerfName); var chartColor = perfValue.CheckState == "CRITICAL" ? '#C00000' : (perfValue.CheckState == "WARN") ? '#C0C000' : '#008000'; var gDiv = $("#" + perfID); var chart = null; if (!gDiv.length) { gDiv = $("
").attr("id", perfID).css("height", "400px"); var canvas = $("").appendTo(gDiv); chart = new Chart(canvas, { type: 'line', data: { datasets: [ { label: "-", data: [], borderColor: chartColor, backgroundColor: null, fill: false, } ] }, options: { scales: { yAxes: [ { ticks: { callback: SkyScanner.scaleSI, beginAtZero: true, } } ], xAxes: [{ type: 'time', time: { unit: "minute", tooltipFormat: "DD.MM.YYYY HH:mm", displayFormats: { minute: "DD.MM.YYYY HH:mm" }, parser: moment.unix } }] }, responsive: true, maintainAspectRatio: false, cubicInterpolationMode: "monotone", fill: false, } }); chart.data.labels.length = 0; chart.data.datasets[0].data.length = 0; chart.data.datasets[0].label = perfValue.PerfName; gDiv.data("chart", chart); } else { chart = gDiv.data("chart"); } chart.data.datasets[0].data.length = 0; $.each(perfData, function () { if (this.TimeStamp != 0) chart.data.datasets[0].data.push({ x: this.TimeStamp, y: this.Value }); }); chart.update(); $("#graphs").append(gDiv); }); }