issue #119: adding log retention period

This commit is contained in:
Pepijn Over 2014-08-06 10:21:08 +02:00
parent 5c99a4bbd3
commit 71d432c973
22 changed files with 326 additions and 36 deletions

View File

@ -14,6 +14,7 @@ Features:
* #82: Added Danish translation.
* #103: Added Russian translation.
* #109: Custom time-out per server.
* #119: Log and archive retention period.
* #110: Support for SMSGlobal SMS gateway <https://www.smsglobal.com/>.
* #82: Support for Danish SMS provider Smsit <http://www.smsit.dk/>

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// За нов ред в имейл съобщението, моля използвайте тага <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -173,7 +173,7 @@ $sm_lang = array(
'config' => array(
'general' => 'General',
'language' => 'Language',
'show_update' => 'Updates',
'show_update' => 'Check for updates?',
'email_status' => 'Allow sending email',
'email_from_email' => 'Email from address',
'email_from_name' => 'Email from name',
@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -251,6 +251,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'De volgende fout is opgetreden bij het versturen van de Pushover notificatie: %s',
'pushover_error_noapp' => 'Kan test notificatie niet verzenden: er is geen Pushover App API token gevonden in de algemene configuratie.',
'pushover_error_nokey' => 'Kan test notificatie niet verzenden: er is geen Pushover key gevonden in je profiel.',
'log_retention_period' => 'Log retentie periode',
'log_retention_period_description' => 'Aantal dagen dat logs van notificaties en archieven van server uptime worden bewaard. Vul 0 in om log opruiming uit te zetten.',
'log_retention_days' => 'dagen',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'Произошла ошибка во время отправки Pushover уведомления: %s',
'pushover_error_noapp' => 'Не удалось отправить пробное уведомление: Pushover "App API token" не был найден в основных настройках.',
'pushover_error_nokey' => 'Не удалось отправить пробное уведомление: Pushover ключ не был найден в вашем профиле.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -250,6 +250,9 @@ $sm_lang = array(
'pushover_error' => 'An error has occurred while sending the Pushover notification: %s',
'pushover_error_noapp' => 'Unable to send test notification: no Pushover App API token found in the global configuration.',
'pushover_error_nokey' => 'Unable to send test notification: no Pushover key found in your profile.',
'log_retention_period' => 'Log retention period',
'log_retention_period_description' => 'Number of days to keep logs of notifications and archives of server uptime. Enter 0 to disable log cleanup.',
'log_retention_days' => 'days',
),
// for newlines in the email messages use <br/>
'notifications' => array(

View File

@ -112,6 +112,7 @@ class ConfigController extends AbstractController {
$tpl_data['sms_selected_' . $config['sms_gateway']] = 'selected="selected"';
$tpl_data['alert_type_selected_' . $config['alert_type']] = 'selected="selected"';
$tpl_data['auto_refresh_servers'] = (isset($config['auto_refresh_servers'])) ? $config['auto_refresh_servers'] : '0';
$tpl_data['log_retention_period'] = (isset($config['log_retention_period'])) ? $config['log_retention_period'] : '365';
foreach($this->checkboxes as $input_key) {
$tpl_data[$input_key . '_checked'] =
@ -148,7 +149,8 @@ class ConfigController extends AbstractController {
'language' => $_POST['language'],
'sms_gateway' => $_POST['sms_gateway'],
'alert_type' => $_POST['alert_type'],
'auto_refresh_servers' => (isset($_POST['auto_refresh_servers'])) ? intval($_POST['auto_refresh_servers']) : '0',
'auto_refresh_servers' => intval(psm_POST('auto_refresh_servers', 0)),
'log_retention_period' => intval(psm_POST('log_retention_period', 365)),
);
foreach($this->checkboxes as $input_key) {
$clean[$input_key] = (isset($_POST[$input_key])) ? '1': '0';
@ -330,6 +332,9 @@ class ConfigController extends AbstractController {
'label_seconds' => psm_get_lang('config', 'seconds'),
'label_save' => psm_get_lang('system', 'save'),
'label_test' => psm_get_lang('config', 'test'),
'label_log_retention_period' => psm_get_lang('config', 'log_retention_period'),
'label_log_retention_period_description' => psm_get_lang('config', 'log_retention_period_description'),
'label_log_retention_days' => psm_get_lang('config', 'log_retention_days'),
);
}
}

View File

@ -150,6 +150,7 @@ class Installer {
('log_email', '1'),
('log_sms', '1'),
('log_pushover', '1'),
('log_retention_period', '365'),
('version', '" . PSM_VERSION . "'),
('version_update_check', '" . PSM_VERSION . "'),
('auto_refresh_servers', '0'),
@ -398,6 +399,8 @@ class Installer {
protected function upgrade310() {
$queries = array();
psm_update_conf('log_retention_period', '365');
psm_update_conf('pushover_status', 1);
psm_update_conf('log_pushover', 1);
psm_update_conf('pushover_api_token', '');

View File

@ -0,0 +1,119 @@
<?php
/**
* PHP Server Monitor
* Monitor your servers and websites.
*
* This file is part of PHP Server Monitor.
* PHP Server Monitor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PHP Server Monitor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
*
* @package phpservermon
* @author Pepijn Over <pep@neanderthal-technology.com>
* @copyright Copyright (c) 2008-2014 Pepijn Over <pep@neanderthal-technology.com>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
* @link http://www.phpservermonitor.org/
* @since phpservermon 3.1
**/
namespace psm\Util\Server;
/**
* Makes sure all data of servers is being archived properly or removed if necessary.
*/
class ArchiveManager {
/**
* Available archiver utils.
* @var array $archivers
*/
protected $archivers = array();
/**
* Database service
* @var \psm\Service\Database $db
*/
protected $db;
/**
* Retention period
* @var \DateInterval $retention_period
* @see setRetentionPeriod()
*/
protected $retention_period;
public function __construct(\psm\Service\Database $db) {
$this->db = $db;
$this->setRetentionPeriod(psm_get_conf('log_retention_period', 365));
$this->archivers[] = new Archiver\UptimeArchiver($db);
$this->archivers[] = new Archiver\LogsArchiver($db);
}
/**
* Archive one or more servers.
* @param int $server_id
* @return boolean
*/
public function archive($server_id = null) {
$result = true;
foreach($this->archivers as $archiver) {
if(!$archiver->archive($server_id)) {
$result = false;
}
}
return $result;
}
/**
* Cleanup old records for one or more servers
* @param int $server_id
* @return boolean
*/
public function cleanup($server_id = null) {
$result = true;
if(!$this->retention_period) {
// cleanup is disabled
return $result;
}
$retdate = new \DateTime();
$retdate->sub($this->retention_period);
foreach($this->archivers as $archiver) {
if(!$archiver->cleanup($retdate, $server_id)) {
$result = false;
}
}
return $result;
}
/**
* Set retention period for this archive run.
*
* Set period to 0 to disable cleanup altogether.
* @param \DateInterval|int $period \DateInterval object or number of days (int)
* @return \psm\Util\Server\ArchiveManager
*/
public function setRetentionPeriod($period) {
if(is_object($period) && $period instanceof \DateInterval) {
$this->retention_period = $period;
} elseif(intval($period) == 0) {
// cleanup disabled
$this->retention_period = false;
} else {
$this->retention_period = new \DateInterval('P' . intval($period) . 'D');
}
return $this;
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* PHP Server Monitor
* Monitor your servers and websites.
*
* This file is part of PHP Server Monitor.
* PHP Server Monitor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PHP Server Monitor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
*
* @package phpservermon
* @author Pepijn Over <pep@neanderthal-technology.com>
* @copyright Copyright (c) 2008-2014 Pepijn Over <pep@neanderthal-technology.com>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
* @link http://www.phpservermonitor.org/
* @since phpservermon 3.1
**/
namespace psm\Util\Server\Archiver;
interface ArchiverInterface {
/**
* Archive for one or all servers.
* @param int $server_id
* @return boolean
*/
public function archive($server_id = null);
/**
* Cleanup data older than the retention period given.
* @param \DateTime $retention_date
* @param int $server_id
* @return boolean
*/
public function cleanup(\DateTime $retention_date, $server_id = null);
}

View File

@ -0,0 +1,70 @@
<?php
/**
* PHP Server Monitor
* Monitor your servers and websites.
*
* This file is part of PHP Server Monitor.
* PHP Server Monitor is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PHP Server Monitor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PHP Server Monitor. If not, see <http://www.gnu.org/licenses/>.
*
* @package phpservermon
* @author Pepijn Over <pep@neanderthal-technology.com>
* @copyright Copyright (c) 2008-2014 Pepijn Over <pep@neanderthal-technology.com>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
* @link http://www.phpservermonitor.org/
* @since phpservermon 3.1
**/
/**
* Cleanup log table
*/
namespace psm\Util\Server\Archiver;
use psm\Service\Database;
class LogsArchiver implements ArchiverInterface {
/**
* Database service
* @var \psm\Service\Database $db
*/
protected $db;
function __construct(Database $db) {
$this->db = $db;
}
/**
* Currently there is not really a log archive.
*
* It stays in the log table until cleaned up.
* @param int $server_id
*/
public function archive($server_id = null) {
return true;
}
public function cleanup(\DateTime $retention_date, $server_id = null) {
$sql_where_server = ($server_id !== null)
// this is obviously not the cleanest way to implement this when using paramter binding.. sorry.
? ' `server_id` = ' . intval($server_id) . ' AND '
: '';
$this->db->execute(
"DELETE FROM `".PSM_DB_PREFIX."log` WHERE {$sql_where_server} `datetime` < :latest_date",
array('latest_date' => $retention_date->format('Y-m-d 00:00:00')),
false
);
return true;
}
}

View File

@ -19,6 +19,7 @@
*
* @package phpservermon
* @author Pepijn Over <pep@neanderthal-technology.com>
* Jérôme Cabanis <http://lauraly.com>
* @copyright Copyright (c) 2008-2014 Pepijn Over <pep@neanderthal-technology.com>
* @license http://www.gnu.org/licenses/gpl.txt GNU GPL v3
* @version Release: @package_version@
@ -36,10 +37,10 @@
*
* @see \psm\Util\Updater\Autorun
*/
namespace psm\Service;
namespace psm\Util\Server\Archiver;
use psm\Service\Database;
class Archiver {
class UptimeArchiver implements ArchiverInterface {
/**
* Database service
@ -56,29 +57,23 @@ class Archiver {
*
* Archiving means calculating averages per day, and storing 1 single
* history row for each day for each server.
*
* @param int $server_id
*/
public function archiveStatus() {
public function archive($server_id = null) {
$latest_date = new \DateTime('-1 week 0:0:0');
$timestamp = $latest_date->getTimestamp();
// Check if archiving is necessary
$last_archive = psm_get_conf('last_archive_time', 0);
if($timestamp <= $last_archive) {
return false;
}
psm_update_conf('last_archive_time', $timestamp);
// Lock tables to prevent simultaneous archiving (by other sessions or the cron job)
$this->db->exec('LOCK TABLES ' . PSM_DB_PREFIX . 'servers_uptime WRITE, ' . PSM_DB_PREFIX . 'servers_history WRITE');
$latest_date_str = $latest_date->format('Y-m-d 00:00:00');
$sql_where_server = $this->createSQLWhereServer($server_id);
$records = $this->db->execute(
"SELECT `server_id`,`date`,`status`,`latency`
FROM `" . PSM_DB_PREFIX."servers_uptime`
WHERE `date` < :latest_date
ORDER BY `date` ASC",
WHERE {$sql_where_server} `date` < :latest_date",
array('latest_date' => $latest_date_str));
if(!empty($records)) {
@ -106,22 +101,24 @@ class Archiver {
// now remove all records from the uptime table
$this->db->execute(
"DELETE FROM `".PSM_DB_PREFIX."servers_uptime` WHERE `date` < :latest_date",
"DELETE FROM `".PSM_DB_PREFIX."servers_uptime` WHERE {$sql_where_server} `date` < :latest_date",
array('latest_date' => $latest_date_str),
false
);
}
// Remove older history entries
$latest_date->modify('-1 year');
$this->db->exec('UNLOCK TABLES');
return true;
}
public function cleanup(\DateTime $retention_date, $server_id = null) {
$sql_where_server = $this->createSQLWhereServer($server_id);
$this->db->execute(
"DELETE FROM `".PSM_DB_PREFIX."servers_history` WHERE `date` < :latest_date",
array('latest_date' => $latest_date->format('Y-m-d 00:00:00')),
"DELETE FROM `".PSM_DB_PREFIX."servers_history` WHERE {$sql_where_server} `date` < :latest_date",
array('latest_date' => $retention_date->format('Y-m-d 00:00:00')),
false
);
$this->db->exec('UNLOCK TABLES');
return true;
}
@ -156,4 +153,13 @@ class Archiver {
);
return $history;
}
protected function createSQLWhereServer($server_id) {
$sql_where_server = ($server_id !== null)
// this is obviously not the cleanest way to implement this when using paramter binding.. sorry.
? ' `server_id` = ' . intval($server_id) . ' AND '
: '';
return $sql_where_server;
}
}

View File

@ -28,7 +28,6 @@
namespace psm\Util\Server;
use psm\Service\Database;
use psm\Service\Archiver;
/**
* History util, create HTML for server graphs
@ -57,9 +56,9 @@ class HistoryGraph {
* @return string
*/
public function createHTML($server_id) {
// Archive all records older than 1 week, if needed
$archiver = new Archiver($this->db);
$archiver->archiveStatus();
// Archive all records for this server to make sure we have up-to-date stats
$archive = new ArchiveManager($this->db);
$archive->archive($server_id);
$now = new \DateTime();
$last_week = new \DateTime('-1 week 0:0:0');

View File

@ -29,7 +29,6 @@
namespace psm\Util\Updater;
use psm\Service\Database;
use psm\Service\User;
use psm\Service\Archiver;
/**
* Run an update on all servers.
@ -87,9 +86,10 @@ class Autorun {
$notifier->notify($server['server_id'], $status_old, $status_new);
}
// clean-up time!! archive all records older than 1 week
$archiver = new Archiver($this->db);
$archiver->archiveStatus();
// clean-up time!! archive all records
$archive = new \psm\Util\Server\ArchiveManager($this->db);
$archive->archive();
$archive->cleanup();
}
/**

View File

@ -27,8 +27,7 @@
<div class="control-group">
<label class="control-label" for="auto_refresh_servers">{{ label_auto_refresh }}</label>
<div class="controls">
<input type="text" class="input-mini" id="auto_refresh_servers" name="auto_refresh_servers" value="{{ auto_refresh_servers }}" maxlength="10" />&nbsp;{{ label_seconds }}
<p class="help-block">{{ label_auto_refresh_servers|raw }}</p>
<input type="text" class="input-mini" id="auto_refresh_servers" name="auto_refresh_servers" value="{{ auto_refresh_servers }}" maxlength="10" data-toggle="tooltip" title="{{ label_auto_refresh_servers }}" />&nbsp;{{ label_seconds }}
</div>
</div>
</fieldset>
@ -50,10 +49,15 @@
<legend>{{ label_settings_log }}</legend>
<div class="control-group">
<div class="controls">
<label class="checkbox"><input type="checkbox" id="log_status" name="log_status[]" {{ log_status_checked|raw }} /> {{ label_log_status }}</label>
<p class="help-block">{{ label_log_status_description|raw }}</p>
<label class="checkbox"><input type="checkbox" id="log_status" name="log_status[]" {{ log_status_checked|raw }} data-toggle="tooltip" title="{{ label_log_status_description }}" /> {{ label_log_status }}</label>
</div>
</div>
<div class="control-group">
<label class="control-label" for="log_retention_period">{{ label_log_retention_period }}</label>
<div class="controls">
<input type="text" class="input-mini" id="log_retention_period" name="log_retention_period" value="{{ log_retention_period }}" data-toggle="tooltip" title="{{ label_log_retention_period_description }}" />&nbsp;{{ label_log_retention_days }}
</div>
</div>
<div class="form-actions">
<button class="btn btn-success" type="submit" name="general_submit">{{ label_save }}</button>
</div>