Added graph Intervall, Shift Sliders

master
Harald Wolff 2019-10-15 12:20:36 +02:00
parent f6d962ed5e
commit e6d6b16430
8 changed files with 215 additions and 24 deletions

View File

@ -17,11 +17,14 @@ namespace ln.skyscanner.checks
{
public enum CheckState { OK, WARN, CRITICAL, FAIL, ERROR }
public struct CheckStateChange
public class CheckStateChange
{
public CheckState NewState;
public DateTime Timestamp;
private CheckStateChange()
{
}
public CheckStateChange(CheckState checkState)
{
NewState = checkState;

View File

@ -108,11 +108,11 @@ namespace ln.skyscanner.services
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.EnsureOpen();
PerfValue[] perfData = perfFile.QueryTime(timeWindow, 0);
PerfValue[] perfData = perfFile.QueryTime(timeWindow, timeSkip);
return perfData;
}
}

View File

@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.application", "..\ln.app
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.json", "..\ln.json\ln.json.csproj", "{D9342117-3249-4D8B-87C9-51A50676B158}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "odb.tool", "..\odb.tool\odb.tool.csproj", "{24C9C372-DCA6-420D-ACD3-5C89C6935D6A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
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}.Release|x86.ActiveCfg = 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
EndGlobal

View File

@ -481,4 +481,12 @@ span#nWARN, span#nCRITICAL, span#nOK {
text-decoration: underline;
}
input.ln-slider {
display: block;
width: 100%;
}
div.ln-slider {
width: 360px;
text-align: center;
}

View File

@ -28,6 +28,9 @@
this.currentNodes = [];
this.currentAction = "";
this.currentState = "";
this.issues = {
OK: 0,
WARN: 0,
@ -50,6 +53,14 @@
return initializers;
}
action(msg){
this.currentAction = msg;
}
state(msg){
this.currentState = msg;
}
wsUpdate(state)
{
try
@ -80,11 +91,12 @@
updateIssues(){
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){
alert("Error fetching current issue list!\n" + JSON.stringify(e));
self.state("Error fetching current issue list!\n" + JSON.stringify(e));
} else {
self.currentIssues = r;
@ -103,6 +115,7 @@
self.lastIssueUpdate = moment().format();
}
self.currentTimeout = setTimeout(function(){ self.updateIssues(); }, 10000);
this.action("");
});
}
@ -153,7 +166,9 @@
loadNode(nodeID,cb,refreshIntervall){
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)
clearTimeout(self.currentTimeout);
@ -164,6 +179,8 @@
setTimeout(()=>{
self.loadNode(nodeID,cb,refreshIntervall);
}, refreshIntervall);
this.action("");
});
}
@ -172,8 +189,8 @@
return ("" + t).replace( /[\.\/]/g, "_");
}
loadPerformanceGraph(perfPath,interval,cb){
LN().rpc("perfValues","GetPerfData",[perfPath,interval],(perfData,e)=>{
loadPerformanceGraph(perfPath,interval,shift,cb){
LN().rpc("perfValues","GetPerfData",[perfPath,interval,shift],(perfData,e)=>{
if (e){
console.log(e);
} else {

View File

@ -63,7 +63,27 @@
<textarea>{{ JSON.stringify( node ) }}</textarea>
</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>

View File

@ -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) => {
LN().load("/vue/ln.skyscanner.node.html").
then((template) => {
@ -7,14 +114,38 @@
path: "/vue/nodes/:nodeID",
component: {
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) {
next((vm) => {
skyscanner.loadNode(to.params.nodeID, (node) => {
vm.node = node;
vm.$nextTick(() => {
skyscanner.buildGraphs(node);
loadGraphs(node);
loadGraphs(node,vm.graphInterval,vm.graphShift);
});
}, 10000);
});
@ -137,14 +268,13 @@ function toSI(value, perfUnit) {
return `${nValue}${prefix}`;
}
function loadGraphs(node) {
function loadGraphs(node,viewInterval,graphShift) {
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;
@ -183,6 +313,7 @@ function loadGraphs(node) {
dataSets.push({
perfName: perfName,
perfUnit: perfUnit,
perfValue: perfValue,
label: perfName + (perfUnit ? " [" + perfUnit + "]" : ""),
data: [],
borderColor: color,
@ -191,28 +322,32 @@ function loadGraphs(node) {
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]);
});
loadChartLines(chart, viewInterval,graphShift);
chart.update();
}
}
function loadChartLine(chart, dataSet, perfValue) {
console.log("loadChartLine()");
function loadChartLines(chart, viewInterval, graphShift){
if (!viewInterval)
return;
skyscanner.loadPerformanceGraph(perfValue.PerfPath, 3600, (perfData) => {
console.log("loadPerformaceGraph(): callback");
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;

View File

@ -57,6 +57,8 @@
<div id="footer" class="flex row">
<div id="ServerString" class="silver" style="">{{ serverString }}</div>
<div id="CurrentActionLabel">{{ currentAction }}</div>
<div id="CurrentStateLabel">{{ currentState }}</div>
<div class="grow"></div>
<div id="ServerTime" class="" style="margin-right: 12px;">{{ serverTime }}</div>
</div>