504 lines
15 KiB
JavaScript
504 lines
15 KiB
JavaScript
Vue.component('ln-slider',{
|
|
model: {
|
|
prop: 'value',
|
|
event: 'change',
|
|
},
|
|
props: {
|
|
value: {
|
|
type: Number,
|
|
default: 1,
|
|
},
|
|
min: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
max: {
|
|
type: Number,
|
|
default: 100,
|
|
},
|
|
step: {
|
|
type: Number,
|
|
default: 1,
|
|
},
|
|
islogarithmic: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
values: {
|
|
type: Array,
|
|
}
|
|
},
|
|
data: function(){
|
|
let d = {
|
|
};
|
|
|
|
if (this.values){
|
|
this.min = 0;
|
|
this.max = this.values.length - 1;
|
|
this.step = 1;
|
|
} else if (this.islogarithmic){
|
|
/* ToDo: Implement */
|
|
} else {
|
|
|
|
}
|
|
|
|
// console.log(`min=${this.min} max=${this.max} step=${this.step} value=${this.value}`);
|
|
|
|
return d;
|
|
},
|
|
computed: {
|
|
displayValue: function(){
|
|
if (this.values)
|
|
{
|
|
let sv = this.sliderValue;
|
|
let element = this.values[this.sliderValue];
|
|
return element[1] || element;
|
|
}
|
|
return this.mapFromRange(this.value);
|
|
},
|
|
sliderValue: {
|
|
get: function(){ return this.mapToRange(this.value); },
|
|
set: function(v){ this.value = this.mapFromRange(v); this.$emit('change', this.value); },
|
|
}
|
|
},
|
|
methods: {
|
|
mapToRange: function(v){
|
|
if (this.values)
|
|
{
|
|
for (let idx=0;idx<this.values.length;idx++)
|
|
{
|
|
let element = this.values[idx];
|
|
if (v == (element[0] || element))
|
|
{
|
|
return idx;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
return this.islogarithmic ? null : v;
|
|
},
|
|
mapFromRange: function(v){
|
|
if (this.values)
|
|
{
|
|
let element = this.values[v];
|
|
let rv = element[0] || element;
|
|
return rv;
|
|
}
|
|
return this.islogarithmic ? null : v;
|
|
},
|
|
fireChange: function(){
|
|
this.$emit('change',this.value);
|
|
}
|
|
},
|
|
template: `
|
|
<div class='ln-slider'>
|
|
<input
|
|
class="ln-slider"
|
|
type="range"
|
|
v-bind:min="min"
|
|
v-bind:max="max"
|
|
v-bind:step="step"
|
|
v-model="sliderValue"
|
|
@change="fireChange"
|
|
>{{ displayValue }}
|
|
</div>`,
|
|
|
|
});
|
|
|
|
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,
|
|
graphInterval: 600,
|
|
graphShift: 0,
|
|
viewIntervals: [
|
|
[ 600,'10 Minuten'],
|
|
[ 3600,'1 Stunde'],
|
|
[ 7200,'2 Stunden'],
|
|
[ 14400,'4 Stunden'],
|
|
[ 28800,'8 Stunden'],
|
|
[ 57600,'16 Stunden'],
|
|
[ 86400,'1 Tag'],
|
|
[ 86400 * 2,'2 Tage'],
|
|
[ 86400 * 4,'4 Tage'],
|
|
[ 86400 * 7,'1 Woche'],
|
|
[ 86400 * 14,'2 Wochen'],
|
|
[ 86400 * 28,'4 Wochen'],
|
|
[ 86400 * 7 * 8,'8 Wochen'],
|
|
[ 86400 * 7 * 16,'16 Wochen'],
|
|
[ 86400 * 7 * 32,'32 Wochen'],
|
|
[ 86400 * 7 * 64,'64 Wochen'],
|
|
],
|
|
};
|
|
},
|
|
beforeRouteEnter: function (to, from, next) {
|
|
next((vm) => {
|
|
skyscanner.loadNode(to.params.nodeID, (node) => {
|
|
vm.node = node;
|
|
vm.$nextTick(() => {
|
|
skyscanner.buildGraphs(node);
|
|
loadGraphs(node,vm.graphInterval,vm.graphShift);
|
|
});
|
|
}, 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,viewInterval,graphShift) {
|
|
for (group in node._graphs) {
|
|
if (!node._graphs.hasOwnProperty(group)) continue;
|
|
|
|
let dataSets = [];
|
|
let yScales = [];
|
|
|
|
|
|
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,
|
|
perfValue: perfValue,
|
|
label: perfName + (perfUnit ? " [" + perfUnit + "]" : ""),
|
|
data: [],
|
|
borderColor: color,
|
|
backgroundColor: color,
|
|
fill: false,
|
|
yAxisID: perfUnit,
|
|
});
|
|
|
|
}
|
|
}
|
|
|
|
let chart = getOrCreateChart(`chart-${group}`, yScales, dataSets);
|
|
chart.options.title.text = `${group}`;
|
|
|
|
loadChartLines(chart, viewInterval,graphShift);
|
|
|
|
chart.update();
|
|
}
|
|
}
|
|
|
|
function loadChartLines(chart, viewInterval, graphShift){
|
|
if (!viewInterval)
|
|
return;
|
|
|
|
chart.data.datasets.forEach((dataSet) => {
|
|
loadChartLine(chart, dataSet, dataSet.perfValue, viewInterval, graphShift);
|
|
});
|
|
}
|
|
|
|
function loadChartLine(chart, dataSet, perfValue, viewInterval, graphShift) {
|
|
if (!viewInterval)
|
|
return;
|
|
|
|
skyscanner.loadPerformanceGraph(perfValue.PerfPath, viewInterval, graphShift, (perfData) => {
|
|
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 = $("<div></div>").attr("id", chartID).css("height", "400px");
|
|
var canvas = $("<canvas></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 = $("<div></div>").attr("id", perfID).css("height", "400px");
|
|
var canvas = $("<canvas></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);
|
|
});
|
|
} |