Added graph Intervall, Shift Sliders
parent
f6d962ed5e
commit
e6d6b16430
|
@ -17,11 +17,14 @@ namespace ln.skyscanner.checks
|
||||||
{
|
{
|
||||||
public enum CheckState { OK, WARN, CRITICAL, FAIL, ERROR }
|
public enum CheckState { OK, WARN, CRITICAL, FAIL, ERROR }
|
||||||
|
|
||||||
public struct CheckStateChange
|
public class CheckStateChange
|
||||||
{
|
{
|
||||||
public CheckState NewState;
|
public CheckState NewState;
|
||||||
public DateTime Timestamp;
|
public DateTime Timestamp;
|
||||||
|
|
||||||
|
private CheckStateChange()
|
||||||
|
{
|
||||||
|
}
|
||||||
public CheckStateChange(CheckState checkState)
|
public CheckStateChange(CheckState checkState)
|
||||||
{
|
{
|
||||||
NewState = checkState;
|
NewState = checkState;
|
||||||
|
|
|
@ -108,11 +108,11 @@ namespace ln.skyscanner.services
|
||||||
PerformanceValueService = performanceValueService;
|
PerformanceValueService = performanceValueService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PerfValue[] GetPerfData(string[] perfPath,int timeWindow = 3600)
|
public PerfValue[] GetPerfData(string[] perfPath,int timeWindow,int timeSkip)
|
||||||
{
|
{
|
||||||
PerfFile perfFile = PerformanceValueService.GetPerfFile(perfPath);
|
PerfFile perfFile = PerformanceValueService.GetPerfFile(perfPath);
|
||||||
perfFile.EnsureOpen();
|
perfFile.EnsureOpen();
|
||||||
PerfValue[] perfData = perfFile.QueryTime(timeWindow, 0);
|
PerfValue[] perfData = perfFile.QueryTime(timeWindow, timeSkip);
|
||||||
return perfData;
|
return perfData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.application", "..\ln.app
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.json", "..\ln.json\ln.json.csproj", "{D9342117-3249-4D8B-87C9-51A50676B158}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.json", "..\ln.json\ln.json.csproj", "{D9342117-3249-4D8B-87C9-51A50676B158}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "odb.tool", "..\odb.tool\odb.tool.csproj", "{24C9C372-DCA6-420D-ACD3-5C89C6935D6A}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
|
@ -67,5 +69,9 @@ Global
|
||||||
{D9342117-3249-4D8B-87C9-51A50676B158}.Debug|x86.Build.0 = Debug|Any CPU
|
{D9342117-3249-4D8B-87C9-51A50676B158}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{D9342117-3249-4D8B-87C9-51A50676B158}.Release|x86.ActiveCfg = Release|Any CPU
|
{D9342117-3249-4D8B-87C9-51A50676B158}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{D9342117-3249-4D8B-87C9-51A50676B158}.Release|x86.Build.0 = Release|Any CPU
|
{D9342117-3249-4D8B-87C9-51A50676B158}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{24C9C372-DCA6-420D-ACD3-5C89C6935D6A}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{24C9C372-DCA6-420D-ACD3-5C89C6935D6A}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{24C9C372-DCA6-420D-ACD3-5C89C6935D6A}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{24C9C372-DCA6-420D-ACD3-5C89C6935D6A}.Release|x86.Build.0 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -481,4 +481,12 @@ span#nWARN, span#nCRITICAL, span#nOK {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.ln-slider {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
div.ln-slider {
|
||||||
|
width: 360px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
|
|
||||||
this.currentNodes = [];
|
this.currentNodes = [];
|
||||||
|
|
||||||
|
this.currentAction = "";
|
||||||
|
this.currentState = "";
|
||||||
|
|
||||||
this.issues = {
|
this.issues = {
|
||||||
OK: 0,
|
OK: 0,
|
||||||
WARN: 0,
|
WARN: 0,
|
||||||
|
@ -50,6 +53,14 @@
|
||||||
return initializers;
|
return initializers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action(msg){
|
||||||
|
this.currentAction = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
state(msg){
|
||||||
|
this.currentState = msg;
|
||||||
|
}
|
||||||
|
|
||||||
wsUpdate(state)
|
wsUpdate(state)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -80,11 +91,12 @@
|
||||||
|
|
||||||
updateIssues(){
|
updateIssues(){
|
||||||
var self = this;
|
var self = this;
|
||||||
console.log("Update issue list");
|
|
||||||
|
|
||||||
LN().rpc("CheckService","GetIssueList",[],function(r,e){
|
this.action("updating issue list...");
|
||||||
|
|
||||||
|
LN().rpc("CheckService","GetIssueList",[],(r,e) => {
|
||||||
if (e){
|
if (e){
|
||||||
alert("Error fetching current issue list!\n" + JSON.stringify(e));
|
self.state("Error fetching current issue list!\n" + JSON.stringify(e));
|
||||||
} else {
|
} else {
|
||||||
self.currentIssues = r;
|
self.currentIssues = r;
|
||||||
|
|
||||||
|
@ -103,6 +115,7 @@
|
||||||
self.lastIssueUpdate = moment().format();
|
self.lastIssueUpdate = moment().format();
|
||||||
}
|
}
|
||||||
self.currentTimeout = setTimeout(function(){ self.updateIssues(); }, 10000);
|
self.currentTimeout = setTimeout(function(){ self.updateIssues(); }, 10000);
|
||||||
|
this.action("");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +166,9 @@
|
||||||
loadNode(nodeID,cb,refreshIntervall){
|
loadNode(nodeID,cb,refreshIntervall){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
LN().rpc("entities","GetNode",[nodeID,],function(r,e){
|
this.action("loading node " + nodeID);
|
||||||
|
|
||||||
|
LN().rpc("entities","GetNode",[nodeID,],(r,e) => {
|
||||||
if (refreshIntervall && self.currentTimeout)
|
if (refreshIntervall && self.currentTimeout)
|
||||||
clearTimeout(self.currentTimeout);
|
clearTimeout(self.currentTimeout);
|
||||||
|
|
||||||
|
@ -164,6 +179,8 @@
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
self.loadNode(nodeID,cb,refreshIntervall);
|
self.loadNode(nodeID,cb,refreshIntervall);
|
||||||
}, refreshIntervall);
|
}, refreshIntervall);
|
||||||
|
|
||||||
|
this.action("");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,8 +189,8 @@
|
||||||
return ("" + t).replace( /[\.\/]/g, "_");
|
return ("" + t).replace( /[\.\/]/g, "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPerformanceGraph(perfPath,interval,cb){
|
loadPerformanceGraph(perfPath,interval,shift,cb){
|
||||||
LN().rpc("perfValues","GetPerfData",[perfPath,interval],(perfData,e)=>{
|
LN().rpc("perfValues","GetPerfData",[perfPath,interval,shift],(perfData,e)=>{
|
||||||
if (e){
|
if (e){
|
||||||
console.log(e);
|
console.log(e);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -63,7 +63,27 @@
|
||||||
<textarea>{{ JSON.stringify( node ) }}</textarea>
|
<textarea>{{ JSON.stringify( node ) }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex column grow" id="graphs"></div>
|
<div class="flex column grow" id="graphs">
|
||||||
|
<div class="controls">
|
||||||
|
<div class="center">
|
||||||
|
Intervall
|
||||||
|
<ln-slider
|
||||||
|
v-model="graphInterval"
|
||||||
|
v-bind:values="viewIntervals"
|
||||||
|
@change="loadGraphs(node,this.graphInterval,this.graphShift);"
|
||||||
|
></ln-slider>
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
Verschiebung
|
||||||
|
<ln-slider
|
||||||
|
v-bind:max="48 * graphInterval"
|
||||||
|
v-bind:step="graphInterval * 0.25"
|
||||||
|
v-model="graphShift"
|
||||||
|
@change="loadGraphs(node,this.graphInterval,this.graphShift);"
|
||||||
|
></ln-slider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,111 @@
|
||||||
SkyScanner.getInitializers().push(
|
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) => {
|
new Promise((resolve, reject) => {
|
||||||
LN().load("/vue/ln.skyscanner.node.html").
|
LN().load("/vue/ln.skyscanner.node.html").
|
||||||
then((template) => {
|
then((template) => {
|
||||||
|
@ -7,14 +114,38 @@
|
||||||
path: "/vue/nodes/:nodeID",
|
path: "/vue/nodes/:nodeID",
|
||||||
component: {
|
component: {
|
||||||
template: template,
|
template: template,
|
||||||
data: function () { return { node: null }; },
|
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) {
|
beforeRouteEnter: function (to, from, next) {
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
skyscanner.loadNode(to.params.nodeID, (node) => {
|
skyscanner.loadNode(to.params.nodeID, (node) => {
|
||||||
vm.node = node;
|
vm.node = node;
|
||||||
vm.$nextTick(() => {
|
vm.$nextTick(() => {
|
||||||
skyscanner.buildGraphs(node);
|
skyscanner.buildGraphs(node);
|
||||||
loadGraphs(node);
|
loadGraphs(node,vm.graphInterval,vm.graphShift);
|
||||||
});
|
});
|
||||||
}, 10000);
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
@ -137,14 +268,13 @@ function toSI(value, perfUnit) {
|
||||||
return `${nValue}${prefix}`;
|
return `${nValue}${prefix}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadGraphs(node) {
|
function loadGraphs(node,viewInterval,graphShift) {
|
||||||
for (group in node._graphs) {
|
for (group in node._graphs) {
|
||||||
if (!node._graphs.hasOwnProperty(group)) continue;
|
if (!node._graphs.hasOwnProperty(group)) continue;
|
||||||
|
|
||||||
let dataSets = [];
|
let dataSets = [];
|
||||||
let yScales = [];
|
let yScales = [];
|
||||||
|
|
||||||
let perfValueDict = {};
|
|
||||||
|
|
||||||
for (perfUnit in node._graphs[group]) {
|
for (perfUnit in node._graphs[group]) {
|
||||||
if (!node._graphs[group].hasOwnProperty(perfUnit)) continue;
|
if (!node._graphs[group].hasOwnProperty(perfUnit)) continue;
|
||||||
|
@ -183,6 +313,7 @@ function loadGraphs(node) {
|
||||||
dataSets.push({
|
dataSets.push({
|
||||||
perfName: perfName,
|
perfName: perfName,
|
||||||
perfUnit: perfUnit,
|
perfUnit: perfUnit,
|
||||||
|
perfValue: perfValue,
|
||||||
label: perfName + (perfUnit ? " [" + perfUnit + "]" : ""),
|
label: perfName + (perfUnit ? " [" + perfUnit + "]" : ""),
|
||||||
data: [],
|
data: [],
|
||||||
borderColor: color,
|
borderColor: color,
|
||||||
|
@ -191,28 +322,32 @@ function loadGraphs(node) {
|
||||||
yAxisID: perfUnit,
|
yAxisID: perfUnit,
|
||||||
});
|
});
|
||||||
|
|
||||||
perfValueDict[perfName] = perfValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let chart = getOrCreateChart(`chart-${group}`, yScales, dataSets);
|
let chart = getOrCreateChart(`chart-${group}`, yScales, dataSets);
|
||||||
chart.options.title.text = `${group}`;
|
chart.options.title.text = `${group}`;
|
||||||
|
|
||||||
chart.data.datasets.forEach((dataSet) => {
|
loadChartLines(chart, viewInterval,graphShift);
|
||||||
console.log("dataSet: " + dataSet.perfName);
|
|
||||||
loadChartLine(chart, dataSet, perfValueDict[dataSet.perfName]);
|
|
||||||
});
|
|
||||||
|
|
||||||
chart.update();
|
chart.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadChartLine(chart, dataSet, perfValue) {
|
function loadChartLines(chart, viewInterval, graphShift){
|
||||||
console.log("loadChartLine()");
|
if (!viewInterval)
|
||||||
|
return;
|
||||||
|
|
||||||
skyscanner.loadPerformanceGraph(perfValue.PerfPath, 3600, (perfData) => {
|
chart.data.datasets.forEach((dataSet) => {
|
||||||
console.log("loadPerformaceGraph(): callback");
|
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 chartColor = perfValue.CheckState == "CRITICAL" ? '#C00000' : (perfValue.CheckState == "WARN") ? '#C0C000' : '#008000';
|
||||||
let perfName = perfValue.PerfName;
|
let perfName = perfValue.PerfName;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,8 @@
|
||||||
|
|
||||||
<div id="footer" class="flex row">
|
<div id="footer" class="flex row">
|
||||||
<div id="ServerString" class="silver" style="">{{ serverString }}</div>
|
<div id="ServerString" class="silver" style="">{{ serverString }}</div>
|
||||||
|
<div id="CurrentActionLabel">{{ currentAction }}</div>
|
||||||
|
<div id="CurrentStateLabel">{{ currentState }}</div>
|
||||||
<div class="grow"></div>
|
<div class="grow"></div>
|
||||||
<div id="ServerTime" class="" style="margin-right: 12px;">{{ serverTime }}</div>
|
<div id="ServerTime" class="" style="margin-right: 12px;">{{ serverTime }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue