diff --git a/CHANGELOG.md b/CHANGELOG.md index b014072..ae964d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ --- develop --- +* feature: Add Device Alert Rules for device-wide alert handling: administrators can pause a device's non-exempt alerts until a selected time or indefinitely, choose a priority threshold that always passes through device pauses and maintenance windows, and allow all device alerts during maintenance for critical devices + * feature: Add a fail-safe for partition maintenance: when the partition metadata for the syslog or syslog_removed table is invalid or incomplete, or a required partition cannot be created, all partition creation and retention pruning stops, the dMaxValue safety partition is never dropped, and the blocked condition with its remediation step is logged and shown on the Syslog Status page * feature: Add bounded multi-day partition recovery: a new 'Partition Recovery Limit' setting caps how many missing partitions are created per table per poller run so large gaps heal over several cycles; retention pruning stays deferred until the future write horizon is restored, and each blocked run reports the remaining gap, the stop reason, and whether writes are accumulating in dMaxValue * feature: Add collector health metrics to the Syslog Status tab: last received log timestamp, oldest unprocessed incoming message age, current incoming backlog, records processed in the latest run, and a warning when data looks stale or the backlog exceeds the new 'Collector Staleness' and 'Collector Backlog Threshold' settings; unavailable metrics read as Unavailable instead of invented values diff --git a/INFO b/INFO index 45475d8..c6f4d47 100644 --- a/INFO +++ b/INFO @@ -21,7 +21,7 @@ [info] name = syslog -version = 4.4 +version = 4.5 longname = Syslog Monitoring author = The Cacti Group email = diff --git a/functions.php b/functions.php index 79c1876..0521e68 100644 --- a/functions.php +++ b/functions.php @@ -4283,6 +4283,53 @@ function syslog_alert_suppression_record(array $alert, array $state): void { syslog_db_execute_prepared('INSERT INTO syslog_alert_suppression (alert_id, scope_key, dedup_hash, last_sent) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE last_sent = VALUES(last_sent)', [$alert['id'], $state['scope_key'], $state['dedup_hash'], time()]); } +/** Return whether this alert's configured maintenance window is active. */ +function syslog_alert_maintenance_is_active(array $alert): bool { + $mode = $alert['maintenance_mode'] ?? 'inherit'; + if ($mode === 'disabled') { + return false; + } + if ($mode === 'custom') { + return syslog_alert_datetime_window_is_active((string) ($alert['maintenance_datetime_start'] ?? ''), (string) ($alert['maintenance_datetime_end'] ?? '')) + || syslog_alert_schedule_is_active(syslog_alert_maintenance_window((string) ($alert['maintenance_days'] ?? ''), (string) ($alert['maintenance_start'] ?? ''), (string) ($alert['maintenance_end'] ?? ''))); + } + + return syslog_alert_datetime_window_is_active((string) read_config_option('syslog_alert_maintenance_datetime_start'), (string) read_config_option('syslog_alert_maintenance_datetime_end')) + || syslog_alert_schedule_is_active(syslog_alert_maintenance_window((string) read_config_option('syslog_alert_maintenance_days'), (string) read_config_option('syslog_alert_maintenance_start'), (string) read_config_option('syslog_alert_maintenance_end'))); +} + +/** + * Limit an alert query by active device-wide handling rules. + * + * A pass-through priority of Critical (2), for example, permits priorities + * Emergency through Critical even if the host is muted or in maintenance. + * A rule applies by hostname to every alert definition, not merely one rule. + * + * @return array{sql:string,params:array} + */ +function syslog_device_rule_sql(bool $maintenance_active): array { + global $syslogdb_default, $syslog_incoming_config; + $host_field = $syslog_incoming_config['hostField'] ?? 'host'; + $priority_field = $syslog_incoming_config['priorityField'] ?? 'priority_id'; + $now = time(); + $active_mute = "(dr.mute_mode = 'indefinite' OR (dr.mute_mode = 'until' AND dr.mute_until > ?))"; + $pass_through = "(dr.pass_through_priority >= 0 AND COALESCE(`$priority_field`, 99) <= dr.pass_through_priority)"; + $mute_filter = "\n\t\t\t\tAND NOT EXISTS (SELECT 1 FROM `$syslogdb_default`.`syslog_device_rule` AS dr WHERE dr.host = `$host_field` AND dr.enabled = 'on' AND NOT $pass_through AND $active_mute)"; + if ($maintenance_active) { + // Normal maintenance still mutes every device. Only an explicit device + // exception may admit a record, so the absence of a device rule is not + // accidentally treated as an exception. + $maintenance_filter = "\n\t\t\t\tAND EXISTS (SELECT 1 FROM `$syslogdb_default`.`syslog_device_rule` AS dr WHERE dr.host = `$host_field` AND dr.enabled = 'on' AND (dr.allow_maintenance = 'on' OR $pass_through))"; + } else { + $maintenance_filter = ''; + } + + return [ + 'sql' => $maintenance_filter . $mute_filter, + 'params' => [$now] + ]; +} + function syslog_process_alerts($max_seq) { global $syslogdb_default; @@ -4309,22 +4356,7 @@ function syslog_process_alerts($max_seq) { if (cacti_sizeof($alerts)) { foreach ($alerts as $alert) { - $mode = $alert['maintenance_mode'] ?? 'inherit'; - if ($mode === 'custom') { - $schedule = syslog_alert_maintenance_window((string) ($alert['maintenance_days'] ?? ''), (string) ($alert['maintenance_start'] ?? ''), (string) ($alert['maintenance_end'] ?? '')); - $dated_window = syslog_alert_datetime_window_is_active((string) ($alert['maintenance_datetime_start'] ?? ''), (string) ($alert['maintenance_datetime_end'] ?? '')); - } elseif ($mode === 'disabled') { - $schedule = ''; - $dated_window = false; - } else { - $schedule = syslog_alert_maintenance_window((string) read_config_option('syslog_alert_maintenance_days'), (string) read_config_option('syslog_alert_maintenance_start'), (string) read_config_option('syslog_alert_maintenance_end')); - $dated_window = syslog_alert_datetime_window_is_active((string) read_config_option('syslog_alert_maintenance_datetime_start'), (string) read_config_option('syslog_alert_maintenance_datetime_end')); - } - if ($dated_window || syslog_alert_schedule_is_active($schedule)) { - syslog_debug(sprintf("Alert Rule '%s' is muted by a maintenance window", $alert['name'])); - - continue; - } + $maintenance_active = syslog_alert_maintenance_is_active($alert); $sql = ''; $params = []; @@ -4345,6 +4377,9 @@ function syslog_process_alerts($max_seq) { $sql = $sql_data['sql']; $params = $sql_data['params']; + $device_rule = syslog_device_rule_sql($maintenance_active); + $sql .= $device_rule['sql']; + $params = array_merge($params, $device_rule['params']); if ($sql != '') { if ($alert['level'] == '1') { @@ -5777,7 +5812,7 @@ function alert_replace_variables($alert, $results, $hostname = '') { function syslog_message_button($message, $device, $program, $facility, $severity, $received, $id = 0, $source = ''): string { $details = compact('device', 'program', 'facility', 'severity', 'received'); $details['message'] = (string) $message; - $details['rules'] = syslog_message_rule_links($id, $source, $received); + $details['rules'] = syslog_message_rule_links($id, $source, $received, $device); $text = title_trim((string) $message, 100); return ''; @@ -5792,7 +5827,7 @@ function syslog_message_button($message, $device, $program, $facility, $severity * * @return array Map of action name to rule editor URL. */ -function syslog_message_rule_links($id, $source, $received): array { +function syslog_message_rule_links($id, $source, $received, $host = ''): array { $links = []; if ($source !== 'main' || !ctype_digit((string) $id) || (int) $id < 1) { return $links; @@ -5804,6 +5839,9 @@ function syslog_message_rule_links($id, $source, $received): array { $links[$action] = $page . '?' . $query; } } + if ($host !== '' && api_plugin_user_realm_auth('syslog_device_rules.php')) { + $links['device'] = 'syslog_device_rules.php?' . http_build_query(['action' => 'edit', 'host' => $host]); + } return $links; } diff --git a/js/dashboard.js b/js/dashboard.js index 4195162..a35e943 100644 --- a/js/dashboard.js +++ b/js/dashboard.js @@ -581,7 +581,7 @@ function syslogDashboardPanelById(panelId) { /* ===================== Event wiring ===================== */ -$(function() { +if (window.jQuery) window.jQuery(function() { if (!document.getElementById('syslog_dashboard_grid')) { return; } @@ -764,4 +764,4 @@ function syslogDashboardPrompt(name, accept) { {text: syslogDashboard.text.cancel, click: function() { $(this).dialog('close'); }} ] }); -} \ No newline at end of file +} diff --git a/locales/po/cacti.pot b/locales/po/cacti.pot index deda955..6fe4e0c 100644 --- a/locales/po/cacti.pot +++ b/locales/po/cacti.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Cacti \n" "Report-Msgid-Bugs-To: developers@cacti.net\n" -"POT-Creation-Date: 2026-09-22 20:32-0400\n" +"POT-Creation-Date: 2026-09-22 21:52-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Cacti Developers >\n" "Language-Team: Cacti Developers \n" @@ -110,8 +110,8 @@ msgstr "" msgid "Permission denied." msgstr "" -#: functions.php:2968 functions.php:2972 setup.php:2360 setup.php:2370 -#: setup.php:2377 +#: functions.php:2968 functions.php:2972 setup.php:2421 setup.php:2431 +#: setup.php:2438 msgid "Invalid request. Please try again." msgstr "" @@ -129,140 +129,140 @@ msgstr "" msgid "Unknown" msgstr "" -#: functions.php:4513 +#: functions.php:4548 #, php-format msgid "Cacti Syslog Threshold Alert '%s' for Host '%s'" msgstr "" -#: functions.php:4515 +#: functions.php:4550 #, php-format msgid "Cacti Syslog Threshold Alert '%s'" msgstr "" -#: functions.php:4523 syslog.php:2242 syslog_alerts.php:1169 +#: functions.php:4558 syslog.php:2242 syslog_alerts.php:1169 msgid "Alert Name" msgstr "" -#: functions.php:4524 functions.php:4551 syslog.php:2241 syslog_alerts.php:653 +#: functions.php:4559 functions.php:4586 syslog.php:2241 syslog_alerts.php:653 #: syslog_alerts.php:1170 msgid "Severity" msgstr "" -#: functions.php:4525 syslog_alerts.php:672 syslog_alerts.php:677 +#: functions.php:4560 syslog_alerts.php:672 syslog_alerts.php:677 #: syslog_alerts.php:1196 msgid "Threshold" msgstr "" -#: functions.php:4526 syslog.php:2123 syslog.php:2244 +#: functions.php:4561 syslog.php:2123 syslog.php:2244 msgid "Count" msgstr "" -#: functions.php:4527 +#: functions.php:4562 msgid "Match String" msgstr "" -#: functions.php:4538 functions.php:4578 +#: functions.php:4573 functions.php:4613 #, php-format msgid "Cacti Syslog Alert '%s' for Host '%s'" msgstr "" -#: functions.php:4540 functions.php:4580 +#: functions.php:4575 functions.php:4615 #, php-format msgid "Cacti Syslog Alert '%s'" msgstr "" -#: functions.php:4549 +#: functions.php:4584 msgid "Hostname" msgstr "" -#: functions.php:4550 functions.php:5484 syslog.php:2114 syslog.php:2239 +#: functions.php:4585 functions.php:5519 syslog.php:2114 syslog.php:2239 #: syslog.php:2296 msgid "Date" msgstr "" -#: functions.php:4552 +#: functions.php:4587 msgid "Level" msgstr "" -#: functions.php:4553 functions.php:5485 lib/syslog_dashboard.php:1621 +#: functions.php:4588 functions.php:5520 lib/syslog_dashboard.php:1621 #: syslog.php:1811 syslog.php:1896 syslog.php:2117 syslog.php:2243 #: syslog.php:2297 syslog_alerts.php:889 syslog_removal.php:679 #: syslog_saved_searches.php:666 msgid "Message" msgstr "" -#: functions.php:4561 +#: functions.php:4596 #, php-format msgid "WARNING: A Syslog Threshold Alert has Been Triggered for Host '%s'" msgstr "" -#: functions.php:4563 +#: functions.php:4598 msgid "WARNING: A Syslog Threshold Alert has Been Triggered" msgstr "" -#: functions.php:4570 +#: functions.php:4605 msgid "Name:" msgstr "" -#: functions.php:4571 functions.php:4627 +#: functions.php:4606 functions.php:4662 msgid "Severity:" msgstr "" -#: functions.php:4572 +#: functions.php:4607 msgid "Threshold:" msgstr "" -#: functions.php:4573 +#: functions.php:4608 msgid "Count:" msgstr "" -#: functions.php:4574 +#: functions.php:4609 msgid "Message String:" msgstr "" -#: functions.php:4625 +#: functions.php:4660 msgid "Hostname:" msgstr "" -#: functions.php:4626 +#: functions.php:4661 msgid "Date:" msgstr "" -#: functions.php:4628 +#: functions.php:4663 msgid "Level:" msgstr "" -#: functions.php:4629 +#: functions.php:4664 msgid "Message:" msgstr "" -#: functions.php:4704 +#: functions.php:4739 msgid ", Host:" msgstr "" -#: functions.php:4704 functions.php:4739 +#: functions.php:4739 functions.php:4774 msgid ", URL:" msgstr "" -#: functions.php:4704 functions.php:4739 +#: functions.php:4739 functions.php:4774 msgid "Sev:" msgstr "" -#: functions.php:4710 functions.php:4735 +#: functions.php:4745 functions.php:4770 #, php-format msgid "Event Alert - %s" msgstr "" -#: functions.php:4739 +#: functions.php:4774 msgid ", Count:" msgstr "" -#: functions.php:5483 lib/syslog_dashboard.php:1568 syslog_alerts.php:890 +#: functions.php:5518 lib/syslog_dashboard.php:1568 syslog_alerts.php:890 #: syslog_removal.php:680 msgid "Host" msgstr "" -#: functions.php:5508 +#: functions.php:5543 #, php-format msgid "Event Report - %s" msgstr "" @@ -377,10 +377,10 @@ msgstr "" msgid "Save" msgstr "" -#: lib/syslog_dashboard.php:1370 lib/syslog_dashboard.php:1525 setup.php:1605 -#: setup.php:2444 syslog.php:1890 syslog_alerts.php:230 -#: syslog_dashboards.php:428 syslog_removal.php:248 syslog_reports.php:213 -#: syslog_saved_searches.php:384 +#: lib/syslog_dashboard.php:1370 lib/syslog_dashboard.php:1525 setup.php:1662 +#: setup.php:2505 syslog.php:1890 syslog_alerts.php:230 +#: syslog_dashboards.php:428 syslog_device_rules.php:126 syslog_removal.php:248 +#: syslog_reports.php:213 syslog_saved_searches.php:384 msgid "Cancel" msgstr "" @@ -388,10 +388,10 @@ msgstr "" msgid "Apply" msgstr "" -#: lib/syslog_dashboard.php:1372 lib/syslog_dashboard.php:1485 setup.php:2035 +#: lib/syslog_dashboard.php:1372 lib/syslog_dashboard.php:1485 setup.php:2092 #: syslog.php:1798 syslog_dashboards.php:300 syslog_dashboards.php:351 -#: syslog_removal.php:36 syslog_saved_searches.php:271 -#: syslog_saved_searches.php:315 +#: syslog_device_rules.php:124 syslog_removal.php:36 +#: syslog_saved_searches.php:271 syslog_saved_searches.php:315 msgid "Delete" msgstr "" @@ -468,7 +468,7 @@ msgstr "" msgid "Refresh" msgstr "" -#: lib/syslog_dashboard.php:1438 setup.php:2177 setup.php:2234 +#: lib/syslog_dashboard.php:1438 setup.php:2235 setup.php:2295 #: syslog_dashboards.php:201 syslog_dashboards.php:203 msgid "Dashboards" msgstr "" @@ -623,7 +623,7 @@ msgstr "" #: lib/syslog_dashboard.php:1603 syslog.php:360 syslog.php:374 syslog.php:2365 #: syslog.php:2376 syslog.php:2429 syslog.php:2430 syslog_alerts.php:802 -#: syslog_reports.php:554 +#: syslog_device_rules.php:265 syslog_reports.php:554 msgid "None" msgstr "" @@ -662,645 +662,656 @@ msgstr "" msgid "Please rename either your config.php.dist or config_local.php.dist files in the syslog directory, and change setup your database before installing." msgstr "" -#: setup.php:1420 +#: setup.php:1477 msgid "What upgrade/install type do you wish to use" msgstr "" -#: setup.php:1421 +#: setup.php:1478 msgid "When you have very large tables, performing a Truncate will be much quicker. If you are concerned about archive data, you can choose either Inline, which will freeze your browser for the period of this upgrade, or background, which will create a background process to bring your old syslog data from a backup table to the new syslog format. Again this process can take several hours." msgstr "" -#: setup.php:1424 +#: setup.php:1481 msgid "Truncate Syslog Table" msgstr "" -#: setup.php:1425 +#: setup.php:1482 msgid "Inline Upgrade" msgstr "" -#: setup.php:1426 +#: setup.php:1483 msgid "Background Upgrade" msgstr "" -#: setup.php:1431 +#: setup.php:1488 msgid "Database Storage Engine" msgstr "" -#: setup.php:1432 +#: setup.php:1489 msgid "The storage engine for the analytical tables. Only InnoDB and, on MariaDB, Aria storage engines are supported." msgstr "" -#: setup.php:1435 +#: setup.php:1492 msgid "InnoDB Storage" msgstr "" -#: setup.php:1436 +#: setup.php:1493 msgid "Aria Storage" msgstr "" -#: setup.php:1445 +#: setup.php:1502 msgid "Retention Policy" msgstr "" -#: setup.php:1446 +#: setup.php:1503 msgid "Choose how many days of Syslog values you wish to maintain in the database." msgstr "" -#: setup.php:1466 +#: setup.php:1523 msgid "Partitions per Day" msgstr "" -#: setup.php:1467 +#: setup.php:1524 msgid "Select the number of partitions per day that you wish to create." msgstr "" -#: setup.php:1470 setup.php:1471 setup.php:1472 setup.php:1473 setup.php:1474 +#: setup.php:1527 setup.php:1528 setup.php:1529 setup.php:1530 setup.php:1531 #, php-format msgid "%d Per Day" msgstr "" -#: setup.php:1479 setup.php:1593 +#: setup.php:1536 setup.php:1650 msgid "Upgrade" msgstr "" -#: setup.php:1481 setup.php:1595 +#: setup.php:1538 setup.php:1652 msgid "Install" msgstr "" -#: setup.php:1495 +#: setup.php:1552 #, php-format msgid "Syslog %s Advisor" msgstr "" -#: setup.php:1499 +#: setup.php:1556 msgid "WARNING: Syslog Upgrade is Time Consuming!!!" msgstr "" -#: setup.php:1500 +#: setup.php:1557 msgid "The upgrade of the 'main' syslog table can be a very time consuming process. As such, it is recommended that you either reduce the size of your syslog table prior to upgrading, or choose the background option

If you choose the background option, your legacy syslog table will be renamed, and a new syslog table will be created. Then, an upgrade process will be launched in the background. Again, this background process can quite a bit of time to complete. However, your data will be preserved

Regardless of your choice, all existing removal and alert rules will be maintained during the upgrade process.

Press 'Upgrade' to proceed with the upgrade, or 'Cancel' to return to the Plugins menu." msgstr "" -#: setup.php:1503 +#: setup.php:1560 msgid "You can also select the retention duration. Please keep in mind that if you have several hosts logging to syslog, this table can become quite large." msgstr "" -#: setup.php:1503 +#: setup.php:1560 msgid "You can also set the database storage engine for the analytical tables syslog and syslog_remove. Only the InnoDB storage engine and, on MariaDB, the Aria storage engine are supported. If using MariaDB, we recommend the Aria Storage Engine as it is designed for analytical queries." msgstr "" -#: setup.php:1503 +#: setup.php:1560 msgid "You have several options to choose from when installing Syslog. The first is the Database Architecture. Partitioned tables are the only supported architecture as they prevent the size of the tables from becoming excessive thus slowing queries. Traditional non-partitioned tables are deprecated and are no longer offered for new installs." msgstr "" -#: setup.php:1509 +#: setup.php:1566 #, php-format msgid "Syslog %s Settings" msgstr "" -#: setup.php:1541 +#: setup.php:1598 msgid "What uninstall method do you want to use?" msgstr "" -#: setup.php:1542 +#: setup.php:1599 msgid "When uninstalling syslog, you can remove everything, or only components, just in case you plan on re-installing in the future." msgstr "" -#: setup.php:1544 +#: setup.php:1601 msgid "Remove Everything (Logs, Tables, Settings)" msgstr "" -#: setup.php:1544 +#: setup.php:1601 msgid "Syslog Data Only" msgstr "" -#: setup.php:1564 +#: setup.php:1621 msgid "Syslog Uninstall Preferences" msgstr "" -#: setup.php:1598 +#: setup.php:1655 msgid "Uninstall" msgstr "" -#: setup.php:1658 +#: setup.php:1715 msgid "Monday" msgstr "" -#: setup.php:1658 +#: setup.php:1715 msgid "Tuesday" msgstr "" -#: setup.php:1658 +#: setup.php:1715 msgid "Wednesday" msgstr "" -#: setup.php:1659 +#: setup.php:1716 msgid "Friday" msgstr "" -#: setup.php:1659 +#: setup.php:1716 msgid "Saturday" msgstr "" -#: setup.php:1659 +#: setup.php:1716 msgid "Sunday" msgstr "" -#: setup.php:1659 +#: setup.php:1716 msgid "Thursday" msgstr "" -#: setup.php:1660 +#: setup.php:1717 msgid "Monday through Friday" msgstr "" -#: setup.php:1660 +#: setup.php:1717 msgid "Saturday and Sunday" msgstr "" -#: setup.php:1661 +#: setup.php:1718 msgid "Every day" msgstr "" -#: setup.php:1664 syslog_alerts.php:711 syslog_alerts.php:726 -#: syslog_alerts.php:734 syslog_removal.php:599 syslog_reports.php:499 +#: setup.php:1721 syslog_alerts.php:711 syslog_alerts.php:726 +#: syslog_alerts.php:734 syslog_device_rules.php:168 +#: syslog_device_rules.php:267 syslog_removal.php:599 syslog_reports.php:499 msgid "Disabled" msgstr "" -#: setup.php:1678 setup.php:1975 setup.php:1977 setup.php:2188 setup.php:2219 -#: setup.php:2235 +#: setup.php:1735 setup.php:2032 setup.php:2034 setup.php:2246 setup.php:2278 +#: setup.php:2296 msgid "Syslog" msgstr "" -#: setup.php:1682 +#: setup.php:1739 msgid "General Settings" msgstr "" -#: setup.php:1686 +#: setup.php:1743 msgid "Syslog Enabled" msgstr "" -#: setup.php:1687 +#: setup.php:1744 msgid "If this checkbox is set, records will be transferred from the Syslog Incoming table to the main syslog table and Alerts and Reports will be enabled. Please keep in mind that if the system is disabled log entries will still accumulate into the Syslog Incoming table as this is defined by the rsyslog or syslog-ng process." msgstr "" -#: setup.php:1692 +#: setup.php:1749 msgid "Strip Domains" msgstr "" -#: setup.php:1693 +#: setup.php:1750 msgid "A comma delimited list of domains that you wish to remove from the syslog hostname, Examples would be 'mydomain.com, otherdomain.com'" msgstr "" -#: setup.php:1700 +#: setup.php:1757 msgid "Refresh Interval" msgstr "" -#: setup.php:1701 +#: setup.php:1758 msgid "This is the time in seconds before the page refreshes." msgstr "" -#: setup.php:1707 +#: setup.php:1764 msgid "Max Report Records" msgstr "" -#: setup.php:1708 +#: setup.php:1765 msgid "For Threshold based Alerts, what is the maximum number that you wish to show in the report. This is used to limit the size of the html log and Email." msgstr "" -#: setup.php:1712 setup.php:1713 setup.php:1714 setup.php:1715 setup.php:1716 -#: setup.php:1717 +#: setup.php:1769 setup.php:1770 setup.php:1771 setup.php:1772 setup.php:1773 +#: setup.php:1774 #, php-format msgid "%d Records" msgstr "" -#: setup.php:1721 +#: setup.php:1778 msgid "Maximum Syslog Processing Processes" msgstr "" -#: setup.php:1722 +#: setup.php:1779 msgid "When set above 1, incoming message processing is spread across parallel worker processes. Each worker handles a disjoint range of incoming messages, speeding up hostname resolution and message transfer under heavy loads. A setting of 1 processes all messages in a single process. Worker processes are not supported on Windows or when the PHP pcntl and POSIX extensions are unavailable, in which case processing falls back to a single process." msgstr "" -#: setup.php:1726 +#: setup.php:1783 #, php-format msgid "%d Worker Process" msgstr "" -#: setup.php:1727 setup.php:1728 setup.php:1729 setup.php:1730 setup.php:1731 +#: setup.php:1784 setup.php:1785 setup.php:1786 setup.php:1787 setup.php:1788 #, php-format msgid "%d Worker Processes" msgstr "" -#: setup.php:1735 +#: setup.php:1792 msgid "Command for Opening Tickets" msgstr "" -#: setup.php:1736 +#: setup.php:1793 msgid "This command will be executed for opening Help Desk Tickets. The command will be required to parse multiple input parameters as follows: --alert-name, --severity, --hostlist, --message. The hostlist will be a comma delimited list of hosts impacted by the alert." msgstr "" -#: setup.php:1742 +#: setup.php:1799 msgid "Host Discovery Options" msgstr "" -#: setup.php:1747 +#: setup.php:1804 msgid "Enable Hostname Resolution" msgstr "" -#: setup.php:1748 +#: setup.php:1805 msgid "If this checkbox is set, all hostnames are resolved via DNS lookup first (If enabled). If the DNS lookup fails, the system will attempt to resolve the hostname against the Cacti host table and replace it with the Cacti host description. If both DNS and Cacti lookups fail, records are assigned a prefix 'unresolved-Original_hostname'." msgstr "" -#: setup.php:1753 +#: setup.php:1810 msgid "Skip DNS Resolution for incoming hosts" msgstr "" -#: setup.php:1754 +#: setup.php:1811 msgid "If this checkbox is set, the system will not attempt to resolve hosts via DNS lookups. This is useful for environments where DNS resolution is not possible or not desired." msgstr "" -#: setup.php:1759 +#: setup.php:1816 msgid "HTML Notification Settings" msgstr "" -#: setup.php:1764 +#: setup.php:1821 msgid "Enable HTML Based Email" msgstr "" -#: setup.php:1765 +#: setup.php:1822 msgid "If this checkbox is set, all Emails will be sent in HTML format. Otherwise, Emails will be sent in plain text." msgstr "" -#: setup.php:1770 +#: setup.php:1827 msgid "Format File to Use" msgstr "" -#: setup.php:1773 +#: setup.php:1830 msgid "Choose the custom html wrapper and CSS file to use. This file contains both html and CSS to wrap around your report. If it contains more than simply CSS, you need to place a special tag inside of the file. This format tag will be replaced by the report content. These files are located in the 'formats' directory." msgstr "" -#: setup.php:1777 +#: setup.php:1834 msgid "Data Retention Settings" msgstr "" -#: setup.php:1782 +#: setup.php:1839 msgid "Syslog Retention" msgstr "" -#: setup.php:1783 +#: setup.php:1840 msgid "This is the number of days to keep events." msgstr "" -#: setup.php:1789 +#: setup.php:1846 msgid "Partition Pre-create Window" msgstr "" -#: setup.php:1790 +#: setup.php:1847 msgid "This is the number of future daily partitions to maintain for partitioned Syslog tables." msgstr "" -#: setup.php:1794 setup.php:2082 setup.php:2101 syslog_alerts.php:516 +#: setup.php:1851 setup.php:2139 setup.php:2158 syslog_alerts.php:516 #, php-format msgid "%d Day" msgstr "" -#: setup.php:1795 setup.php:1796 setup.php:1797 setup.php:1798 setup.php:1799 -#: setup.php:1800 setup.php:2083 setup.php:2084 setup.php:2085 setup.php:2086 -#: setup.php:2087 setup.php:2102 setup.php:2103 setup.php:2104 setup.php:2105 -#: setup.php:2106 syslog_alerts.php:517 +#: setup.php:1852 setup.php:1853 setup.php:1854 setup.php:1855 setup.php:1856 +#: setup.php:1857 setup.php:2140 setup.php:2141 setup.php:2142 setup.php:2143 +#: setup.php:2144 setup.php:2159 setup.php:2160 setup.php:2161 setup.php:2162 +#: setup.php:2163 syslog_alerts.php:517 #, php-format msgid "%d Days" msgstr "" -#: setup.php:1804 +#: setup.php:1861 msgid "Partition Recovery Limit" msgstr "" -#: setup.php:1805 +#: setup.php:1862 msgid "When partitions are missing (for example after maintenance downtime), at most this many missing partitions per table are created on each poller run. The remaining gap heals over subsequent runs; retention pruning stays deferred until the future partition horizon is fully restored. Applies to partitioned Syslog tables only." msgstr "" -#: setup.php:1809 +#: setup.php:1866 #, php-format msgid "%d Partition per run" msgstr "" -#: setup.php:1810 setup.php:1811 setup.php:1812 setup.php:1813 setup.php:1814 +#: setup.php:1867 setup.php:1868 setup.php:1869 setup.php:1870 setup.php:1871 #, php-format msgid "%d Partitions per run" msgstr "" -#: setup.php:1818 +#: setup.php:1875 msgid "Collector Staleness Threshold" msgstr "" -#: setup.php:1819 +#: setup.php:1876 msgid "The Syslog Status page shows a warning when no new message has arrived within this many seconds. Set to 0 to use the default of 300 seconds." msgstr "" -#: setup.php:1823 +#: setup.php:1880 msgid "Default (300 seconds)" msgstr "" -#: setup.php:1824 setup.php:1825 setup.php:1826 setup.php:1827 setup.php:1828 +#: setup.php:1881 setup.php:1882 setup.php:1883 setup.php:1884 setup.php:1885 #, php-format msgid "%d seconds" msgstr "" -#: setup.php:1832 +#: setup.php:1889 msgid "Collector Backlog Threshold" msgstr "" -#: setup.php:1833 +#: setup.php:1890 msgid "The Syslog Status page shows a warning when more than this many messages sit unprocessed in the Syslog Incoming table. Set to 0 to use the default of 10000 messages." msgstr "" -#: setup.php:1837 +#: setup.php:1894 msgid "Default (10000 messages)" msgstr "" -#: setup.php:1838 setup.php:1839 setup.php:1840 setup.php:1841 +#: setup.php:1895 setup.php:1896 setup.php:1897 setup.php:1898 #, php-format msgid "%d Messages" msgstr "" -#: setup.php:1845 +#: setup.php:1902 msgid "Syslog Alert Retention" msgstr "" -#: setup.php:1846 +#: setup.php:1903 msgid "This is the number of days to keep alert logs." msgstr "" -#: setup.php:1852 +#: setup.php:1909 msgid "Alert Suppression and Maintenance" msgstr "" -#: setup.php:1857 +#: setup.php:1914 msgid "Maintenance Window Days" msgstr "" -#: setup.php:1858 +#: setup.php:1915 msgid "Days when all alert notifications are muted during the configured maintenance timeframe." msgstr "" -#: setup.php:1864 +#: setup.php:1921 msgid "Maintenance Window Starts" msgstr "" -#: setup.php:1865 +#: setup.php:1922 msgid "Local start time for the global maintenance window." msgstr "" -#: setup.php:1871 +#: setup.php:1928 msgid "Maintenance Window Ends" msgstr "" -#: setup.php:1872 +#: setup.php:1929 msgid "Local end time for the global maintenance window. An earlier end time continues into the next day." msgstr "" -#: setup.php:1878 +#: setup.php:1935 msgid "One-time Maintenance Starts" msgstr "" -#: setup.php:1879 +#: setup.php:1936 msgid "Optional local date and time to start a one-time global maintenance window." msgstr "" -#: setup.php:1883 +#: setup.php:1940 msgid "One-time Maintenance Ends" msgstr "" -#: setup.php:1884 +#: setup.php:1941 msgid "Optional local date and time to end a one-time global maintenance window. Format: YYYY-MM-DD HH:MM." msgstr "" -#: setup.php:1888 +#: setup.php:1945 msgid "Default Alert Cooldown" msgstr "" -#: setup.php:1889 +#: setup.php:1946 msgid "Suppress any repeat notification for the same rule and reporting scope for this many minutes. Per-rule values override this setting. Set to 0 to disable." msgstr "" -#: setup.php:1896 +#: setup.php:1953 msgid "Default Duplicate Suppression" msgstr "" -#: setup.php:1897 +#: setup.php:1954 msgid "Suppress a notification with the same matched message set for this many minutes. Per-rule values override this setting. Set to 0 to disable." msgstr "" -#: setup.php:1904 +#: setup.php:1961 msgid "Remote Message Processing" msgstr "" -#: setup.php:1908 +#: setup.php:1965 msgid "Enable Remote Data Collector Message Processing" msgstr "" -#: setup.php:1909 +#: setup.php:1966 msgid "If your Remote Data Collectors have their own Syslog databases and process their messages independently, check this checkbox. By checking this Checkbox, your Remote Data Collectors will need to maintain their own 'config_local.php' file in order to inform Syslog to use an independent database for message display and processing. Please use the template file 'config_local.php.dist' for this purpose. WARNING: Syslog tables will be automatically created as soon as this option is enabled." msgstr "" -#: setup.php:1914 +#: setup.php:1971 msgid "Remote Data Collector Rules Sync" msgstr "" -#: setup.php:1915 +#: setup.php:1972 msgid "If your Remote Data Collectors have their own Syslog databases and process thrie messages independently, check this checkbox if you wish the Main Cacti databases Alerts, Removal and Report rules to be sent to the Remote Cacti System." msgstr "" -#: setup.php:2036 syslog_removal.php:37 +#: setup.php:2093 syslog_device_rules.php:124 syslog_removal.php:37 msgid "Disable" msgstr "" -#: setup.php:2037 syslog_removal.php:38 +#: setup.php:2094 syslog_device_rules.php:124 syslog_removal.php:38 msgid "Enable" msgstr "" -#: setup.php:2038 syslog.php:1918 syslog_dashboards.php:300 -#: syslog_dashboards.php:351 syslog_removal.php:40 +#: setup.php:2095 syslog.php:1918 syslog_dashboards.php:300 +#: syslog_dashboards.php:351 syslog_device_rules.php:124 syslog_removal.php:40 #: syslog_saved_searches.php:271 syslog_saved_searches.php:315 msgid "Export" msgstr "" -#: setup.php:2081 setup.php:2100 +#: setup.php:2138 setup.php:2157 msgid "Indefinite" msgstr "" -#: setup.php:2088 setup.php:2107 syslog_alerts.php:518 +#: setup.php:2145 setup.php:2164 syslog_alerts.php:518 #, php-format msgid "%d Week" msgstr "" -#: setup.php:2089 setup.php:2108 syslog_alerts.php:519 +#: setup.php:2146 setup.php:2165 syslog_alerts.php:519 #, php-format msgid "%d Weeks" msgstr "" -#: setup.php:2090 setup.php:2109 +#: setup.php:2147 setup.php:2166 #, php-format msgid "%d Month" msgstr "" -#: setup.php:2091 setup.php:2092 setup.php:2093 setup.php:2094 setup.php:2095 -#: setup.php:2110 setup.php:2111 setup.php:2112 setup.php:2113 setup.php:2114 +#: setup.php:2148 setup.php:2149 setup.php:2150 setup.php:2151 setup.php:2152 +#: setup.php:2167 setup.php:2168 setup.php:2169 setup.php:2170 setup.php:2171 #, php-format msgid "%d Months" msgstr "" -#: setup.php:2096 setup.php:2115 +#: setup.php:2153 setup.php:2172 #, php-format msgid "%d Year" msgstr "" -#: setup.php:2119 syslog.php:295 syslog.php:310 syslog.php:325 +#: setup.php:2176 syslog.php:295 syslog.php:310 syslog.php:325 #: syslog_dashboards.php:324 syslog_reports.php:809 msgid "Never" msgstr "" -#: setup.php:2120 +#: setup.php:2177 #, php-format msgid "%d Minute" msgstr "" -#: setup.php:2121 setup.php:2122 setup.php:2123 syslog_alerts.php:503 +#: setup.php:2178 setup.php:2179 setup.php:2180 syslog_alerts.php:503 #: syslog_alerts.php:504 syslog_alerts.php:505 syslog_alerts.php:506 #: syslog_alerts.php:507 syslog_alerts.php:508 #, php-format msgid "%d Minutes" msgstr "" -#: setup.php:2127 syslog.php:1978 +#: setup.php:2184 syslog.php:1978 msgid "Notice" msgstr "" -#: setup.php:2128 syslog.php:1977 syslog.php:1996 +#: setup.php:2185 syslog.php:1977 syslog.php:1996 msgid "Warning" msgstr "" -#: setup.php:2129 syslog.php:1974 +#: setup.php:2186 syslog.php:1974 msgid "Critical" msgstr "" -#: setup.php:2133 +#: setup.php:2190 msgid "Begins with" msgstr "" -#: setup.php:2134 +#: setup.php:2191 msgid "Contains" msgstr "" -#: setup.php:2135 +#: setup.php:2192 msgid "Ends with" msgstr "" -#: setup.php:2136 +#: setup.php:2193 msgid "Hostname is" msgstr "" -#: setup.php:2137 +#: setup.php:2194 msgid "Program is" msgstr "" -#: setup.php:2138 +#: setup.php:2195 msgid "Facility is" msgstr "" -#: setup.php:2139 syslog_alerts.php:690 +#: setup.php:2196 syslog_alerts.php:690 msgid "Filter Builder" msgstr "" -#: setup.php:2140 syslog_alerts.php:691 +#: setup.php:2197 syslog_alerts.php:691 msgid "SQL Expression" msgstr "" -#: setup.php:2144 +#: setup.php:2201 msgid "Daily" msgstr "" -#: setup.php:2145 +#: setup.php:2202 msgid "Weekly" msgstr "" -#: setup.php:2172 +#: setup.php:2229 msgid "Import/Export" msgstr "" -#: setup.php:2173 +#: setup.php:2230 msgid "Alert Rules" msgstr "" -#: setup.php:2173 setup.php:2174 setup.php:2175 setup.php:2176 setup.php:2177 -#: setup.php:2182 +#: setup.php:2230 setup.php:2231 setup.php:2232 setup.php:2233 setup.php:2234 +#: setup.php:2235 setup.php:2240 msgid "Syslog Settings" msgstr "" -#: setup.php:2174 +#: setup.php:2231 syslog_device_rules.php:257 +msgid "Device Alert Rules" +msgstr "" + +#: setup.php:2232 msgid "Removal Rules" msgstr "" -#: setup.php:2175 +#: setup.php:2233 msgid "Report Rules" msgstr "" -#: setup.php:2176 setup.php:2233 syslog_saved_searches.php:195 +#: setup.php:2234 setup.php:2294 syslog_saved_searches.php:195 msgid "Saved Search Templates" msgstr "" -#: setup.php:2220 +#: setup.php:2279 msgid "Syslog Removals" msgstr "" -#: setup.php:2221 setup.php:2222 setup.php:2226 setup.php:2227 setup.php:2231 +#: setup.php:2280 setup.php:2281 setup.php:2285 setup.php:2286 setup.php:2289 +#: setup.php:2292 msgid "(Edit)" msgstr "" -#: setup.php:2223 setup.php:2228 setup.php:2232 +#: setup.php:2282 setup.php:2287 setup.php:2293 msgid "(Actions)" msgstr "" -#: setup.php:2225 +#: setup.php:2284 msgid "Syslog Alerts" msgstr "" -#: setup.php:2230 +#: setup.php:2288 +msgid "Syslog Device Alert Rules" +msgstr "" + +#: setup.php:2291 msgid "Syslog Reports" msgstr "" -#: setup.php:2334 +#: setup.php:2395 msgid "Display Syslog in Range" msgstr "" -#: setup.php:2404 +#: setup.php:2465 #, php-format msgid "There were %s Device records removed from the Syslog database" msgstr "" -#: setup.php:2425 +#: setup.php:2486 msgid "Syslog Utilities" msgstr "" -#: setup.php:2429 +#: setup.php:2490 msgid "Purge Syslog Devices" msgstr "" -#: setup.php:2431 +#: setup.php:2492 msgid "Are you sure you want to purge stale Syslog devices?" msgstr "" -#: setup.php:2437 +#: setup.php:2498 msgid "Confirm Purge" msgstr "" -#: setup.php:2451 syslog_alerts.php:230 syslog_dashboards.php:428 -#: syslog_removal.php:248 syslog_reports.php:213 syslog_saved_searches.php:384 +#: setup.php:2512 syslog_alerts.php:230 syslog_dashboards.php:428 +#: syslog_device_rules.php:126 syslog_removal.php:248 syslog_reports.php:213 +#: syslog_saved_searches.php:384 msgid "Continue" msgstr "" -#: setup.php:2477 +#: setup.php:2538 msgid "This menu pick provides a means to remove Devices that are no longer reporting into Cacti's syslog server." msgstr "" @@ -1580,7 +1591,7 @@ msgstr "" msgid "[ Unprocessed Messages: %s ]" msgstr "" -#: syslog.php:1728 +#: syslog.php:1728 syslog_device_rules.php:223 msgid "Enter a search term" msgstr "" @@ -1662,7 +1673,8 @@ msgid "Display Rows" msgstr "" #: syslog.php:1822 syslog_alerts.php:1055 syslog_dashboards.php:237 -#: syslog_removal.php:827 syslog_reports.php:665 syslog_saved_searches.php:229 +#: syslog_device_rules.php:225 syslog_removal.php:827 syslog_reports.php:665 +#: syslog_saved_searches.php:229 msgid "Default" msgstr "" @@ -1720,12 +1732,14 @@ msgid "Save Search As" msgstr "" #: syslog.php:1915 syslog_alerts.php:1035 syslog_dashboards.php:227 -#: syslog_removal.php:807 syslog_reports.php:645 syslog_saved_searches.php:219 +#: syslog_device_rules.php:223 syslog_removal.php:807 syslog_reports.php:645 +#: syslog_saved_searches.php:219 msgid "Search" msgstr "" #: syslog.php:1916 syslog_alerts.php:1072 syslog_dashboards.php:254 -#: syslog_removal.php:844 syslog_reports.php:682 syslog_saved_searches.php:246 +#: syslog_device_rules.php:226 syslog_removal.php:844 syslog_reports.php:682 +#: syslog_saved_searches.php:246 msgid "Clear" msgstr "" @@ -1774,6 +1788,7 @@ msgid "Informational" msgstr "" #: syslog.php:2115 syslog.php:2240 syslog.php:2296 syslog_alerts.php:664 +#: syslog_device_rules.php:167 syslog_device_rules.php:258 msgid "Device" msgstr "" @@ -1825,6 +1840,10 @@ msgstr "" msgid "Create Alarm Rule" msgstr "" +#: syslog.php:2299 +msgid "Create Device Alert Rule" +msgstr "" + #: syslog.php:2299 msgid "Create Removal Rule" msgstr "" @@ -1989,7 +2008,8 @@ msgid "Build filter conditions or enter an SQL expression to match syslog messag msgstr "" #: syslog_alerts.php:708 syslog_alerts.php:711 syslog_alerts.php:1041 -#: syslog_alerts.php:1173 syslog_removal.php:599 syslog_removal.php:813 +#: syslog_alerts.php:1173 syslog_device_rules.php:168 +#: syslog_device_rules.php:224 syslog_removal.php:599 syslog_removal.php:813 #: syslog_removal.php:942 syslog_reports.php:499 syslog_reports.php:651 #: syslog_reports.php:780 msgid "Enabled" @@ -2115,7 +2135,7 @@ msgstr "" msgid "Optional local date and time to stop muting this rule. Format: YYYY-MM-DD HH:MM." msgstr "" -#: syslog_alerts.php:783 syslog_reports.php:568 +#: syslog_alerts.php:783 syslog_device_rules.php:173 syslog_reports.php:568 msgid "Notes" msgstr "" @@ -2164,14 +2184,18 @@ msgid "Should a Help Desk Ticket be opened for this Alert. NOTE: The Ticket com msgstr "" #: syslog_alerts.php:834 syslog_alerts.php:1047 syslog_alerts.php:1198 -#: syslog_dashboards.php:322 syslog_dashboards.php:735 syslog_removal.php:819 -#: syslog_removal.php:964 syslog_reports.php:657 syslog_reports.php:804 +#: syslog_dashboards.php:322 syslog_dashboards.php:735 +#: syslog_device_rules.php:172 syslog_device_rules.php:224 +#: syslog_removal.php:819 syslog_removal.php:964 syslog_reports.php:657 +#: syslog_reports.php:804 msgid "No" msgstr "" #: syslog_alerts.php:834 syslog_alerts.php:1046 syslog_alerts.php:1198 -#: syslog_dashboards.php:322 syslog_dashboards.php:735 syslog_removal.php:818 -#: syslog_removal.php:964 syslog_reports.php:656 syslog_reports.php:804 +#: syslog_dashboards.php:322 syslog_dashboards.php:735 +#: syslog_device_rules.php:172 syslog_device_rules.php:224 +#: syslog_removal.php:818 syslog_removal.php:964 syslog_reports.php:656 +#: syslog_reports.php:804 msgid "Yes" msgstr "" @@ -2216,7 +2240,8 @@ msgstr "" msgid "Alarm filter conditions" msgstr "" -#: syslog_alerts.php:1045 syslog_removal.php:817 syslog_reports.php:655 +#: syslog_alerts.php:1045 syslog_device_rules.php:224 syslog_removal.php:817 +#: syslog_reports.php:655 msgid "All" msgstr "" @@ -2225,8 +2250,8 @@ msgstr "" msgid "Rows" msgstr "" -#: syslog_alerts.php:1071 syslog_dashboards.php:253 syslog_removal.php:843 -#: syslog_reports.php:681 syslog_saved_searches.php:245 +#: syslog_alerts.php:1071 syslog_dashboards.php:253 syslog_device_rules.php:226 +#: syslog_removal.php:843 syslog_reports.php:681 syslog_saved_searches.php:245 msgid "Go" msgstr "" @@ -2453,6 +2478,138 @@ msgstr "" msgid "Renaming applies to every viewer of this dashboard. Panels are managed by their owners from the Syslog Dashboard tab." msgstr "" +#: syslog_device_rules.php:63 +msgid "Choose a future pause end date and time." +msgstr "" + +#: syslog_device_rules.php:69 +msgid "A device name is required." +msgstr "" + +#: syslog_device_rules.php:125 +#, php-format +msgid "Click Continue to %s the following Device Alert Rule(s)." +msgstr "" + +#: syslog_device_rules.php:161 +msgid "Do not pass any priority" +msgstr "" + +#: syslog_device_rules.php:163 +#, php-format +msgid "%s and more urgent" +msgstr "" + +#: syslog_device_rules.php:166 +msgid "Device Alert Rule" +msgstr "" + +#: syslog_device_rules.php:167 +msgid "Search current Syslog devices as you type, or enter any IP address or hostname." +msgstr "" + +#: syslog_device_rules.php:169 +msgid "Alert Handling" +msgstr "" + +#: syslog_device_rules.php:169 +msgid "Do not pause" +msgstr "" + +#: syslog_device_rules.php:169 +msgid "Pause all non-exempt alerts until a date, or indefinitely." +msgstr "" + +#: syslog_device_rules.php:169 +msgid "Pause indefinitely" +msgstr "" + +#: syslog_device_rules.php:169 +msgid "Pause until" +msgstr "" + +#: syslog_device_rules.php:170 +msgid "Local date and time, YYYY-MM-DD HH:MM." +msgstr "" + +#: syslog_device_rules.php:170 +msgid "Pause Ends" +msgstr "" + +#: syslog_device_rules.php:171 +msgid "Always Allow Priority" +msgstr "" + +#: syslog_device_rules.php:171 +msgid "These priorities pass through this device pause and maintenance windows. Critical and more urgent is a typical platinum-device choice." +msgstr "" + +#: syslog_device_rules.php:172 +msgid "Allow During Maintenance" +msgstr "" + +#: syslog_device_rules.php:172 +msgid "Allow all priorities from this device during an alert maintenance window. The priority exception above still applies when this is No." +msgstr "" + +#: syslog_device_rules.php:180 +msgid "Device Alert Rule [edit]" +msgstr "" + +#: syslog_device_rules.php:180 +msgid "Device Alert Rule [new]" +msgstr "" + +#: syslog_device_rules.php:220 +msgid "Device Alert Rule Filters" +msgstr "" + +#: syslog_device_rules.php:225 syslog_device_rules.php:254 +#: syslog_removal.php:823 syslog_removal.php:952 +msgid "Rules" +msgstr "" + +#: syslog_device_rules.php:258 +msgid "Handling" +msgstr "" + +#: syslog_device_rules.php:258 +msgid "Maintenance" +msgstr "" + +#: syslog_device_rules.php:258 +msgid "Pass Through" +msgstr "" + +#: syslog_device_rules.php:261 +msgid "No device alert rules found." +msgstr "" + +#: syslog_device_rules.php:264 +msgid "Not paused" +msgstr "" + +#: syslog_device_rules.php:264 +msgid "Paused indefinitely" +msgstr "" + +#: syslog_device_rules.php:264 +#, php-format +msgid "Paused until %s" +msgstr "" + +#: syslog_device_rules.php:265 +msgid "and more urgent" +msgstr "" + +#: syslog_device_rules.php:270 +msgid "Allow all" +msgstr "" + +#: syslog_device_rules.php:270 +msgid "Use priority exception" +msgstr "" + #: syslog_removal.php:39 msgid "Reprocess" msgstr "" @@ -2579,10 +2736,6 @@ msgstr "" msgid "Removal filter conditions" msgstr "" -#: syslog_removal.php:823 syslog_removal.php:952 -msgid "Rules" -msgstr "" - #: syslog_removal.php:915 msgid "Syslog Removal Rule Filters" msgstr "" diff --git a/locales/po/ka-GE.po b/locales/po/ka-GE.po index 4006252..eba0bbf 100644 --- a/locales/po/ka-GE.po +++ b/locales/po/ka-GE.po @@ -4,19 +4,7 @@ # FIRST AUTHOR , YEAR. # msgid "" -msgstr "" -"Project-Id-Version: Cacti\n" -"Report-Msgid-Bugs-To: developers@cacti.net\n" -"POT-Creation-Date: 2026-09-22 20:32-0400\n" -"PO-Revision-Date: 2026-08-04 11:18+0000\n" -"Last-Translator: Ekaterine papava \n" -"Language-Team: Georgian \n" -"Language: ka-GE\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.11.4\n" +msgstr "Project-Id-Version: Cacti\nReport-Msgid-Bugs-To: developers@cacti.net\nPOT-Creation-Date: 2026-09-22 20:32-0400\nPO-Revision-Date: 2026-09-25 03:18+0000\nLast-Translator: Ekaterine papava \nLanguage-Team: Georgian \nLanguage: ka-GE\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Generator: Weblate 5.11.4\n" #: functions.php:687 #, fuzzy @@ -318,7 +306,7 @@ msgstr "" #: lib/syslog_dashboard.php:616 msgid "Other" -msgstr "" +msgstr "სხვა" #: lib/syslog_dashboard.php:659 lib/syslog_dashboard.php:1044 msgid "A valid dashboard panel is required." @@ -430,46 +418,43 @@ msgstr "Syslog ჩართულია" #: lib/syslog_dashboard.php:1396 lib/syslog_dashboard.php:1557 #: lib/syslog_dashboard.php:1581 syslog.php:256 msgid "Dashboard" -msgstr "" +msgstr "სამუშაო დაფა" #: lib/syslog_dashboard.php:1399 lib/syslog_dashboard.php:1579 msgid "Time Range" msgstr "დროის შუალედი" #: lib/syslog_dashboard.php:1404 lib/syslog_dashboard.php:1582 -#, fuzzy msgid "Last Hour" -msgstr "%d საათი" +msgstr "ბოლო საათი" #: lib/syslog_dashboard.php:1405 lib/syslog_dashboard.php:1583 -#, fuzzy, php-format +#, php-format msgid "Last %d Hours" -msgstr "%d საათი" +msgstr "ბოლო %d საათი" #: lib/syslog_dashboard.php:1406 lib/syslog_dashboard.php:1584 msgid "Last Day" -msgstr "" +msgstr "ბოლო დღე" #: lib/syslog_dashboard.php:1407 lib/syslog_dashboard.php:1585 -#, fuzzy msgid "Last Week" -msgstr "ბოლო გაგზავნილი" +msgstr "ბოლო კვირა" #: lib/syslog_dashboard.php:1408 lib/syslog_dashboard.php:1586 -#, fuzzy, php-format +#, php-format msgid "Last %d Weeks" -msgstr "%d კვირა" +msgstr "ბოლო %dკვირა" #: lib/syslog_dashboard.php:1409 lib/syslog_dashboard.php:1587 -#, fuzzy msgid "Last Month" -msgstr "ბოლო გაგზავნილი" +msgstr "ბოლო თვე" #: lib/syslog_dashboard.php:1410 lib/syslog_dashboard.php:1411 #: lib/syslog_dashboard.php:1588 lib/syslog_dashboard.php:1589 -#, fuzzy, php-format +#, php-format msgid "Last %d Months" -msgstr "%d თვე" +msgstr "ბოლო %d თვე" #: lib/syslog_dashboard.php:1421 syslog.php:1839 syslog.php:1917 msgid "Refresh" @@ -495,11 +480,11 @@ msgstr "" #: lib/syslog_dashboard.php:1482 syslog.php:1796 msgid "New" -msgstr "" +msgstr "ახალი" #: lib/syslog_dashboard.php:1484 msgid "Rename" -msgstr "" +msgstr "სახელის გადარქმევა" #: lib/syslog_dashboard.php:1495 msgid "Add Panel" @@ -519,7 +504,7 @@ msgstr "" #: lib/syslog_dashboard.php:1529 msgid "Title" -msgstr "" +msgstr "სათაური" #: lib/syslog_dashboard.php:1533 msgid "Log Source" @@ -553,24 +538,23 @@ msgstr "%d სიმბოლო" #: lib/syslog_dashboard.php:1549 msgid "Line" -msgstr "" +msgstr "ხაზი" #: lib/syslog_dashboard.php:1550 msgid "Area" -msgstr "" +msgstr "არე" #: lib/syslog_dashboard.php:1551 msgid "Bar" -msgstr "" +msgstr "პანელი" #: lib/syslog_dashboard.php:1555 -#, fuzzy msgid "Interval" -msgstr "განახლების შუალედი" +msgstr "ინტერვალი" #: lib/syslog_dashboard.php:1558 msgid "Auto" -msgstr "" +msgstr "ავტო" #: lib/syslog_dashboard.php:1559 #, fuzzy @@ -801,31 +785,31 @@ msgstr "წაშლა" #: setup.php:1658 msgid "Monday" -msgstr "" +msgstr "ორშაბათი" #: setup.php:1658 msgid "Tuesday" -msgstr "" +msgstr "სამშაბათი" #: setup.php:1658 msgid "Wednesday" -msgstr "" +msgstr "ოთხშაბათი" #: setup.php:1659 msgid "Friday" -msgstr "" +msgstr "პარასკევი" #: setup.php:1659 msgid "Saturday" -msgstr "" +msgstr "შაბათი" #: setup.php:1659 msgid "Sunday" -msgstr "" +msgstr "კვირა" #: setup.php:1659 msgid "Thursday" -msgstr "" +msgstr "ხუთშაბათი" #: setup.php:1660 msgid "Monday through Friday" @@ -837,7 +821,7 @@ msgstr "" #: setup.php:1661 msgid "Every day" -msgstr "" +msgstr "ყოველდღე" #: setup.php:1664 syslog_alerts.php:711 syslog_alerts.php:726 #: syslog_alerts.php:734 syslog_removal.php:599 syslog_reports.php:499 @@ -1000,14 +984,14 @@ msgid "When partitions are missing (for example after maintenance downtime), at msgstr "" #: setup.php:1809 -#, fuzzy, php-format +#, php-format msgid "%d Partition per run" -msgstr "დანაყოფი დღეში" +msgstr "%d დანაყოფი გაშვებაზე" #: setup.php:1810 setup.php:1811 setup.php:1812 setup.php:1813 setup.php:1814 -#, fuzzy, php-format +#, php-format msgid "%d Partitions per run" -msgstr "დანაყოფი დღეში" +msgstr "%d დანაყოფი გაშვებაზე" #: setup.php:1818 msgid "Collector Staleness Threshold" @@ -1039,9 +1023,9 @@ msgid "Default (10000 messages)" msgstr "" #: setup.php:1838 setup.php:1839 setup.php:1840 setup.php:1841 -#, fuzzy, php-format +#, php-format msgid "%d Messages" -msgstr "შეტყობინებები" +msgstr "%d შეტყობინება" #: setup.php:1845 msgid "Syslog Alert Retention" @@ -1338,7 +1322,7 @@ msgstr "არჩეული განგაში" #: syslog.php:313 syslog.php:543 msgid "seconds" -msgstr "" +msgstr "წამი" #: syslog.php:334 msgid "min/avg/max" diff --git a/setup.php b/setup.php index 6adf4ca..0edeef5 100644 --- a/setup.php +++ b/setup.php @@ -69,7 +69,7 @@ function plugin_syslog_install() { api_plugin_register_hook('syslog', 'replicate_out', 'syslog_replicate_out', 'setup.php'); api_plugin_register_realm('syslog', 'syslog.php', 'Syslog User', 1); - api_plugin_register_realm('syslog', 'syslog_alerts.php,syslog_removal.php,syslog_reports.php,syslog_saved_searches.php,syslog_dashboards.php', 'Syslog Administration', 1); + api_plugin_register_realm('syslog', 'syslog_alerts.php,syslog_device_rules.php,syslog_removal.php,syslog_reports.php,syslog_saved_searches.php,syslog_dashboards.php', 'Syslog Administration', 1); api_plugin_register_realm('syslog', 'syslog_saved_searches_share.php', 'Share Saved Templates', 1); api_plugin_register_realm('syslog', 'syslog_dashboards_share.php', 'Share Dashboards', 1); @@ -392,6 +392,29 @@ function syslog_upgrade_dashboard_realm(): void { } } +/** Give existing Syslog administrators access to device alert rules. */ +function syslog_upgrade_device_rule_realm(): void { + global $user_auth_realm_filenames; + $realms = db_fetch_assoc_prepared('SELECT id, file FROM plugin_realms WHERE plugin = ?', ['syslog']); + if (!is_array($realms)) { + return; + } + foreach ($realms as $realm) { + $files = explode(',', $realm['file']); + if (!in_array('syslog_alerts.php', $files, true)) { + continue; + } + if (!in_array('syslog_device_rules.php', $files, true)) { + if (!db_execute_prepared('UPDATE plugin_realms SET file = ? WHERE id = ? AND plugin = ?', [$realm['file'] . ',syslog_device_rules.php', $realm['id'], 'syslog'])) { + return; + } + api_plugin_replicate_config(); + } + $user_auth_realm_filenames['syslog_device_rules.php'] = (int) $realm['id'] + 100; + return; + } +} + /** * Upgrade the Syslog database schema for legacy installs. * @@ -403,12 +426,13 @@ function syslog_check_upgrade(): void { syslog_connect(); syslog_upgrade_saved_search_realm(); syslog_upgrade_dashboard_realm(); + syslog_upgrade_device_rule_realm(); // Keep newly introduced permission realms available for existing installs. api_plugin_register_realm('syslog', 'syslog_saved_searches_share.php', 'Share Saved Templates', 0); api_plugin_register_realm('syslog', 'syslog_dashboards_share.php', 'Share Dashboards', 0); // Let's only run this check if we are on a page that actually needs the data - $files = ['plugins.php', 'syslog.php', 'syslog_removal.php', 'syslog_alerts.php', 'syslog_reports.php', 'syslog_saved_searches.php', 'syslog_dashboards.php']; + $files = ['plugins.php', 'syslog.php', 'syslog_removal.php', 'syslog_alerts.php', 'syslog_device_rules.php', 'syslog_reports.php', 'syslog_saved_searches.php', 'syslog_dashboards.php']; if (substr($_SERVER['SCRIPT_FILENAME'], -18) != 'syslog_process.php' && !in_array(get_current_page(), $files, true)) { return; @@ -626,6 +650,25 @@ function syslog_check_upgrade(): void { INDEX `last_sent` (`last_sent`)) ENGINE=InnoDB"); + // Device rules are evaluated against every matching incoming record, rather + // than against a particular alert rule. This keeps a device mute effective + // for every alert definition that could match the device. + syslog_db_execute("CREATE TABLE IF NOT EXISTS `$syslogdb_default`.`syslog_device_rule` ( + `id` int(10) unsigned NOT NULL auto_increment, + `host` varchar(64) NOT NULL, + `enabled` char(2) NOT NULL default 'on', + `mute_mode` varchar(16) NOT NULL default 'none', + `mute_until` int(10) unsigned NOT NULL default '0', + `pass_through_priority` tinyint NOT NULL default '-1', + `allow_maintenance` char(2) NOT NULL default '', + `notes` varchar(255) NOT NULL default '', + `user` varchar(64) NOT NULL default '', + `date` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), + UNIQUE KEY `host` (`host`), + KEY `enabled_mute` (`enabled`, `mute_mode`, `mute_until`)) + ENGINE=InnoDB"); + // Structured filter JSON can exceed the old VARCHAR limit. TEXT also keeps // the alert table below the InnoDB/MariaDB inline row-size ceiling. syslog_db_execute('ALTER TABLE syslog_alert MODIFY column message TEXT NOT NULL'); @@ -1050,6 +1093,20 @@ function syslog_setup_table_new(array $options): void { INDEX `last_sent` (`last_sent`)) ENGINE=InnoDB"); + syslog_db_execute("CREATE TABLE IF NOT EXISTS `$syslogdb_default`.`syslog_device_rule` ( + `id` int(10) unsigned NOT NULL auto_increment, + `host` varchar(64) NOT NULL, + `enabled` char(2) NOT NULL default 'on', + `mute_mode` varchar(16) NOT NULL default 'none', + `mute_until` int(10) unsigned NOT NULL default '0', + `pass_through_priority` tinyint NOT NULL default '-1', + `allow_maintenance` char(2) NOT NULL default '', + `notes` varchar(255) NOT NULL default '', + `user` varchar(64) NOT NULL default '', + `date` int(10) unsigned NOT NULL default '0', + PRIMARY KEY (`id`), UNIQUE KEY `host` (`host`), + KEY `enabled_mute` (`enabled`, `mute_mode`, `mute_until`)) ENGINE=InnoDB"); + if ($truncate) { syslog_db_execute("DROP TABLE IF EXISTS `$syslogdb_default`.`syslog_remove`"); } @@ -2171,6 +2228,7 @@ function syslog_config_arrays(): void { if ($temp == __('Import/Export')) { $menu2[__('Syslog Settings', 'syslog')]['plugins/syslog/syslog_alerts.php'] = __('Alert Rules', 'syslog'); + $menu2[__('Syslog Settings', 'syslog')]['plugins/syslog/syslog_device_rules.php'] = __('Device Alert Rules', 'syslog'); $menu2[__('Syslog Settings', 'syslog')]['plugins/syslog/syslog_removal.php'] = __('Removal Rules', 'syslog'); $menu2[__('Syslog Settings', 'syslog')]['plugins/syslog/syslog_reports.php'] = __('Report Rules', 'syslog'); $menu2[__('Syslog Settings', 'syslog')]['plugins/syslog/syslog_saved_searches.php'] = __('Saved Search Templates', 'syslog'); @@ -2188,6 +2246,7 @@ function syslog_config_arrays(): void { auth_augment_roles(__('Syslog', 'syslog'), [ 'syslog.php', 'syslog_alerts.php', + 'syslog_device_rules.php', 'syslog_removal.php', 'syslog_reports.php', 'syslog_saved_searches.php', @@ -2226,6 +2285,8 @@ function syslog_draw_navigation_text($nav) { $nav['syslog_alerts.php:edit'] = ['title' => __('(Edit)', 'syslog'), 'mapping' => 'index.php:,syslog_alerts.php:', 'url' => 'syslog_alerts.php', 'level' => '2']; $nav['syslog_alerts.php:newedit'] = ['title' => __('(Edit)', 'syslog'), 'mapping' => 'index.php:,syslog_alerts.php:', 'url' => 'syslog_alerts.php', 'level' => '2']; $nav['syslog_alerts.php:actions'] = ['title' => __('(Actions)', 'syslog'), 'mapping' => 'index.php:,syslog_alerts.php:', 'url' => 'syslog_alerts.php', 'level' => '2']; + $nav['syslog_device_rules.php:'] = ['title' => __('Syslog Device Alert Rules', 'syslog'), 'mapping' => 'index.php:', 'url' => $config['url_path'] . 'plugins/syslog/syslog_device_rules.php', 'level' => '1']; + $nav['syslog_device_rules.php:edit'] = ['title' => __('(Edit)', 'syslog'), 'mapping' => 'index.php:,syslog_device_rules.php:', 'url' => 'syslog_device_rules.php', 'level' => '2']; $nav['syslog_reports.php:'] = ['title' => __('Syslog Reports', 'syslog'), 'mapping' => 'index.php:', 'url' => $config['url_path'] . 'plugins/syslog/syslog_reports.php', 'level' => '1']; $nav['syslog_reports.php:edit'] = ['title' => __('(Edit)', 'syslog'), 'mapping' => 'index.php:,syslog_reports.php:', 'url' => 'syslog_reports.php', 'level' => '2']; diff --git a/syslog.php b/syslog.php index 6e2e8e9..6b77ddc 100644 --- a/syslog.php +++ b/syslog.php @@ -2296,7 +2296,7 @@ function syslog_messages(string $tab = 'syslog'): void {

__('Date', 'syslog'), 'device' => __('Device', 'syslog'), 'program' => __('Program', 'syslog'), 'facility' => __('Facility', 'syslog'), 'severity' => __('Priority', 'syslog')] as $key => $label) { print '
' . html_escape($label) . "
"; } ?>


 		
' data-error=''>
-
+
diff --git a/syslog_device_rules.php b/syslog_device_rules.php new file mode 100644 index 0000000..13d95d9 --- /dev/null +++ b/syslog_device_rules.php @@ -0,0 +1,285 @@ + 1000) { + $limit = 1000; + } + header('Content-Type: application/json; charset=UTF-8'); + $hosts = syslog_db_fetch_assoc_prepared("SELECT host FROM `$syslogdb_default`.`syslog_hosts` WHERE host LIKE ? ORDER BY host LIMIT $limit", [$term]); + print json_encode(array_map(static fn($host) => ['label' => $host['host'], 'value' => $host['host']], $hosts)); + exit; +} + +set_default_action(); + +switch (get_request_var('action')) { + case 'save': + device_rule_save(); + break; + case 'actions': + device_rule_actions(); + break; + case 'export': + device_rule_export(); + break; + case 'edit': + top_header(); + syslog_include_js(); + device_rule_edit(); + bottom_footer(); + break; + default: + top_header(); + syslog_include_js(); + device_rule_list(); + bottom_footer(); +} + +function device_rule_save(): void { + if (!syslog_allow_edits() || !isset_request_var('save_component_device_rule')) { + return; + } + $mode = get_nfilter_request_var('mute_mode'); + $mode = in_array($mode, ['none', 'until', 'indefinite'], true) ? $mode : 'none'; + $until = $mode === 'until' ? strtotime(get_nfilter_request_var('mute_until')) : 0; + if ($mode === 'until' && ($until === false || $until <= time())) { + raise_message('syslog_device_rule_time', __('Choose a future pause end date and time.', 'syslog'), MESSAGE_LEVEL_ERROR); + header('Location: syslog_device_rules.php?action=edit&id=' . get_filter_request_var('id')); + return; + } + $host = trim(get_nfilter_request_var('host')); + if ($host === '') { + raise_message('syslog_device_rule_host', __('A device name is required.', 'syslog'), MESSAGE_LEVEL_ERROR); + header('Location: syslog_device_rules.php?action=edit&id=' . get_filter_request_var('id')); + return; + } + $priority = get_filter_request_var('pass_through_priority'); + $priority = $priority >= -1 && $priority <= 7 ? $priority : -1; + $save = [ + 'id' => get_filter_request_var('id'), 'host' => $host, + 'enabled' => get_nfilter_request_var('enabled') === 'on' ? 'on' : '', + 'mute_mode' => $mode, 'mute_until' => (int) $until, + 'pass_through_priority' => $priority, + 'allow_maintenance' => get_nfilter_request_var('allow_maintenance') === 'on' ? 'on' : '', + 'notes' => form_input_validate(get_nfilter_request_var('notes'), 'notes', '', true, 3), + 'user' => get_username($_SESSION['sess_user_id']), 'date' => time() + ]; + syslog_sync_save($save, 'syslog_device_rule', 'id'); + header('Location: syslog_device_rules.php'); +} + +/** Render and apply the standard Cacti bulk-action confirmation workflow. */ +function device_rule_actions(): void { + global $syslog_actions, $syslogdb_default; + get_filter_request_var('drp_action', FILTER_VALIDATE_REGEXP, ['options' => ['regexp' => '/^[1-4]$/']]); + if (isset_request_var('selected_items')) { + $items = sanitize_unserialize_selected_items(get_request_var('selected_items')); + $action = get_request_var('drp_action'); + if ($items !== false && $action === '4') { + $_SESSION['syslog_device_rule_exporter'] = rawurlencode(serialize($items)); + } elseif ($items !== false && syslog_allow_edits()) { + foreach ($items as $id) { + if ((int) $id < 1) continue; + if ($action === '1') syslog_db_execute_prepared("DELETE FROM `$syslogdb_default`.`syslog_device_rule` WHERE id = ?", [$id]); + if ($action === '2') syslog_db_execute_prepared("UPDATE `$syslogdb_default`.`syslog_device_rule` SET enabled = '' WHERE id = ?", [$id]); + if ($action === '3') syslog_db_execute_prepared("UPDATE `$syslogdb_default`.`syslog_device_rule` SET enabled = 'on' WHERE id = ?", [$id]); + } + } + header('Location: syslog_device_rules.php'); + return; + } + top_header(); + form_start('syslog_device_rules.php'); + html_start_box($syslog_actions[get_request_var('drp_action')], '60%', '', '3', 'center', ''); + $items = []; + $list = ''; + foreach ($_POST as $name => $value) { + if (preg_match('/^chk_([0-9]+)$/', $name, $matches)) { + $rule = syslog_db_fetch_cell_prepared("SELECT host FROM `$syslogdb_default`.`syslog_device_rule` WHERE id = ?", [(int) $matches[1]]); + if ($rule !== null) { $items[] = $matches[1]; $list .= '
  • ' . html_escape($rule) . '
  • '; } + } + } + if (!cacti_sizeof($items)) { + raise_message(40); + header('Location: syslog_device_rules.php'); + return; + } + $verb = [1 => __('Delete', 'syslog'), 2 => __('Disable', 'syslog'), 3 => __('Enable', 'syslog'), 4 => __('Export', 'syslog')][(int) get_request_var('drp_action')]; + print '

    ' . __esc('Click Continue to %s the following Device Alert Rule(s).', strtolower($verb), 'syslog') . '

      ' . $list . '
    '; + print ' '; + html_end_box(); + form_end(false); + bottom_footer(); +} + +/** Download selected device alert rules as a portable JSON document. */ +function device_rule_export(): void { + global $syslogdb_default; + $items = sanitize_unserialize_selected_items(get_nfilter_request_var('selected_items')); + if ($items === false) { + return; + } + $rules = []; + foreach ($items as $id) { + if ((int) $id < 1) continue; + $rule = syslog_db_fetch_row_prepared("SELECT * FROM `$syslogdb_default`.`syslog_device_rule` WHERE id = ?", [$id]); + if (cacti_sizeof($rule)) { + unset($rule['id']); + $rules[] = $rule; + } + } + $output = json_encode(['version' => SYSLOG_IMPORT_VERSION, 'generator' => 'syslog', 'table' => 'syslog_device_rule', 'templates' => $rules], JSON_PRETTY_PRINT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); + header('Content-Type: application/json; charset=UTF-8'); + header('Content-Disposition: attachment; filename=syslog_device_rules_export.json'); + print $output === false ? '' : $output; +} + +function device_rule_edit(): void { + global $syslog_levels, $syslogdb_default; + $id = get_filter_request_var('id'); + $rule = $id ? syslog_db_fetch_row_prepared("SELECT * FROM `$syslogdb_default`.`syslog_device_rule` WHERE id = ?", [$id]) : []; + if (!cacti_sizeof($rule)) { + $rule = ['host' => get_nfilter_request_var('host'), 'enabled' => 'on', 'mute_mode' => 'none', 'mute_until' => '', 'pass_through_priority' => '-1', 'allow_maintenance' => '', 'notes' => '']; + } + $priorities = ['-1' => __('Do not pass any priority', 'syslog')]; + foreach ($syslog_levels as $priority => $label) { + $priorities[$priority] = __esc('%s and more urgent', ucfirst($label), 'syslog'); + } + $fields = [ + 'spacer' => ['method' => 'spacer', 'friendly_name' => __('Device Alert Rule', 'syslog')], + 'host' => ['method' => 'drop_callback', 'action' => 'ajax_hosts', 'id' => $rule['host'], 'sql' => 'SELECT ' . db_qstr($rule['host']) . ' AS id, ' . db_qstr($rule['host']) . ' AS name', 'friendly_name' => __('Device', 'syslog'), 'description' => __('Search current Syslog devices as you type, or enter any IP address or hostname.', 'syslog'), 'value' => '|arg1:host|', 'size' => 50, 'max_length' => 64], + 'enabled' => ['method' => 'drop_array', 'friendly_name' => __('Enabled', 'syslog'), 'array' => ['on' => __('Enabled', 'syslog'), '' => __('Disabled', 'syslog')], 'value' => '|arg1:enabled|'], + 'mute_mode' => ['method' => 'drop_array', 'friendly_name' => __('Alert Handling', 'syslog'), 'description' => __('Pause all non-exempt alerts until a date, or indefinitely.', 'syslog'), 'array' => ['none' => __('Do not pause', 'syslog'), 'until' => __('Pause until', 'syslog'), 'indefinite' => __('Pause indefinitely', 'syslog')], 'value' => '|arg1:mute_mode|'], + 'mute_until' => ['method' => 'textbox', 'friendly_name' => __('Pause Ends', 'syslog'), 'description' => __('Local date and time, YYYY-MM-DD HH:MM.', 'syslog'), 'value' => '|arg1:mute_until|', 'size' => 18, 'max_length' => 16], + 'pass_through_priority' => ['method' => 'drop_array', 'friendly_name' => __('Always Allow Priority', 'syslog'), 'description' => __('These priorities pass through this device pause and maintenance windows. Critical and more urgent is a typical platinum-device choice.', 'syslog'), 'array' => $priorities, 'value' => '|arg1:pass_through_priority|'], + 'allow_maintenance' => ['method' => 'drop_array', 'friendly_name' => __('Allow During Maintenance', 'syslog'), 'description' => __('Allow all priorities from this device during an alert maintenance window. The priority exception above still applies when this is No.', 'syslog'), 'array' => ['' => __('No', 'syslog'), 'on' => __('Yes', 'syslog')], 'value' => '|arg1:allow_maintenance|'], + 'notes' => ['method' => 'textarea', 'friendly_name' => __('Notes', 'syslog'), 'value' => '|arg1:notes|', 'textarea_rows' => 4, 'textarea_cols' => 70], + 'id' => ['method' => 'hidden_zero', 'value' => '|arg1:id|'], '_id' => ['method' => 'hidden_zero', 'value' => '|arg1:id|'], 'save_component_device_rule' => ['method' => 'hidden', 'value' => '1'] + ]; + if (!empty($rule['mute_until'])) { + $rule['mute_until'] = date('Y-m-d H:i', (int) $rule['mute_until']); + } + form_start('syslog_device_rules.php', 'syslog_device_rule_edit'); + html_start_box($id ? __('Device Alert Rule [edit]', 'syslog') : __('Device Alert Rule [new]', 'syslog'), '100%', '', '3', 'center', ''); + draw_edit_form(['config' => ['no_form_tag' => true], 'fields' => inject_form_variables($fields, $rule)]); + html_end_box(); + form_save_button('syslog_device_rules.php', '', 'id'); + ?> + + ['filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1'], + 'page' => ['filter' => FILTER_VALIDATE_INT, 'default' => '1'], + 'enabled' => ['filter' => FILTER_VALIDATE_INT, 'pageset' => true, 'default' => '-1'], + 'filter' => ['filter' => FILTER_DEFAULT, 'pageset' => true, 'default' => ''] + ]; + validate_store_request_vars($filters, 'sess_syslog_device_rules'); + $url = syslog_allow_edits() ? 'syslog_device_rules.php?action=edit' : ''; + html_start_box(__('Device Alert Rule Filters', 'syslog'), '100%', '', '3', 'center', $url); + ?> +
    + + + + +
    ' value=''>'>'>
    '>
    + + 'on'"); + } + $rows = get_request_var('rows') == '-1' ? (int) read_config_option('num_rows_table') : (int) get_request_var('rows'); + $rows = max(1, $rows); + $total_rows = (int) syslog_db_fetch_cell_prepared("SELECT COUNT(*) FROM `$syslogdb_default`.`syslog_device_rule` $sql_where", $sql_params); + $page = max(1, (int) get_request_var('page')); + $offset = ($page - 1) * $rows; + $rules = syslog_db_fetch_assoc_prepared("SELECT * FROM `$syslogdb_default`.`syslog_device_rule` $sql_where ORDER BY host LIMIT $offset, $rows", $sql_params); + $nav = html_nav_bar('syslog_device_rules.php?filter=' . urlencode(get_request_var('filter')) . '&enabled=' . get_request_var('enabled') . '&rows=' . $rows, MAX_DISPLAY_PAGES, $page, $rows, $total_rows, 4, __('Rules', 'syslog'), 'page', 'main'); + form_start('syslog_device_rules.php', 'chk'); + print $nav; + html_start_box(__('Device Alert Rules', 'syslog'), '100%', '', '3', 'center', ''); + $display_text = ['host' => [__('Device', 'syslog'), 'ASC'], 'handling' => [__('Handling', 'syslog'), 'ASC'], 'pass' => [__('Pass Through', 'syslog'), 'ASC'], 'maintenance' => [__('Maintenance', 'syslog'), 'ASC']]; + html_header_sort_checkbox($display_text, 'host', 'ASC'); + if (!cacti_sizeof($rules)) { + print '' . __('No device alert rules found.', 'syslog') . ''; + } + foreach ($rules as $rule) { + $handling = $rule['mute_mode'] === 'until' ? __esc('Paused until %s', date('Y-m-d H:i', (int) $rule['mute_until']), 'syslog') : ($rule['mute_mode'] === 'indefinite' ? __('Paused indefinitely', 'syslog') : __('Not paused', 'syslog')); + $pass = (int) $rule['pass_through_priority'] >= 0 ? ucfirst($syslog_levels[$rule['pass_through_priority']]) . ' ' . __('and more urgent', 'syslog') : __('None', 'syslog'); + form_alternate_row('line' . $rule['id'], true); + form_selectable_cell(filter_value(html_escape($rule['host']) . ($rule['enabled'] === 'on' ? '' : ' (' . __('Disabled', 'syslog') . ')'), get_request_var('filter'), $config['url_path'] . 'plugins/syslog/syslog_device_rules.php?action=edit&id=' . $rule['id']), $rule['id']); + form_selectable_cell($handling, $rule['id']); + form_selectable_cell($pass, $rule['id']); + form_selectable_cell($rule['allow_maintenance'] === 'on' ? __('Allow all', 'syslog') : __('Use priority exception', 'syslog'), $rule['id']); + form_checkbox_cell($rule['host'], $rule['id']); + form_end_row(); + } + html_end_box(false); + if (cacti_sizeof($rules)) { + print $nav; + } + draw_actions_dropdown($syslog_actions); + form_end(false); + if (isset($_SESSION['syslog_device_rule_exporter'])) { + syslog_download_frame('syslog_device_rules.php?action=export&selected_items=' . $_SESSION['syslog_device_rule_exporter']); + kill_session_var('syslog_device_rule_exporter'); + exit; + } +} diff --git a/tests/Unit/DeviceRulePolicyTest.php b/tests/Unit/DeviceRulePolicyTest.php new file mode 100644 index 0000000..262b051 --- /dev/null +++ b/tests/Unit/DeviceRulePolicyTest.php @@ -0,0 +1,43 @@ + 'host', 'priorityField' => 'priority_id']; + + $active = syslog_device_rule_sql(true); + // Maintenance must not let a host with no device rule through: an EXISTS + // filter is required while maintenance is active. + expect($active['sql'])->toContain('AND EXISTS') + ->toContain("dr.allow_maintenance = 'on'") + ->toContain('pass_through_priority') + // An active device pause still applies during maintenance. + ->toContain('AND NOT EXISTS'); + expect($active['params'])->toHaveCount(1); + + $inactive = syslog_device_rule_sql(false); + expect($inactive['sql'])->not->toContain('AND EXISTS') + ->toContain('AND NOT EXISTS'); +}); diff --git a/tests/Unit/MessageRuleLinksTest.php b/tests/Unit/MessageRuleLinksTest.php index dd8c2f2..88f3823 100644 --- a/tests/Unit/MessageRuleLinksTest.php +++ b/tests/Unit/MessageRuleLinksTest.php @@ -39,6 +39,11 @@ expect($query['id'] === '43' && $query['action'] === 'newedit' && $query['date'] === '2026-09-13 00:12:42')->toBeTrue('Editor targets the selected record'); } + $allowed[] = 'syslog_device_rules.php'; + $links = syslog_message_rule_links(43, 'main', '2026-09-13 00:12:42', 'platinum-router'); + parse_str(parse_url($links['device'], PHP_URL_QUERY), $query); + expect(strpos($links['device'], 'syslog_device_rules.php?') === 0 && $query['host'] === 'platinum-router')->toBeTrue('Permitted users can seed a device-wide rule from the selected message host'); + foreach (['removed', 'alerts', ''] as $source) { expect(syslog_message_rule_links(42, $source, ''))->toBe([], 'Unsupported source must not resolve an unrelated main record'); }