diff --git a/daily.php b/daily.php index 2929c99ebe..7de5822dd6 100644 --- a/daily.php +++ b/daily.php @@ -204,39 +204,65 @@ if ($options['f'] === 'notifications') { } if ($options['f'] === 'bill_data') { - try { - if (Config::get('distributed_poller')) { - MemcacheLock::lock('syslog_purge', 0, 86000); - } - $billing_data_purge = Config::get('billing_data_purge'); - if (is_numeric($billing_data_purge) && $billing_data_purge > 0) { - # Deletes data older than XX months before the start of the last complete billing period - echo "Deleting billing data more than $billing_data_purge month before the last completed billing cycle\n"; - $sql = "DELETE bill_data - FROM bill_data - INNER JOIN (SELECT bill_id, - SUBDATE( - SUBDATE( - ADDDATE( - subdate(curdate(), (day(curdate())-1)), # Start of this month - bill_day - 1), # Billing anniversary - INTERVAL IF(bill_day > DAY(curdate()), 1, 0) MONTH), # Deal with anniversary not yet happened this month - INTERVAL ? MONTH) AS threshold # Adjust based on config threshold - FROM bills) q - ON bill_data.bill_id = q.bill_id AND bill_data.timestamp < q.threshold;"; - dbQuery($sql, array($billing_data_purge)); - } - } catch (LockException $e) { - echo $e->getMessage() . PHP_EOL; - exit(-1); - } + # Deletes data older than XX months before the start of the last complete billing period + $msg = "Deleting billing data more than %d month before the last completed billing cycle\n"; + $table = 'bill_data'; + $sql = "DELETE bill_data + FROM bill_data + INNER JOIN (SELECT bill_id, + SUBDATE( + SUBDATE( + ADDDATE( + subdate(curdate(), (day(curdate())-1)), # Start of this month + bill_day - 1), # Billing anniversary + INTERVAL IF(bill_day > DAY(curdate()), 1, 0) MONTH), # Deal with anniversary not yet happened this month + INTERVAL ? MONTH) AS threshold # Adjust based on config threshold + FROM bills) q + ON bill_data.bill_id = q.bill_id AND bill_data.timestamp < q.threshold;"; + lock_and_purge_query($table, $sql, $msg); } if ($options['f'] === 'alert_log') { - $ret = lock_and_purge('alert_log', 'time_logged < DATE_SUB(NOW(),INTERVAL ? DAY)'); - exit($ret); + $msg = "Deleting alert_logs more than %d days that are not active\n"; + $table = 'alert_log'; + $sql = "DELETE alert_log + FROM alert_log + INNER JOIN alerts + ON alerts.device_id=alert_log.device_id AND alerts.rule_id=alert_log.rule_id + WHERE alerts.state=0 AND alert_log.time_logged < DATE_SUB(NOW(),INTERVAL ? DAY) + "; + lock_and_purge_query($table, $sql, $msg); + + # alert_log older than $config['alert_log_purge'] days match now only the alert_log of active alerts + # in case of flapping of an alert, many entries are kept in alert_log + # we want only to keep the last alert_log that contains the alert details + + $msg = "Deleting history of active alert_logs more than %d days\n"; + $sql = "DELETE + FROM alert_log + WHERE id IN( + SELECT id FROM( + SELECT id + FROM alert_log a1 + WHERE + time_logged < DATE_SUB(NOW(),INTERVAL ? DAY) + AND (device_id, rule_id, time_logged) NOT IN ( + SELECT device_id, rule_id, max(time_logged) + FROM alert_log a2 WHERE a1.device_id = a2.device_id AND a1.rule_id = a2.rule_id + AND a2.time_logged < DATE_SUB(NOW(),INTERVAL ? DAY) + ) + ) as c + ) + "; + $purge_duration = Config::get('alert_log_purge'); + if (!(is_numeric($purge_duration) && $purge_duration > 0)) { + return -2; + } + $sql = str_replace("?", strval($purge_duration), $sql); + lock_and_purge_query($table, $sql, $msg); } + if ($options['f'] === 'purgeusers') { try { if (Config::get('distributed_poller')) { diff --git a/includes/functions.php b/includes/functions.php index 428f82f430..57cfc45b80 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -2526,6 +2526,36 @@ function lock_and_purge($table, $sql) } } +/** + * If Distributed, create a lock, then purge the mysql table according to the sql query + * + * @param string $table + * @param string $sql + * @param string $msg + * @return int exit code + */ +function lock_and_purge_query($table, $sql, $msg) +{ + $purge_name = $table . '_purge'; + + if (Config::get('distributed_poller')) { + MemcacheLock::lock($purge_name, 0, 86000); + } + $purge_duration = Config::get($purge_name); + if (!(is_numeric($purge_duration) && $purge_duration > 0)) { + return -2; + } + try { + if (dbQuery($sql, array($purge_duration))) { + printf($msg, $purge_duration); + } + } catch (LockException $e) { + echo $e->getMessage() . PHP_EOL; + return -1; + } + return 0; +} + /** * Convert space separated hex OID content to character *