Increased graph data processing speed (#944)
parent
c090a398d1
commit
9fe598d774
|
@ -6,6 +6,7 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^5.5.9|>=7.0.8",
|
"php": "^5.5.9|>=7.0.8",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
|
"ext-json": "*",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ext-xml": "*",
|
"ext-xml": "*",
|
||||||
"phpmailer/phpmailer": ">=6.0.6 ~6.0",
|
"phpmailer/phpmailer": ">=6.0.6 ~6.0",
|
||||||
|
|
|
@ -29,7 +29,10 @@
|
||||||
|
|
||||||
namespace psm\Util\Server;
|
namespace psm\Util\Server;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
use psm\Service\Database;
|
use psm\Service\Database;
|
||||||
|
use Twig\Error\Error;
|
||||||
|
use Twig_Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* History util, create HTML for server graphs
|
* History util, create HTML for server graphs
|
||||||
|
@ -39,17 +42,17 @@ class HistoryGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database service
|
* Database service
|
||||||
* @var \psm\Service\Database $db;
|
* @var Database $db;
|
||||||
*/
|
*/
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Twig environment
|
* Twig environment
|
||||||
* @var \Twig_Environment $twig
|
* @var Twig_Environment $twig
|
||||||
*/
|
*/
|
||||||
protected $twig;
|
protected $twig;
|
||||||
|
|
||||||
public function __construct(Database $db, \Twig_Environment $twig)
|
public function __construct(Database $db, Twig_Environment $twig)
|
||||||
{
|
{
|
||||||
$this->db = $db;
|
$this->db = $db;
|
||||||
$this->twig = $twig;
|
$this->twig = $twig;
|
||||||
|
@ -57,7 +60,9 @@ class HistoryGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare the HTML for the graph
|
* Prepare the HTML for the graph
|
||||||
* @return string
|
* @param string $server_id ID of server to fetch data for
|
||||||
|
* @return string Created HTML
|
||||||
|
* @throws Error On twig error
|
||||||
*/
|
*/
|
||||||
public function createHTML($server_id)
|
public function createHTML($server_id)
|
||||||
{
|
{
|
||||||
|
@ -65,9 +70,9 @@ class HistoryGraph
|
||||||
$archive = new ArchiveManager($this->db);
|
$archive = new ArchiveManager($this->db);
|
||||||
$archive->archive($server_id);
|
$archive->archive($server_id);
|
||||||
|
|
||||||
$now = new \DateTime();
|
$now = new DateTime();
|
||||||
$last_week = new \DateTime('-1 week 0:0:0');
|
$last_week = new DateTime('-1 week 0:0:0');
|
||||||
$last_year = new \DateTime('-1 year -1 week 0:0:0');
|
$last_year = new DateTime('-1 year -1 week 0:0:0');
|
||||||
|
|
||||||
$graphs = array(
|
$graphs = array(
|
||||||
0 => $this->generateGraphUptime($server_id, $last_week, $now),
|
0 => $this->generateGraphUptime($server_id, $last_week, $now),
|
||||||
|
@ -101,8 +106,8 @@ class HistoryGraph
|
||||||
/**
|
/**
|
||||||
* Generate data for uptime graph
|
* Generate data for uptime graph
|
||||||
* @param int $server_id
|
* @param int $server_id
|
||||||
* @param \DateTime $start_time Lowest DateTime of the graph
|
* @param DateTime $start_time Lowest DateTime of the graph
|
||||||
* @param \DateTime $end_time Highest DateTime of the graph
|
* @param DateTime $end_time Highest DateTime of the graph
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function generateGraphUptime($server_id, $start_time, $end_time)
|
public function generateGraphUptime($server_id, $start_time, $end_time)
|
||||||
|
@ -112,9 +117,9 @@ class HistoryGraph
|
||||||
'latency' => array(),
|
'latency' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$hour = new \DateTime('-1 hour');
|
$hour = new DateTime('-1 hour');
|
||||||
$day = new \DateTime('-1 day');
|
$day = new DateTime('-1 day');
|
||||||
$week = new \DateTime('-1 week');
|
$week = new DateTime('-1 week');
|
||||||
|
|
||||||
$records = $this->getRecords('uptime', $server_id, $start_time, $end_time);
|
$records = $this->getRecords('uptime', $server_id, $start_time, $end_time);
|
||||||
|
|
||||||
|
@ -148,8 +153,8 @@ class HistoryGraph
|
||||||
/**
|
/**
|
||||||
* Generate data for history graph
|
* Generate data for history graph
|
||||||
* @param int $server_id
|
* @param int $server_id
|
||||||
* @param \DateTime $start_time Lowest DateTime of the graph
|
* @param DateTime $start_time Lowest DateTime of the graph
|
||||||
* @param \DateTime $end_time Highest DateTime of the graph
|
* @param DateTime $end_time Highest DateTime of the graph
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function generateGraphHistory($server_id, $start_time, $end_time)
|
public function generateGraphHistory($server_id, $start_time, $end_time)
|
||||||
|
@ -160,9 +165,9 @@ class HistoryGraph
|
||||||
'latency_max' => array(),
|
'latency_max' => array(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$week = new \DateTime('-2 week 0:0:0');
|
$week = new DateTime('-2 week 0:0:0');
|
||||||
$month = new \DateTime('-1 month -1 week 0:0:0');
|
$month = new DateTime('-1 month -1 week 0:0:0');
|
||||||
$year = new \DateTime('-1 year -1 week 0:0:0');
|
$year = new DateTime('-1 year -1 week 0:0:0');
|
||||||
|
|
||||||
$records = $this->getRecords('history', $server_id, $year, $end_time);
|
$records = $this->getRecords('history', $server_id, $year, $end_time);
|
||||||
|
|
||||||
|
@ -197,8 +202,8 @@ class HistoryGraph
|
||||||
* Get all uptime/history records for a server
|
* Get all uptime/history records for a server
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @param int $server_id
|
* @param int $server_id
|
||||||
* @param \DateTime $start_time Lowest DateTime of the graph
|
* @param DateTime $start_time Lowest DateTime of the graph
|
||||||
* @param \DateTime $end_time Highest DateTime of the graph
|
* @param DateTime $end_time Highest DateTime of the graph
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getRecords($type, $server_id, $start_time, $end_time)
|
protected function getRecords($type, $server_id, $start_time, $end_time)
|
||||||
|
@ -207,17 +212,19 @@ class HistoryGraph
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$records = $this->db->execute(
|
/** @noinspection SqlNoDataSourceInspection */
|
||||||
"SELECT *
|
/** @noinspection SqlResolve */
|
||||||
|
/** @noinspection PhpUndefinedConstantInspection */
|
||||||
|
return $this->db->execute(
|
||||||
|
"SELECT *, UNIX_TIMESTAMP(CONVERT_TZ(`date`, '+00:00', @@session.time_zone)) AS date_ts
|
||||||
FROM `" . PSM_DB_PREFIX . "servers_$type`
|
FROM `" . PSM_DB_PREFIX . "servers_$type`
|
||||||
WHERE `server_id` = :server_id AND `date` BETWEEN :start_time AND :end_time ORDER BY `date` ASC",
|
WHERE `server_id` = :server_id AND `date` BETWEEN :start_time AND :end_time ORDER BY `date`",
|
||||||
array(
|
array(
|
||||||
'server_id' => $server_id,
|
'server_id' => $server_id,
|
||||||
'start_time' => $start_time->format('Y-m-d H:i:s'),
|
'start_time' => $start_time->format('Y-m-d H:i:s'),
|
||||||
'end_time' => $end_time->format('Y-m-d H:i:s'),
|
'end_time' => $end_time->format('Y-m-d H:i:s'),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return $records;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -225,12 +232,9 @@ class HistoryGraph
|
||||||
* @param array $records All uptime records to parse, MUST BE SORTED BY DATE IN ASCENDING ORDER
|
* @param array $records All uptime records to parse, MUST BE SORTED BY DATE IN ASCENDING ORDER
|
||||||
* @param array $lines Array with keys as line ids to prepare (key must be available in uptime records)
|
* @param array $lines Array with keys as line ids to prepare (key must be available in uptime records)
|
||||||
* @param string $latency_avg_key which key from uptime records to use for calculating averages
|
* @param string $latency_avg_key which key from uptime records to use for calculating averages
|
||||||
* @param \DateTime $start_time Lowest DateTime of the graph
|
* @param DateTime $start_time Lowest DateTime of the graph
|
||||||
* @param \DateTime $end_time Highest DateTime of the graph
|
* @param DateTime $end_time Highest DateTime of the graph
|
||||||
* @param boolean $add_uptime Add uptime calculation?
|
* @param boolean $add_uptime Add uptime calculation?
|
||||||
* @param array $prev Previous result
|
|
||||||
* @param int $downtime Total downtime
|
|
||||||
* @param int $prev_downtime Timestamp from last offline record. 0 when last record is uptime
|
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function generateGraphLines(
|
protected function generateGraphLines(
|
||||||
|
@ -241,79 +245,90 @@ class HistoryGraph
|
||||||
$end_time,
|
$end_time,
|
||||||
$add_uptime = false
|
$add_uptime = false
|
||||||
) {
|
) {
|
||||||
$now = new \DateTime();
|
$now = new DateTime();
|
||||||
$data = array();
|
$data = array();
|
||||||
|
|
||||||
// PLEASE NOTE: all times are in microseconds! because of javascript.
|
// PLEASE NOTE: all times are in microseconds! because of javascript.
|
||||||
$latency_avg = 0;
|
$latency_avg = 0;
|
||||||
|
|
||||||
|
/** @var array $prev Previous record */
|
||||||
$prev = reset($records);
|
$prev = reset($records);
|
||||||
|
|
||||||
|
// Timestamp from last offline record. 0 when last record is up.
|
||||||
$prev_downtime = 0;
|
$prev_downtime = 0;
|
||||||
|
// Total downtime
|
||||||
$downtime = 0;
|
$downtime = 0;
|
||||||
|
|
||||||
|
// The keys of the lines iterated
|
||||||
|
$line_keys = array_keys($lines);
|
||||||
|
// Determine whether to process data for the short history graph
|
||||||
|
$is_short_graph = count($line_keys) === 1 && $line_keys[0] === 'latency';
|
||||||
|
|
||||||
// get highest latency record for offline height
|
// get highest latency record for offline height
|
||||||
$n = count($records);
|
$highest_latency = 0.0;
|
||||||
$highest_latency = 0.0000;
|
if ($is_short_graph) {
|
||||||
for ($i = 0; $i < $n; $i++) {
|
foreach ($records as $record) {
|
||||||
if (!array_key_exists('latency', $records[$i])) {
|
$latency = (float) $record['latency'];
|
||||||
continue;
|
if ($latency > $highest_latency) {
|
||||||
|
$highest_latency = $latency;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Update if latency is higher
|
// to ms
|
||||||
$highest_latency = $highest_latency < floatval($records[$i]['latency']) ?
|
$highest_latency = round($highest_latency * 1000);
|
||||||
floatval($records[$i]['latency']) : $highest_latency;
|
|
||||||
}
|
}
|
||||||
// to ms
|
|
||||||
$highest_latency = round($highest_latency * 1000);
|
|
||||||
|
|
||||||
// Create the list of points and server down zones
|
// Create the list of points and server down zones
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
$time = strtotime($record['date']);
|
|
||||||
// use the first line to calculate average latency
|
// use the first line to calculate average latency
|
||||||
$latency_avg += (float) $record[$latency_avg_key];
|
$latency_avg += (float) $record[$latency_avg_key];
|
||||||
|
|
||||||
foreach ($lines as $key => $value) {
|
if ($is_short_graph) {
|
||||||
// add the value for each of the different lines
|
$time = (int) $record['date_ts'];
|
||||||
if (isset($record[$key])) {
|
// Timestamp in milliseconds
|
||||||
if (isset($record['status'])) {
|
$time_ms = $time * 1000;
|
||||||
// down
|
if (!$record['status']) {
|
||||||
if ($record['status'] == 0) {
|
// down
|
||||||
$lines['online'][] = $prev['status']
|
$lines['online'][] = $prev['status']
|
||||||
// Previous datapoint was online
|
// Previous datapoint was online
|
||||||
? '{ x: ' . ($time * 1000) . ', y: ' . $prev['latency'] * 1000 . '}'
|
? ['x' => $time_ms, 'y' => round($prev['latency'] * 1000, 3)]
|
||||||
// Previous datapoint was offline
|
// Previous datapoint was offline
|
||||||
: '{ x: ' . ($time * 1000) . ', y: null}';
|
: ['x' => $time_ms, 'y' => null];
|
||||||
// new outage start
|
// new outage start
|
||||||
$lines['offline'][] = '{ x: ' . ($time * 1000) . ', y:' . $highest_latency . '}';
|
$lines['offline'][] = ['x' => $time_ms, 'y' => $highest_latency];
|
||||||
|
|
||||||
$prev_downtime != 0 ?: $prev_downtime = $time;
|
if ($prev_downtime === 0) {
|
||||||
} else {
|
$prev_downtime = $time;
|
||||||
// up
|
|
||||||
// outage ends
|
|
||||||
$lines['offline'][] = $prev['status']
|
|
||||||
// Previous datapoint was online
|
|
||||||
? '{ x: ' . ($time * 1000) . ', y:null}'
|
|
||||||
// Previous datapoint was offline
|
|
||||||
: '{ x: ' . ($time * 1000) . ', y:' . $highest_latency . '}';
|
|
||||||
$lines['online'][] = '{ x: ' . ($time * 1000) . ', y: ' .
|
|
||||||
round((float) $record[$key] * 1000, 2) . '}';
|
|
||||||
|
|
||||||
$prev_downtime == 0 ?: $downtime += ($time - $prev_downtime);
|
|
||||||
$prev_downtime = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$lines[$key][] = '{ x: \'' . $record['date'] . '\', y: ' . $record[$key] * 1000 . '}';
|
|
||||||
}
|
}
|
||||||
$prev = $record;
|
} else {
|
||||||
|
// up
|
||||||
|
// outage ends
|
||||||
|
$lines['offline'][] = $prev['status']
|
||||||
|
// Previous datapoint was online
|
||||||
|
? ['x' => $time_ms, 'y' => null]
|
||||||
|
// Previous datapoint was offline
|
||||||
|
: ['x' => $time_ms, 'y' => $highest_latency];
|
||||||
|
$lines['online'][] = ['x' => $time_ms, 'y' => round($record['latency'] * 1000, 3)];
|
||||||
|
|
||||||
|
if ($prev_downtime !== 0) {
|
||||||
|
$downtime += ($time - $prev_downtime);
|
||||||
|
}
|
||||||
|
$prev_downtime = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($line_keys as $key) {
|
||||||
|
// add the value for each of the different lines
|
||||||
|
$lines[$key][] = ['x' => $record['date'], 'y' => $record[$key] * 1000];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$prev = $record;
|
||||||
}
|
}
|
||||||
// Was down before.
|
// Was down before.
|
||||||
// Record the first and last date as a string in the down array
|
// Record the first and last date as a string in the down array
|
||||||
$prev_downtime == 0 ?: $downtime += ($now->getTimestamp() - $prev_downtime);
|
$prev_downtime == 0 ?: $downtime += ($now->getTimestamp() - $prev_downtime);
|
||||||
if ($add_uptime) {
|
if ($add_uptime) {
|
||||||
$prev['status'] ?: $lines['offline'][] =
|
if (!$prev['status']) {
|
||||||
'{ x: ' . ($now->getTimestamp() * 1000) . ', y:' . $highest_latency . '}';
|
$lines['offline'][] = ['x' => $now->getTimestamp() * 1000, 'y' => $highest_latency];
|
||||||
|
}
|
||||||
$data['uptime'] = 100 - ($downtime / ($end_time->getTimestamp() - $start_time->getTimestamp()));
|
$data['uptime'] = 100 - ($downtime / ($end_time->getTimestamp() - $start_time->getTimestamp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,11 +337,12 @@ class HistoryGraph
|
||||||
if (empty($line_value)) {
|
if (empty($line_value)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$lines_merged[$line_key]['value'] = implode(', ', $line_value);
|
$lines_merged[$line_key]['value'] = json_encode($line_value);
|
||||||
$lines_merged[$line_key]['name'] = psm_get_lang('servers', $line_key);
|
$lines_merged[$line_key]['name'] = psm_get_lang('servers', $line_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['latency_avg'] = count($records) > 0 ? ($latency_avg / count($records)) : 0;
|
$n_records = count($records);
|
||||||
|
$data['latency_avg'] = $n_records > 0 ? ($latency_avg / $n_records) : 0;
|
||||||
$data['lines'] = sizeof($lines_merged) ? $lines_merged : '';
|
$data['lines'] = sizeof($lines_merged) ? $lines_merged : '';
|
||||||
$data['end_timestamp'] = number_format($end_time->getTimestamp(), 0, '', '') * 1000;
|
$data['end_timestamp'] = number_format($end_time->getTimestamp(), 0, '', '') * 1000;
|
||||||
$data['start_timestamp'] = number_format($start_time->getTimestamp(), 0, '', '') * 1000;
|
$data['start_timestamp'] = number_format($start_time->getTimestamp(), 0, '', '') * 1000;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
data: {
|
data: {
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
data: [{{ graph.lines.offline.value }}],
|
data: {{ graph.lines.offline.value|raw }},
|
||||||
label: '{{ graph.lines.offline.name }}',
|
label: '{{ graph.lines.offline.name }}',
|
||||||
backgroundColor: '#dc3545',
|
backgroundColor: '#dc3545',
|
||||||
borderColor: '#dc3545',
|
borderColor: '#dc3545',
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
spanGaps: false,
|
spanGaps: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: [{{ graph.lines.online.value }}],
|
data: {{ graph.lines.online.value|raw }},
|
||||||
label: '{{graph.lines.online.name }}',
|
label: '{{graph.lines.online.name }}',
|
||||||
fill: false,
|
fill: false,
|
||||||
spanGaps: false,
|
spanGaps: false,
|
||||||
|
@ -120,7 +120,7 @@
|
||||||
datasets: [
|
datasets: [
|
||||||
{% for key,line in graph.lines %}
|
{% for key,line in graph.lines %}
|
||||||
{
|
{
|
||||||
data: [{{ line.value|raw }}],
|
data: {{ line.value|raw }},
|
||||||
label: '{{ line.name }}',
|
label: '{{ line.name }}',
|
||||||
backgroundColor: colors['{{key}}'],
|
backgroundColor: colors['{{key}}'],
|
||||||
borderColor: colors['{{key}}'],
|
borderColor: colors['{{key}}'],
|
||||||
|
|
Loading…
Reference in New Issue