我正在使用HighCharts为时间序列数据编写一个简单的查看器。可能发生的一个问题是值可能会停止进入一段时间,然后恢复。在我的系统上,这些值最终会进入数据库,我不会丢失它们,它们只会被延迟。我想要的UI是它在数据进入时每秒正常滚动一次(如果工作正常)。如果数据停止,UI应该暂停滚动(这也有效)。如果数据可用性稍后恢复,那么我希望图表能够填充"间隙填充",即填充在不可用期间错过的部分。
这就是我现在想要解决的问题。我发出一个同步$ .ajax调用来获取丢失的数据,但返回的数据是页面本身的HTML,而不是JSON。我已经测试了服务器端调用,并且从直接从浏览器调用时返回JSON正常。所以任何人都可以看到我的差距填补"阴谋?请参阅注释" data2由于某种原因,这里是HTML而不是JSON"在下面的代码中,它出错了。
谢谢你, 维吉尔
<!doctype html>
<html lang="en">
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script>
function log(msg) {
if ( window.console && window.console.log ) {
console.log(msg)
}
}
function pauseBtnHandler() {
pauseChart = !pauseChart
if (pauseChart) {
$('#pauseBtn').val('Resume Display')
}
else {
$('#pauseBtn').val('Pause Display')
}
}
function timestampToLocaldate(timestamp) {
return new Date(timestamp - TIMEZONE_OFFSET)
}
$(function () {
$(document).ready(function() {
$.ajaxSetup({ cache: false })
pauseChart = false
prevTimestamp = 0
prevScroll = true
dataStoppedTimestamp = false
// get localtime offset in minutes, then convert to ms for use with charting
offset = new Date().getTimezoneOffset()
TIMEZONE_OFFSET = -offset * 60 * 1000
SAMPLE_PERIOD = 1000
// Do an initial query to get the current latest timestamp (in ms since Epoch)
jQuery.ajax({
url: '/mgmt/currentValues',
success: function(data) {
now = data['timestamp'] * 1000 + TIMEZONE_OFFSET
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error getting initial timestamp, defaulting time to now ' + thrownError)
now = new Date().getTime()
},
async: false
});
var chart;
$('#chart').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
backgroundColor:
{
linearGradient: [0, 0, 0, 500],
stops: [
[0, 'rgb(160, 160, 160)'],
[1, 'rgb(0, 0, 0)']
]
},
events: {
load: function() {
var series1 = this.series[0];
setInterval(function() {
$.get("mgmt/currentValues",function(data, status){
if (!pauseChart) {
var timestamp = data['timestamp'] * 1000 + TIMEZONE_OFFSET
// Only scroll the chart if a more recent value has come in
dt = timestamp - prevTimestamp
var scroll = (dt > 0)
if (!scroll) {
dataStoppedTimestamp = timestamp
}
// Determine if gap fill required
if (prevScroll == false && scroll == true && dt > SAMPLE_PERIOD) {
log('doing gapfill from ' + timestampToLocaldate(dataStoppedTimestamp) + ' to ' + timestampToLocaldate(timestamp))
jQuery.ajax({
url:'/mgmt/getdatafortimeperiod/%d/%d' % (dataStoppedTimestamp, timestamp),
success: function(data2) {
// data2 here is HTML not JSON for some reason
log(data2)
for (row2 in data2) {
var timestampGf = row2['timestamp'] * 1000 + TIMEZONE_OFFSET
series1.addPoint([timestampGf, row2['cpuPct']], false, true)
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error getting gapfill data ' + thownError)
},
async: false
});
}
series1.addPoint([timestamp, data['cpuPct']], scroll, true)
log(timestampToLocaldate(timestamp) + ' ' + data['cpuPct'])
prevTimestamp = timestamp
prevScroll = scroll
}
});
}, SAMPLE_PERIOD);
}
}
},
title: {
text: 'PERFORMANCE DATA',
style: {
color: 'black',
fontWeight: 'bold',
fontSize: '1.5em',
fontFamily: 'Arial',
}
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
labels: {
style: {
color: 'white',
fontFamily: 'Arial',
},
}
},
yAxis: [{
lineWidth: 1,
min: 0,
labels: {
style: {
color: 'white',
fontFamily: 'Arial',
},
},
title: {
text: 'CPU (%)',
style: {
color: 'white',
fontWeight: 'bold',
fontSize: '16px',
fontFamily: 'Arial',
}
}
}],
tooltip: {
formatter: function() {
str = '<b>'+ this.series.name +'</b><br/>'+
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
Highcharts.numberFormat(this.y, 0);
return str;
}
},
legend: {
enabled: true,
itemStyle: {
color: 'white',
font: 20,
},
backgroundColor: '#1C1C1C',
margin: 30,
itemDistance: 22,
symbolWidth:22,
symbolHeight:16,
},
exporting: {
enabled: true
},
series: [{
name: 'CPU %',
color: '#FF0000',
data: (function() {
// generate an initial array of data
var data = [],
time = now,
i;
for (i = -39; i <= 0; i++) {
data.push({
x: time + i * SAMPLE_PERIOD,
y: 0
});
}
return data;
})()
},
]
});
});
});
</script>
</head>
<body>
<div id="graph">
<div id="chart" style="; height: 100%; margin: 0 auto; "></div>
<div id="pauseButton">
<input id="pauseBtn" type="submit" value="Pause Display" onclick="pauseBtnHandler();">
</div>
</div>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script>
function log(msg) {
if ( window.console && window.console.log ) {
console.log(msg)
}
}
function pauseBtnHandler() {
pauseChart = !pauseChart
if (pauseChart) {
$('#pauseBtn').val('Resume Display')
}
else {
$('#pauseBtn').val('Pause Display')
}
}
function timestampToLocaldate(timestamp) {
return new Date(timestamp - TIMEZONE_OFFSET)
}
$(function () {
$(document).ready(function() {
$.ajaxSetup({ cache: false })
pauseChart = false
prevTimestamp = 0
prevScroll = true
dataStoppedTimestamp = false
// get localtime offset in minutes, then convert to ms for use with charting
offset = new Date().getTimezoneOffset()
TIMEZONE_OFFSET = -offset * 60 * 1000
SAMPLE_PERIOD = 1000
// Do an initial query to get the current latest timestamp (in ms since Epoch)
jQuery.ajax({
url: '/mgmt/currentValues',
success: function(data) {
now = data['timestamp'] * 1000 + TIMEZONE_OFFSET
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error getting initial timestamp, defaulting time to now ' + thrownError)
now = new Date().getTime()
},
async: false
});
var chart;
$('#chart').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
backgroundColor:
{
linearGradient: [0, 0, 0, 500],
stops: [
[0, 'rgb(160, 160, 160)'],
[1, 'rgb(0, 0, 0)']
]
},
events: {
load: function() {
var series1 = this.series[0];
setInterval(function() {
$.get("mgmt/currentValues",function(data, status){
if (!pauseChart) {
var timestamp = data['timestamp'] * 1000 + TIMEZONE_OFFSET
// Only scroll the chart if a more recent value has come in
dt = timestamp - prevTimestamp
var scroll = (dt > 0)
if (!scroll) {
dataStoppedTimestamp = timestamp
}
// Determine if gap fill required
if (prevScroll == false && scroll == true && dt > SAMPLE_PERIOD) {
log('doing gapfill from ' + timestampToLocaldate(dataStoppedTimestamp) + ' to ' + timestampToLocaldate(timestamp))
jQuery.ajax({
url:'/mgmt/getdatafortimeperiod/%d/%d' % (dataStoppedTimestamp, timestamp),
success: function(data2) {
// data2 here is HTML not JSON for some reason
log(data2)
for (row2 in data2) {
var timestampGf = row2['timestamp'] * 1000 + TIMEZONE_OFFSET
series1.addPoint([timestampGf, row2['cpuPct']], false, true)
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Error getting gapfill data ' + thownError)
},
async: false
});
}
series1.addPoint([timestamp, data['cpuPct']], scroll, true)
log(timestampToLocaldate(timestamp) + ' ' + data['cpuPct'])
prevTimestamp = timestamp
prevScroll = scroll
}
});
}, SAMPLE_PERIOD);
}
}
},
title: {
text: 'PERFORMANCE DATA',
style: {
color: 'black',
fontWeight: 'bold',
fontSize: '1.5em',
fontFamily: 'Arial',
}
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150,
labels: {
style: {
color: 'white',
fontFamily: 'Arial',
},
}
},
yAxis: [{
lineWidth: 1,
min: 0,
labels: {
style: {
color: 'white',
fontFamily: 'Arial',
},
},
title: {
text: 'CPU (%)',
style: {
color: 'white',
fontWeight: 'bold',
fontSize: '16px',
fontFamily: 'Arial',
}
}
}],
tooltip: {
formatter: function() {
str = '<b>'+ this.series.name +'</b><br/>'+
Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
Highcharts.numberFormat(this.y, 0);
return str;
}
},
legend: {
enabled: true,
itemStyle: {
color: 'white',
font: 20,
},
backgroundColor: '#1C1C1C',
margin: 30,
itemDistance: 22,
symbolWidth:22,
symbolHeight:16,
},
exporting: {
enabled: true
},
series: [{
name: 'CPU %',
color: '#FF0000',
data: (function() {
// generate an initial array of data
var data = [],
time = now,
i;
for (i = -39; i <= 0; i++) {
data.push({
x: time + i * SAMPLE_PERIOD,
y: 0
});
}
return data;
})()
},
]
});
});
});
</script>
</head>
<body>
<div id="graph">
<div id="chart" style="; height: 100%; margin: 0 auto; "></div>
<div id="pauseButton">
<input id="pauseBtn" type="submit" value="Pause Display" onclick="pauseBtnHandler();">
</div>
</div>
</body>
</html>
答案 0 :(得分:0)
发现问题,非常基本。我使用Python样式的sprintf格式来生成gapfill URL。我脑子里的Python太多了。