Made some improvements to how server statistics are displayed.
This commit is contained in:
parent
a11ecf4140
commit
9b8eaa7aa7
4 changed files with 194 additions and 71 deletions
|
@ -13,6 +13,14 @@ $default_timezone = 'Europe/Amsterdam';
|
|||
// What is your site name?
|
||||
$a->config['sitename'] = "EXPERIMENTAL Friendica public directory";
|
||||
|
||||
//Statistic display settings.
|
||||
$a->config['stats'] = array(
|
||||
|
||||
//For site health, the max age for which to display data.
|
||||
'maxDataAge' => 3600*24*30*4 //120 days = ~4 months
|
||||
|
||||
);
|
||||
|
||||
//Settings related to the syncing feature.
|
||||
$a->config['syncing'] = array(
|
||||
|
||||
|
@ -46,7 +54,7 @@ $a->config['site-health'] = array(
|
|||
//Wait for at least ... before probing a site again.
|
||||
//The longer this value, the more "stable" site-healths will be over time.
|
||||
//Note: If a bad (negative) health site submits something, a probe will be performed regardless.
|
||||
'min_probe_delay' => 3*24*3600, // 3 days
|
||||
'min_probe_delay' => 24*3600, // 1 day
|
||||
|
||||
//Probes get a simple /friendica/json file from the server.
|
||||
//Feel free to set this timeout to a very tight value.
|
||||
|
|
81
include/smoothing.js
Normal file
81
include/smoothing.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
(function(){
|
||||
|
||||
window.Smoothing = {
|
||||
|
||||
/**
|
||||
* Applies both a moving average bracket and and exponential smoothing.
|
||||
* @param {array} raw The raw Y values.
|
||||
* @param {float} factor The exponential smoothing factor to apply (between o and 1).
|
||||
* @param {int} bracket The amount of datapoints to add to the backet on each side! (2 = 5 data points)
|
||||
* @return {array} The smoothed Y values.
|
||||
*/
|
||||
exponentialMovingAverage: function(raw, factor, bracket){
|
||||
|
||||
var output = [];
|
||||
var smoother = new ExponentialSmoother(factor);
|
||||
|
||||
//Transform each data point with the smoother.
|
||||
for (var i = 0; i < raw.length; i++){
|
||||
|
||||
var input = raw[i];
|
||||
|
||||
//See if we should bracket.
|
||||
if(bracket > 0){
|
||||
|
||||
//Cap our start and end so it doesn't go out of bounds.
|
||||
var start = Math.max(i-bracket, 0);
|
||||
var end = Math.min(i+bracket, raw.length);
|
||||
|
||||
//Push the range to our input.
|
||||
input = [];
|
||||
for(var j = start; j < end; j++){
|
||||
input.push(raw[j]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
output.push(
|
||||
smoother.transform(input)
|
||||
);
|
||||
};
|
||||
|
||||
return output;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Exponential Smoother class.
|
||||
var ExponentialSmoother = function(factor){
|
||||
this.currentValue = null;
|
||||
this.smoothingFactor = factor || 1;
|
||||
};
|
||||
|
||||
ExponentialSmoother.prototype.transform = function(input){
|
||||
|
||||
// In case our input is a bracket, first average it.
|
||||
if(input.length){
|
||||
var len = input.length;
|
||||
var sum = 0;
|
||||
for (var i = input.length - 1; i >= 0; i--)
|
||||
sum += input[i]
|
||||
input = sum/len;
|
||||
}
|
||||
|
||||
// Start with our initial value.
|
||||
if(this.currentValue === null){
|
||||
this.currentValue = input;
|
||||
}
|
||||
|
||||
// Our output is basically an updated value.
|
||||
return this.currentValue =
|
||||
|
||||
// Weigh our current value with the smoothing factor.
|
||||
(this.currentValue * this.smoothingFactor) +
|
||||
|
||||
// Add the input to it with the inverse value of the smoothing factor.
|
||||
( (1-this.smoothingFactor) * input );
|
||||
|
||||
};
|
||||
|
||||
})();
|
167
mod/health.php
167
mod/health.php
|
@ -129,6 +129,42 @@ function health_summary(&$a){
|
|||
function health_details($a, $id)
|
||||
{
|
||||
|
||||
//Max data age in MySQL date.
|
||||
$maxDate = date('Y-m-d H:i:s', time()-($a->config['stats']['maxDataAge']));
|
||||
|
||||
//Include graphael line charts.
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/smoothing.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/raphael.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/g.raphael.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/g.line-min.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript">
|
||||
window.smoothingFactor = 0.3;
|
||||
window.smoothingBracket = 2;
|
||||
window.availableCharts = [];
|
||||
window.drawRaw = false;
|
||||
window.drawCharts = function(){
|
||||
for (var i = availableCharts.length - 1; i >= 0; i--) {
|
||||
availableCharts[i](jQuery);
|
||||
};
|
||||
};
|
||||
window.onHoverPoint = function(r){ return function(){
|
||||
this.tags = r.set();
|
||||
var i = this.y.length-1;
|
||||
this.tags.push(r.popup(this.x, this.y[i], Math.round(this.values[i])+"ms", "right", 5).insertBefore(this));
|
||||
}};
|
||||
window.onUnHoverPoint = function(r){ return function(){
|
||||
this.tags && this.tags.remove();
|
||||
}};
|
||||
jQuery(function($){
|
||||
drawCharts();
|
||||
$(".js-toggle-raw").click(function(e){
|
||||
e.preventDefault();
|
||||
drawRaw=!drawRaw;
|
||||
drawCharts();
|
||||
});
|
||||
});
|
||||
</script>';
|
||||
|
||||
//The overall health status.
|
||||
$r = q(
|
||||
"SELECT * FROM `site-health`
|
||||
|
@ -196,62 +232,14 @@ function health_details($a, $id)
|
|||
|
||||
//Get probe speed data.
|
||||
$r = q(
|
||||
"SELECT `request_time`, `dt_performed` FROM `site-probe`
|
||||
WHERE `site_health_id` = %u",
|
||||
intval($site['id'])
|
||||
"SELECT AVG(`request_time`) as `avg_time`, date(`dt_performed`) as `date` FROM `site-probe`
|
||||
WHERE `site_health_id` = %u
|
||||
AND `dt_performed` > '%s'
|
||||
GROUP BY `date`",
|
||||
intval($site['id']),
|
||||
$maxDate
|
||||
);
|
||||
if(count($r)){
|
||||
//Include graphael line charts.
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/raphael.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/g.raphael.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/g.line-min.js"></script>';
|
||||
$speeds = array();
|
||||
$times = array();
|
||||
$mintime = time();
|
||||
foreach($r as $row){
|
||||
$speeds[] = $row['request_time'];
|
||||
$time = strtotime($row['dt_performed']);
|
||||
$times[] = $time;
|
||||
if($mintime > $time) $mintime = $time;
|
||||
}
|
||||
for($i=0; $i < count($times); $i++){
|
||||
$times[$i] -= $mintime;
|
||||
$times[$i] = floor($times[$i] / (24*3600));
|
||||
}
|
||||
$a->page['htmlhead'] .=
|
||||
'<script type="text/javascript">
|
||||
jQuery(function($){
|
||||
|
||||
var r = Raphael("probe-chart")
|
||||
, x = ['.implode(',', $times).']
|
||||
, y = ['.implode(',', $speeds).']
|
||||
;
|
||||
|
||||
r.linechart(30, 15, 400, 300, x, [y], {symbol:"circle", axis:"0 0 0 1", shade:true, width:1.5}).hoverColumn(function () {
|
||||
this.tags = r.set();
|
||||
for (var i = 0, ii = this.y.length; i < ii; i++) {
|
||||
this.tags.push(r.popup(this.x, this.y[i], this.values[i]+"ms", "right", 5).insertBefore(this).attr([{ fill: "#eee" }, { fill: this.symbols[i].attr("fill") }]));
|
||||
}
|
||||
}, function () {
|
||||
this.tags && this.tags.remove();
|
||||
});
|
||||
|
||||
});
|
||||
</script>';
|
||||
}
|
||||
|
||||
//Get scrape speed data.
|
||||
$r = q(
|
||||
"SELECT AVG(`total_time`) as `avg_time`, date(`dt_performed`) as `date` FROM `site-scrape`
|
||||
WHERE `site_health_id` = %u GROUP BY `date`",
|
||||
intval($site['id'])
|
||||
// date('Y-m-d H:i:s', time()-(3*24*3600)) //Max 3 days old.
|
||||
);
|
||||
if($r && count($r)){
|
||||
//Include graphael line charts.
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/raphael.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/g.raphael.js"></script>'.PHP_EOL;
|
||||
$a->page['htmlhead'] .= '<script type="text/javascript" src="'.$a->get_baseurl().'/include/g.line-min.js"></script>';
|
||||
$speeds = array();
|
||||
$times = array();
|
||||
$mintime = time();
|
||||
|
@ -267,21 +255,66 @@ function health_details($a, $id)
|
|||
}
|
||||
$a->page['htmlhead'] .=
|
||||
'<script type="text/javascript">
|
||||
jQuery(function($){
|
||||
availableCharts.push(function($){
|
||||
|
||||
var r = Raphael("scrape-chart")
|
||||
, x = ['.implode(',', $times).']
|
||||
, y = ['.implode(',', $speeds).']
|
||||
;
|
||||
var id = "probe-chart";
|
||||
$("#"+id+" svg").remove();
|
||||
var r = Raphael(id);
|
||||
var x = ['.implode(',', $times).'];
|
||||
var y = ['.implode(',', $speeds).'];
|
||||
var smoothY = Smoothing.exponentialMovingAverage(y, smoothingFactor, smoothingBracket);
|
||||
var values = [smoothY];
|
||||
if(drawRaw){
|
||||
values.push(y);
|
||||
}
|
||||
|
||||
r.linechart(30, 15, 400, 300, x, [y], {shade:true, axis:"0 0 0 1", width:1}).hoverColumn(function () {
|
||||
this.tags = r.set();
|
||||
for (var i = 0, ii = this.y.length; i < ii; i++) {
|
||||
this.tags.push(r.popup(this.x, this.y[i], Math.round(this.values[i])+"ms", "right", 5).insertBefore(this));
|
||||
}
|
||||
}, function () {
|
||||
this.tags && this.tags.remove();
|
||||
});
|
||||
r.linechart(30, 15, 400, 300, x, values, {axis:"0 0 0 1", shade:true, width:0.8})
|
||||
.hoverColumn(onHoverPoint(r), onUnHoverPoint(r));
|
||||
|
||||
});
|
||||
</script>';
|
||||
}
|
||||
|
||||
//Get scrape speed data.
|
||||
$r = q(
|
||||
"SELECT AVG(`total_time`) as `avg_time`, date(`dt_performed`) as `date` FROM `site-scrape`
|
||||
WHERE `site_health_id` = %u
|
||||
AND `dt_performed` > '%s'
|
||||
GROUP BY `date`",
|
||||
intval($site['id']),
|
||||
$maxDate
|
||||
);
|
||||
if($r && count($r)){
|
||||
$speeds = array();
|
||||
$times = array();
|
||||
$mintime = time();
|
||||
foreach($r as $row){
|
||||
$speeds[] = $row['avg_time'];
|
||||
$time = strtotime($row['date']);
|
||||
$times[] = $time;
|
||||
if($mintime > $time) $mintime = $time;
|
||||
}
|
||||
for($i=0; $i < count($times); $i++){
|
||||
$times[$i] -= $mintime;
|
||||
$times[$i] = floor($times[$i] / (24*3600));
|
||||
}
|
||||
$a->page['htmlhead'] .=
|
||||
'<script type="text/javascript">
|
||||
availableCharts.push(function($){
|
||||
|
||||
var id = "scrape-chart";
|
||||
$("#"+id+" svg").remove();
|
||||
var r = Raphael(id);
|
||||
var x = ['.implode(',', $times).'];
|
||||
var y = ['.implode(',', $speeds).'];
|
||||
var smoothY = Smoothing.exponentialMovingAverage(y, smoothingFactor, smoothingBracket);
|
||||
var values = [smoothY];
|
||||
if(drawRaw){
|
||||
values.push(y);
|
||||
}
|
||||
|
||||
r.linechart(30, 15, 400, 300, x, values, {shade:true, axis:"0 0 0 1", width:0.8})
|
||||
.hoverColumn(onHoverPoint(r), onUnHoverPoint(r));
|
||||
|
||||
});
|
||||
</script>';
|
||||
|
|
|
@ -28,8 +28,9 @@
|
|||
<div class="profile_speed">Profile speed: $avg_profile_timems</div>
|
||||
<div class="scrape_speed">Scrape speed: $avg_scrape_timems</div>
|
||||
<div class="submit_speed">Submit speed: $avg_submit_timems</div>
|
||||
<span class="health perfect">$no_scrape_support</span>
|
||||
<span class="health perfect">$no_scrape_support</span><br>
|
||||
<a href="javascript:;" class="js-toggle-raw">Toggle raw data</a>
|
||||
</div>
|
||||
<div id="probe-chart" class="speed-chart">Probe speed</div>
|
||||
<div id="scrape-chart" class="speed-chart">Submit speed</div>
|
||||
<div id="probe-chart" class="speed-chart">Probe speed in ms<br>(last 120 days)</div>
|
||||
<div id="scrape-chart" class="speed-chart">Submit speed in ms<br>(last 120 days)</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue