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 struct CheckStateChange
|
||||
public class CheckStateChange
|
||||
{
|
||||
public CheckState NewState;
|
||||
public DateTime Timestamp;
|
||||
|
||||
private CheckStateChange()
|
||||
{
|
||||
}
|
||||
public CheckStateChange(CheckState checkState)
|
||||
{
|
||||
NewState = checkState;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue