0 && isset($notification_lists[$notify_list])) { $emails = explode(',', $notification_lists[$notify_list]); monitorAddEmails($reboot_emails, $emails, $host_id); } } /** * Fetch the configured global alert email list. * * @return array */ function getAlertEmails(): array { $alert_email = read_config_option('alert_email'); return ($alert_email != '') ? explode(',', $alert_email) : []; } /** * Delete monitor table rows that reference missing hosts. * * @param string $table_name Monitor table to purge. * * @return void */ function purgeOrphanMonitorRows(string $table_name): void { $removed_hosts = db_fetch_assoc("SELECT mu.host_id FROM $table_name AS mu LEFT JOIN host AS h ON h.id = mu.host_id WHERE h.id IS NULL"); if (cacti_sizeof($removed_hosts)) { db_execute("DELETE mu FROM $table_name AS mu LEFT JOIN host AS h ON h.id = mu.host_id WHERE h.id IS NULL"); } } /** * Get monitored hosts whose uptime indicates a reboot. * * @return array */ function getRebootedHosts(): array { return db_fetch_assoc('SELECT h.id, h.description, h.hostname, h.snmp_sysUpTimeInstance, mu.uptime FROM host AS h LEFT JOIN plugin_monitor_uptime AS mu ON h.id = mu.host_id WHERE h.snmp_version > 0 AND status IN (2,3) AND h.deleted = "" AND h.monitor = "on" AND (mu.uptime IS NULL OR mu.uptime > h.snmp_sysUpTimeInstance) AND h.snmp_sysUpTimeInstance > 0'); } /** * Fetch notification lists and map id to email string. * * @return array */ function getNotificationListsMap(): array { return array_rekey( db_fetch_assoc('SELECT id, emails FROM plugin_notification_lists ORDER BY id'), 'id', 'emails' ); } /** * Add reboot recipients based on host threshold notification settings. * * @param array $reboot_emails Recipient map keyed by email, then host id. * @param int|string $host_id Host id being processed. * @param array $alert_emails Global alert email list. * @param array $notification_lists Map of notification list id to emails. * * @return void */ function addTholdRebootRecipients(array &$reboot_emails, mixed $host_id, array $alert_emails, array $notification_lists): void { $notify = db_fetch_row_prepared( 'SELECT thold_send_email, thold_host_email FROM host WHERE id = ?', [$host_id] ); if (!cacti_sizeof($notify)) { return; } switch ($notify['thold_send_email']) { case '1': monitorAddEmails($reboot_emails, $alert_emails, $host_id); break; case '2': monitorAddNotificationList($reboot_emails, $notify['thold_host_email'], $host_id, $notification_lists); break; case '3': monitorAddEmails($reboot_emails, $alert_emails, $host_id); monitorAddNotificationList($reboot_emails, $notify['thold_host_email'], $host_id, $notification_lists); break; default: break; } } /** * Build reboot recipient map and persist reboot history rows. * * @param array $rebooted_hosts Rebooted host rows. * @param array $alert_emails Global alert email list. * * @return array */ function buildRebootEmailMap(array $rebooted_hosts, array $alert_emails): array { $reboot_emails = []; $notification_lists = getNotificationListsMap(); $monitor_list = read_config_option('monitor_list'); $monitor_thold = read_config_option('monitor_reboot_thold'); foreach ($rebooted_hosts as $host) { db_execute_prepared( 'INSERT INTO plugin_monitor_reboot_history (host_id, reboot_time) VALUES (?, ?)', [$host['id'], date(MONITOR_DATE_TIME_FORMAT, time() - intval($host['snmp_sysUpTimeInstance']))] ); monitorAddNotificationList($reboot_emails, $monitor_list, $host['id'], $notification_lists); if ($monitor_thold == 'on') { addTholdRebootRecipients($reboot_emails, $host['id'], $alert_emails, $notification_lists); } } return $reboot_emails; } /** * Dispatch reboot notifications per-recipient or as a single batched email. * * @param array $reboot_emails Recipient map keyed by email, then host id. * * @return void */ function sendRebootNotifications(array $reboot_emails): void { $monitor_send_one_email = read_config_option('monitor_send_one_email'); if (!cacti_sizeof($reboot_emails)) { return; } $all_hosts = []; $to_email = ''; foreach ($reboot_emails as $email => $hosts) { if ($email == '') { monitorDebug('Unable to process reboot notification due to empty Email address.'); continue; } $to_email .= ($to_email != '' ? ',' : '') . $email; $all_hosts = array_unique(array_merge($all_hosts, array_values($hosts))); if ($monitor_send_one_email !== 'on') { monitorDebug('Processing the Email address: ' . $email); processRebootEmail($email, $hosts); } } if ($monitor_send_one_email == 'on' && $to_email !== '') { monitorDebug('Processing the Email address: ' . $to_email); processRebootEmail($to_email, $all_hosts); } } /** * Process reboot detection, uptime refresh, and down-event history logging. * * @return array{int, int} Reboot count and recent down count. */ function monitorUptimeChecker(): array { monitorDebug('Checking for Uptime of Devices'); $alert_emails = getAlertEmails(); purgeOrphanMonitorRows('plugin_monitor_uptime'); purgeOrphanMonitorRows('plugin_monitor_reboot_history'); $rebooted_hosts = getRebootedHosts(); if (cacti_sizeof($rebooted_hosts)) { $reboot_emails = buildRebootEmailMap($rebooted_hosts, $alert_emails); sendRebootNotifications($reboot_emails); } // Freshen the uptimes db_execute('REPLACE INTO plugin_monitor_uptime (host_id, uptime) SELECT id, snmp_sysUpTimeInstance FROM host WHERE snmp_version > 0 AND status IN(2,3) AND deleted = "" AND monitor = "on" AND snmp_sysUpTimeInstance > 0'); // Log Recently Down db_execute('INSERT IGNORE INTO plugin_monitor_notify_history (host_id, notify_type, notification_time, notes) SELECT h.id, "3" AS notify_type, status_fail_date AS notification_time, status_last_error AS notes FROM host AS h WHERE status = 1 AND deleted = "" AND monitor = "on" AND status_event_count = 1'); $recent = db_affected_rows(); return [cacti_sizeof($rebooted_hosts), $recent]; } /** * Build reboot details table/text and capture the last resolved host row. * * @param array $hosts Host ids to include. * * @return array{string, string, array} */ function buildRebootDetails(array $hosts): array { $body_txt = ''; $last_host = []; $body = '' . PHP_EOL; $body .= '' . PHP_EOL; $body .= '' . '' . PHP_EOL; $body .= '' . PHP_EOL; foreach ($hosts as $host_id) { $host = db_fetch_row_prepared( 'SELECT description, hostname FROM host WHERE id = ?', [$host_id] ); if (!cacti_sizeof($host)) { continue; } $last_host = $host; $body .= '' . '' . '' . '' . PHP_EOL; $body_txt .= __('Description: ', 'monitor') . $host['description'] . PHP_EOL . __('Hostname: ', 'monitor') . $host['hostname'] . PHP_EOL . PHP_EOL; } $body .= '
' . __('Description', 'monitor') . '' . __('Hostname', 'monitor') . '
' . $host['description'] . '' . $host['hostname'] . '
' . PHP_EOL; return [$body, $body_txt, $last_host]; } /** * Build reboot notification subject from host count and delivery mode. * * @param array $hosts Host id list. * @param array $last_host Last host row seen while building details. * * @return string */ function buildRebootSubject(array $hosts, array $last_host): string { $subject = read_config_option('monitor_subject'); $monitor_send_one_email = read_config_option('monitor_send_one_email'); if ($monitor_send_one_email == 'on' && cacti_sizeof($last_host)) { return $subject . ' ' . $last_host['description'] . ' (' . $last_host['hostname'] . ')'; } if (cacti_sizeof($hosts) == 1 && cacti_sizeof($last_host)) { return $subject . ' 1 device - ' . $last_host['description'] . ' (' . $last_host['hostname'] . ')'; } return $subject . ' ' . cacti_sizeof($hosts) . ' devices'; } /** * Wrap body output with report format template and build mail headers. * * @param string $body HTML body content. * @param string $body_txt Plain text body content. * * @return array{string, string, array} */ function prepareReportOutput(string $body, string $body_txt): array { $output = ''; $report_tag = ''; $theme = 'modern'; monitorDebug('Loading Format File'); $format_ok = reports_load_format_file(read_config_option('monitor_format_file'), $output, $report_tag, $theme); monitorDebug('Format File Loaded, Format is ' . ($format_ok ? 'Ok' : 'Not Ok') . ', Report Tag is ' . $report_tag); if ($format_ok) { if ($report_tag) { $output = str_replace('', $body, $output); } else { $output = $output . PHP_EOL . $body; } } else { $output = $body; } monitorDebug('HTML Processed'); if (defined('CACTI_VERSION')) { $version = CACTI_VERSION; } else { $version = get_cacti_version(); } $headers = ['User-Agent' => 'Cacti-Monitor-v' . $version]; return [$output, $body_txt, $headers]; } /** * Render and send one reboot notification email payload. * * @param string $email Recipient email address string. * @param array $hosts Host ids to include in the message. * * @return void */ function processRebootEmail(string $email, array $hosts): void { monitorDebug("Reboot Processing for $email starting"); [$body, $body_txt, $last_host] = buildRebootDetails($hosts); $subject = buildRebootSubject($hosts, $last_host); $template_output = read_config_option('monitor_body'); $template_output = str_replace('
', $body, $template_output) . PHP_EOL; if (strpos($template_output, '
') !== false) { $toutput = str_replace('
', $body_txt, $template_output) . PHP_EOL; } else { $toutput = $body_txt; } if (read_config_option('monitor_reboot_notify') != 'on') { return; } [$output, $toutput, $headers] = prepareReportOutput($body, $toutput); processSendEmail($email, $subject, $output, $toutput, $headers, 'Reboot Notifications'); } /** * Resolve alert/warn host ids for requested global/list subscription scopes. * * @param array $lists Requested scopes (`global` or list ids). * @param array $global_list Flattened global notification host ids by severity. * @param array $notify_list Flattened list notification host ids by severity. * * @return array{array, array} */ function collectNotificationHosts(array $lists, array $global_list, array $notify_list): array { $alert_hosts = []; $warn_hosts = []; foreach ($lists as $list) { if ($list === 'global') { if (isset($global_list['alert'])) { $alert_hosts = array_merge($alert_hosts, explode(',', $global_list['alert'])); } if (isset($global_list['warn'])) { $warn_hosts = array_merge($warn_hosts, explode(',', $global_list['warn'])); } continue; } if (isset($notify_list[$list]['alert'])) { $alert_hosts = array_merge($alert_hosts, explode(',', $notify_list[$list]['alert'])); } if (isset($notify_list[$list]['warn'])) { $warn_hosts = array_merge($warn_hosts, explode(',', $notify_list[$list]['warn'])); } } return [$alert_hosts, $warn_hosts]; } /** * De-duplicate alert/warn host ids and log notification history entries. * * @param array $alert_hosts Alert host ids; normalized in place. * @param array $warn_hosts Warning host ids; normalized in place. * * @return void */ function normalizeAndLogNotificationHosts(array &$alert_hosts, array &$warn_hosts): void { if (cacti_sizeof($alert_hosts)) { $alert_hosts = array_unique($alert_hosts, SORT_NUMERIC); logMessages('alert', $alert_hosts); } if (cacti_sizeof($warn_hosts)) { $warn_hosts = array_unique($warn_hosts, SORT_NUMERIC); logMessages('warn', $warn_hosts); } } /** * Build shared intro copy for ping threshold email and text output. * * @param int|string $freq Resend frequency in minutes. * * @return array{string, string} */ function buildPingNotificationIntro(mixed $freq): array { $body = '

' . __(MONITOR_PING_NOTIFICATION_SUBJECT, 'monitor') . '

' . PHP_EOL; $body_txt = __(MONITOR_PING_NOTIFICATION_SUBJECT, 'monitor') . PHP_EOL; $message = __('The following report will identify Devices that have eclipsed their ping latency thresholds. You are receiving this report since you are subscribed to a Device associated with the Cacti system located at the following URL below.'); $body .= '

' . $message . '

' . PHP_EOL; $body_txt .= $message . PHP_EOL; $body .= '

Cacti Monitoring Site

' . PHP_EOL; $body_txt .= __('Cacti Monitoring Site', 'monitor') . PHP_EOL; if ($freq > 0) { $body .= '

' . __('You will receive notifications every %d minutes if the Device is above its threshold.', $freq, 'monitor') . '

' . PHP_EOL; $body_txt .= __('You will receive notifications every %d minutes if the Device is above its threshold.', $freq, 'monitor') . PHP_EOL; } else { $body .= '

' . __('You will receive notifications every time the Device is above its threshold.', 'monitor') . '

' . PHP_EOL; $body_txt .= __('You will receive notifications every time the Device is above its threshold.', 'monitor') . PHP_EOL; } return [$body, $body_txt]; } /** * Append one severity section for breached host thresholds. * * @param string $body HTML body output buffer. * @param string $body_txt Plain text output buffer. * @param array $host_ids Host ids for the section. * @param array $criticalities Criticality label map. * @param string $section_text Section heading text. * @param string $threshold_field Host threshold field name. * * @return void */ function appendThresholdSection(string &$body, string &$body_txt, array $host_ids, array $criticalities, string $section_text, string $threshold_field): void { global $config; if (!cacti_sizeof($host_ids)) { return; } $body .= '

' . __($section_text, 'monitor') . '

' . PHP_EOL; $body_txt .= __($section_text, 'monitor') . PHP_EOL; $body .= '' . PHP_EOL; $body .= '' . PHP_EOL; $body .= '' . '' . '' . '' . PHP_EOL; $body .= '' . PHP_EOL; $body_txt .= __('Hostname', 'monitor') . "\t" . __('Criticality', 'monitor') . "\t" . __(MONITOR_ALERT_PING_LABEL, 'monitor') . "\t" . __(MONITOR_CURRENT_PING_LABEL, 'monitor') . PHP_EOL; $hosts = db_fetch_assoc('SELECT * FROM host WHERE id IN(' . implode(',', $host_ids) . ') AND deleted = ""'); if (cacti_sizeof($hosts)) { foreach ($hosts as $host) { $body .= '' . PHP_EOL; $body .= '' . PHP_EOL; $body .= '' . PHP_EOL; $body .= '' . PHP_EOL; $body .= '' . PHP_EOL; $body .= '' . PHP_EOL; $body_txt .= $host['description'] . "\t" . $criticalities[$host['monitor_criticality']] . "\t" . number_format_i18n($host[$threshold_field], 2) . " ms\t" . number_format_i18n($host['cur_time'], 2) . ' ms' . PHP_EOL; } } $body .= '
' . __('Hostname', 'monitor') . '' . __('Criticality', 'monitor') . '' . __(MONITOR_ALERT_PING_LABEL, 'monitor') . '' . __(MONITOR_CURRENT_PING_LABEL, 'monitor') . '
' . $host['description'] . '' . $criticalities[$host['monitor_criticality']] . '' . number_format_i18n($host[$threshold_field], 2) . ' ms' . number_format_i18n($host['cur_time'], 2) . ' ms
' . PHP_EOL; } /** * Build log-friendly summary text for alert/warn delivery counts. * * @param array $alert_hosts Alert host ids. * @param array $warn_hosts Warning host ids. * * @return string */ function buildNotificationStatus(array $alert_hosts, array $warn_hosts): string { $status = ''; if (cacti_sizeof($alert_hosts)) { $status = sizeof($alert_hosts) . ' Alert Notifications'; } if (cacti_sizeof($warn_hosts)) { if ($status !== '') { $status .= ', and '; } $status .= sizeof($warn_hosts) . ' Warning Notifications'; } return $status; } /** * Build and send a ping-threshold notification for one recipient. * * @param string $email Recipient email. * @param array $lists Requested scopes (`global` or list ids). * @param array $global_list Flattened global host ids by severity. * @param array $notify_list Flattened list host ids by severity. * * @return void */ function processEmail(string $email, array $lists, array $global_list, array $notify_list): void { monitorDebug('Into Processing'); $criticalities = [ 0 => __('Disabled', 'monitor'), 1 => __('Low', 'monitor'), 2 => __('Medium', 'monitor'), 3 => __('High', 'monitor'), 4 => __('Mission Critical', 'monitor') ]; [$alert_hosts, $warn_hosts] = collectNotificationHosts($lists, $global_list, $notify_list); monitorDebug('Lists Processed'); normalizeAndLogNotificationHosts($alert_hosts, $warn_hosts); monitorDebug('Found ' . sizeof($alert_hosts) . ' Alert Hosts, and ' . sizeof($warn_hosts) . ' Warn Hosts'); if (!cacti_sizeof($alert_hosts) && !cacti_sizeof($warn_hosts)) { return; } monitorDebug('Formatting Email'); $freq = read_config_option('monitor_resend_frequency'); $subject = __(MONITOR_PING_NOTIFICATION_SUBJECT, 'monitor'); [$body, $body_txt] = buildPingNotificationIntro($freq); appendThresholdSection( $body, $body_txt, $alert_hosts, $criticalities, 'The following Devices have breached their Alert Notification Threshold.', 'monitor_alert' ); appendThresholdSection( $body, $body_txt, $warn_hosts, $criticalities, 'The following Devices have breached their Warning Notification Threshold.', 'monitor_warn' ); [$output, $toutput, $headers] = prepareReportOutput($body, $body_txt); $status = buildNotificationStatus($alert_hosts, $warn_hosts); processSendEmail($email, $subject, $output, $toutput, $headers, $status); } /** * Send an email through Cacti mailer with configured sender fallbacks. * * @param string $email Recipient email string. * @param string $subject Message subject. * @param string $output HTML output body. * @param string $toutput Plain text output body. * @param array $headers Extra headers passed to mailer. * @param string $status Status text used in logs. * * @return void */ function processSendEmail(string $email, string $subject, string $output, string $toutput, array $headers, string $status): void { $from_email = read_config_option('monitor_fromemail'); if ($from_email == '') { $from_email = read_config_option('settings_from_email'); if ($from_email == '') { $from_email = 'Cacti@cacti.net'; } } $from_name = read_config_option('monitor_fromname'); if ($from_name == '') { $from_name = read_config_option('settings_from_name'); if ($from_name == '') { $from_name = 'Cacti Reporting'; } } $html = true; if (read_config_option('thold_send_text_only') == 'on') { $output = monitorText($toutput); $html = false; } monitorDebug("Sending Email to '$email' for $status"); $error = mailer( [$from_email, $from_name], $email, '', '', '', $subject, $output, monitorText($toutput), null, $headers, $html ); monitorDebug("The return from the mailer was '$error'"); if (strlen($error)) { cacti_log("WARNING: Monitor had problems sending to '$email' for $status. The error was '$error'", false, 'MONITOR'); } else { cacti_log("NOTICE: Email Notification Sent to '$email' for $status.", false, 'MONITOR'); } } /** * Convert HTML-ish report content into plain text line output. * * @param string $output HTML or mixed output. * * @return string */ function monitorText(string $output): string { $output = explode(PHP_EOL, $output); $new_output = ''; if (cacti_sizeof($output)) { foreach ($output as $line) { $line = str_replace('
', PHP_EOL, $line); $line = str_replace('
', PHP_EOL, $line); $line = trim(strip_tags($line)); $new_output .= $line . PHP_EOL; } } return $new_output; } /** * Persist alert or warning notification history rows once per host. * * @param string $type Severity type (`alert` or `warn`). * @param array $alert_hosts Host ids to log for the severity. * * @return void */ function logMessages(string $type, array $alert_hosts): void { global $start_date; static $processed = []; if ($type == 'warn') { $type = '0'; $column = 'monitor_warn'; } elseif ($type == 'alert') { $type = '1'; $column = 'monitor_alert'; } foreach ($alert_hosts as $id) { if (!isset($processed[$id])) { db_execute_prepared( "INSERT INTO plugin_monitor_notify_history (host_id, notify_type, ping_time, ping_threshold, notification_time) SELECT id, '$type' AS notify_type, cur_time, $column, '$start_date' AS notification_time FROM host WHERE deleted = '' AND monitor = 'on' AND id = ?", [$id] ); } $processed[$id] = true; } } /** * Add grouped host ids to global/list collections by host email mode. * * @param string $type Severity key (`alert` or `warn`). * @param array $entry Grouped SQL row containing mode/list/ids. * @param array $global_list Global grouped bucket, updated in place. * @param array $notify_list Per-list grouped bucket, updated in place. * @param array $lists Set of list ids used for recipient lookups. * * @return void */ function addGroupedNotificationEntry(string $type, array $entry, array &$global_list, array &$notify_list, array &$lists): void { if ($entry['thold_send_email'] == '1' || $entry['thold_send_email'] == '3') { $global_list[$type][] = $entry; } if (($entry['thold_send_email'] == '2' || $entry['thold_send_email'] == '3') && $entry['thold_host_email'] > 0) { $notify_list[$type][$entry['thold_host_email']][] = $entry; $lists[$entry['thold_host_email']] = $entry['thold_host_email']; } } /** * Query and group threshold-breached hosts for one severity type. * * @param int|string $type Severity key (`alert` or `warn`). * @param int $criticality Minimum criticality threshold. * @param array $global_list Global grouped bucket, updated in place. * @param array $notify_list Per-list grouped bucket, updated in place. * @param array $lists Set of notification list ids, updated in place. * * @return void */ function getHostsByListType(string $type, mixed $criticality, array &$global_list, array &$notify_list, array &$lists): void { $last_time = date(MONITOR_DATE_TIME_FORMAT, time() - read_config_option('monitor_resend_frequency') * 60); $hosts = db_fetch_cell_prepared( "SELECT COUNT(*) FROM host WHERE status = 3 AND deleted = '' AND monitor = 'on' AND thold_send_email > 0 AND monitor_criticality >= ? AND cur_time > monitor_$type", [$criticality] ); if ($hosts <= 0) { return; } $htype = ($type == 'warn') ? 1 : 0; $groups = db_fetch_assoc_prepared( "SELECT thold_send_email, thold_host_email, GROUP_CONCAT(host.id) AS id FROM host LEFT JOIN ( SELECT host_id, MAX(notification_time) AS notification_time FROM plugin_monitor_notify_history WHERE notify_type = ? GROUP BY host_id ) AS nh ON host.id=nh.host_id WHERE status = 3 AND deleted = '' AND monitor = 'on' AND thold_send_email > 0 AND monitor_criticality >= ? AND cur_time > monitor_$type " . ($type == 'warn' ? ' AND cur_time < monitor_alert' : '') . ' AND (notification_time < ? OR notification_time IS NULL) AND host.total_polls > 1 GROUP BY thold_host_email, thold_send_email ORDER BY thold_host_email, thold_send_email', [$htype, $criticality, $last_time] ); if (!cacti_sizeof($groups)) { return; } foreach ($groups as $entry) { addGroupedNotificationEntry($type, $entry, $global_list, $notify_list, $lists); } } /** * Flatten grouped host id chunks for a single severity bucket. * * @param array $list Grouped rows, each row containing a CSV `id` field. * * @return string */ function flattenGroupSeverityList(array $list): string { $flattened = ''; foreach ($list as $item) { $flattened .= ($flattened !== '' ? ',' : '') . $item['id']; } return $flattened; } /** * Flatten grouped host ids for each notification list id. * * @param array $lists Grouped entries keyed by notification list id. * * @return array */ function flattenNotifySeverityLists(array $lists): array { $flattened = []; foreach ($lists as $id => $list) { $flattened[$id] = flattenGroupSeverityList($list); } return $flattened; } /** * Flatten grouped global and per-list structures into CSV host id strings. * * @param array $global_list Global grouped structure, updated in place. * @param array $notify_list Per-list grouped structure, updated in place. * * @return void */ function flattenLists(array &$global_list, array &$notify_list): void { if (cacti_sizeof($global_list)) { $new_global = []; foreach ($global_list as $severity => $list) { $new_global[$severity] = flattenGroupSeverityList($list); } $global_list = $new_global; } if (cacti_sizeof($notify_list)) { $new_list = []; foreach ($notify_list as $severity => $lists) { $new_list[$severity] = flattenNotifySeverityLists($lists); } $notify_list = $new_list; } } /** * Add email addresses into the recipient scope map. * * @param array $notification_emails Recipient map, updated in place. * @param array $emails Raw email values to normalize. * @param string|int $scope_key Scope key (`global` or list id). * * @return void */ function addEmailsToNotificationMap(array &$notification_emails, array $emails, mixed $scope_key): void { foreach ($emails as $user) { $user = trim($user); if ($user !== '') { $notification_emails[$user][$scope_key] = true; } } } /** * Build recipient map for global and notification list subscriptions. * * @param array $lists Notification list ids to resolve. * * @return array */ function getEmailsAndLists(array $lists): array { $notification_emails = []; $alert_email = read_config_option('alert_email'); $global_emails = ($alert_email != '') ? explode(',', $alert_email) : []; if (cacti_sizeof($global_emails)) { addEmailsToNotificationMap($notification_emails, $global_emails, 'global'); } if (!cacti_sizeof($lists)) { return $notification_emails; } $list_emails = db_fetch_assoc('SELECT id, emails FROM plugin_notification_lists WHERE id IN (' . implode(',', $lists) . ')'); if (!cacti_sizeof($list_emails)) { return $notification_emails; } foreach ($list_emails as $email) { addEmailsToNotificationMap($notification_emails, explode(',', $email['emails']), $email['id']); } return $notification_emails; } /** * Purge notification and reboot history records older than configured retention. * * @return array{int, int} Purged notify count and purged reboot count. */ function purgeEventRecords(): array { // Purge old records $days = read_config_option('monitor_log_storage'); if (empty($days)) { $days = 120; } db_execute_prepared( 'DELETE FROM plugin_monitor_notify_history WHERE notification_time < FROM_UNIXTIME(UNIX_TIMESTAMP() - (? * 86400))', [$days] ); $purge_n = db_affected_rows(); db_execute_prepared( 'DELETE FROM plugin_monitor_reboot_history WHERE log_time < FROM_UNIXTIME(UNIX_TIMESTAMP() - (? * 86400))', [$days] ); $purge_r = db_affected_rows(); return [$purge_n, $purge_r]; } /** * Print a debug line when poller debug mode is enabled. * * @param string $message Debug message. * * @return void */ function monitorDebug(string $message): void { global $debug; if ($debug) { print trim($message) . PHP_EOL; } } /** * Print monitor poller version information. * * @return void */ function displayVersion(): void { global $config; if (!function_exists('plugin_monitor_version')) { include_once $config['base_path'] . '/plugins/monitor/setup.php'; } $info = plugin_monitor_version(); print 'Cacti Monitor Poller, Version ' . $info['version'] . ', ' . COPYRIGHT_YEARS . PHP_EOL; } /** * Print CLI help output for this poller entrypoint. * * @return void */ function displayHelp(): void { displayVersion(); print PHP_EOL; print 'usage: poller_monitor.php [--debug]' . PHP_EOL . PHP_EOL; print ' --debug - debug execution, e.g. for testing' . PHP_EOL . PHP_EOL; }