Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 33 additions & 10 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ When generating code for this repository:

### Key Dependencies
- Cacti core framework (`api_plugin_*`, `db_*`, `read_config_option()`, `get_filter_request_var()`, etc.).
- This plugin's own `syslog_db_*` wrapper layer (`database.php`) instead of core `db_*` for syslog tables.
- This plugin's own `syslog_db_*` wrapper layer (`includes/database.php`) instead of core `db_*` for syslog tables.
- Optional: `gettext` for internationalization.

## Project Context
Expand All @@ -29,9 +29,10 @@ This is the **Syslog Plugin** for Cacti, a PHP-based network monitoring and grap
## Project Structure
```
plugin_syslog/
├── setup.php # Install/uninstall/upgrade hooks, schema, realms, menu entries
├── database.php # syslog_db_* wrapper layer (dual-database support)
├── functions.php # Core logic: search DSL, CSV export, partitions, alerts
├── setup.php # Compatibility facade, lifecycle and upgrade orchestration
├── includes/ # Owned setup modules: schema, processing, settings, UI hooks
├── includes/database.php # syslog_db_* wrapper layer (dual-database support)
├── includes/functions.php # Core logic: search DSL, CSV export, partitions, alerts
├── syslog.php # Main UI entry point (System Logs / Alert Logs tabs)
├── syslog_alerts.php # Alert rule administration
├── syslog_removal.php # Removal rule administration
Expand All @@ -49,8 +50,9 @@ plugin_syslog/

## Architecture & Data Flow
- **Dual Database Support:** The plugin can store data in the main Cacti database OR a dedicated syslog database.
- **Critical:** ALWAYS use the `syslog_db_*` wrapper functions (defined in `database.php`) for all database operations. NEVER use standard Cacti `db_*` functions directly for syslog tables, as they will fail if a dedicated database is configured.
- **Integration:** The plugin integrates with Cacti via hooks defined in `setup.php`.
- **Critical:** ALWAYS use the `syslog_db_*` wrapper functions (defined in `includes/database.php`) for all database operations. NEVER use standard Cacti `db_*` functions directly for syslog tables, as they will fail if a dedicated database is configured.
- **Integration:** `setup.php` is the compatibility bootstrap; Cacti hooks are
registered there but point at the module that owns each callback.
- **Poller Integration:** Background processes (`syslog_process.php`, `syslog_removal.php`) are triggered by Cacti's poller or run independently.
- **Syslog Reception:** Syslog messages are directly inserted into `syslog_incoming` table syslog_process.php then processes them.

Expand All @@ -63,8 +65,9 @@ plugin_syslog/
- **Schema:** Tables are defined/updated in `setup.php` (`syslog_setup_table_new`).

### Cacti Integration Patterns
- **Hooks:** Register hooks in `plugin_syslog_install()` in `setup.php`.
- Example: `api_plugin_register_hook('syslog', 'top_header_tabs', 'syslog_show_tab', 'setup.php');`
- **Hooks:** Register hooks in `plugin_syslog_install()` in `setup.php`, but
point each registration to the owning module (for example,
`includes/navigation.php` for `syslog_show_tab`).
- **Permissions:** Register realms in `setup.php`.
- Example: `api_plugin_register_realm('syslog', 'syslog.php', 'Syslog User', 1);`
- **UI:** Follow Cacti's UI patterns (top tabs, breadcrumbs, filter bars).
Expand Down Expand Up @@ -172,6 +175,26 @@ integer/numeric context (e.g. arithmetic, strict `===` comparisons).
- **Type Safety:** Add type hints to function arguments and return types where possible, ensuring backward compatibility with supported PHP versions.
- **Cleanup:** Remove unused variables and commented-out code blocks found in the modified sections.

## `setup.php` Module Boundaries

- Keep `setup.php` as the compatibility facade: lifecycle entry points,
`plugin_syslog_version()`, `syslog_check_upgrade()` and its realm/permission
orchestration, `syslog_connect()`, and config-file discovery only.
- Load modules lazily with `require_once` at the lifecycle or callback boundary
that needs them. Do not eagerly load every `includes/*.php` module from
`setup.php`; Cacti hook registration already identifies and loads the owning
callback module.
- Put schema creation and migrations in `includes/schema.php`; retain
`includes/database.php` as the `syslog_db_*` wrapper layer.
- Put poller and replication callbacks in `includes/processing.php`; settings
hooks in `includes/settings.php`; tabs/navigation/graph buttons in
`includes/navigation.php`; install adviser UI in `includes/installer.php`;
and utilities callbacks in `includes/utilities.php`.
- Preserve public function names, signatures, SQL, and include order during a
move. Never combine a function move with a hook-path change or logic change.
- Source-inspection tests must use the central function-owner map in
`tests/bootstrap-unit.php`; update that map in the same commit as a move.

## DBA & Query Optimization
- **Query Analysis:** Always review SQL queries for performance. Suggest indexes if filtering by non-indexed columns.
- **Prepared Statements:** Prefer `syslog_db_execute_prepared` over string concatenation for security and performance.
Expand Down Expand Up @@ -231,9 +254,9 @@ Document all changes in `CHANGELOG.md` under `--- develop ---`, prefixed by type

## Key Files
- `setup.php`: Plugin installation, hook registration, and schema updates.
- `database.php`: Database abstraction layer wrappers (`syslog_db_*`).
- `includes/database.php`: Database abstraction layer wrappers (`syslog_db_*`).
- `config.php.dist`: Template for database configuration.
- `functions.php`: Core logic and utility functions.
- `includes/functions.php`: Core logic and utility functions.
- `syslog.php`: Main UI entry point.

## CI & Dependency Baselines
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

--- develop ---

* feature: Add Remote Data Collector processing, rules-sync, and record-storage options to the setup advisor; reject Aria selections whenever any collector option is enabled
* change: Use TEXT for message columns previously limited to VARCHAR(2048), including existing installations
* ci: Drop Ruby from the CodeQL language matrix; the plugin ships no Ruby source, so the Ruby database build failed with "no source code seen"
* dev: Move the shared function and database libraries to includes/ and point the entry-point includes, coverage source, and tests at the new path
* feature: Restyle the System Logs and Alert Logs severity legends as rounded, evenly spaced, solid-colour chips that line up with the Thold status legends, with theme-appropriate backgrounds loaded from a per-theme css/<theme>.css file (falling back to a theme-neutral css/legend.css)
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ tables, but the plugin does not migrate the table automatically.

Only the InnoDB storage engine and, on MariaDB, the Aria storage engine are
supported. Other engines, including MyISAM, are no longer offered and fall
back to InnoDB when legacy settings request them.
back to InnoDB when legacy settings request them. Enabling any Remote Data
Collector option requires InnoDB; the setup advisor selects it automatically.

## Important Version 4.0 Release Notes

Expand Down
56 changes: 56 additions & 0 deletions docs/setup-modules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# `setup.php` module ownership

`setup.php` is the Syslog plugin's compatibility entry point. Page and worker
entry points may continue to include it directly; lifecycle code loads only
the module it needs, while Cacti loads hook callback modules by their registered
path.

This is a relocation refactor. A module move must not rename a function,
change SQL, or change hook ownership in the same commit.

## Stable facade

`setup.php` owns the plugin lifecycle and upgrade orchestration:

- `plugin_syslog_install()` and `plugin_syslog_uninstall()`
- `plugin_syslog_check_config()` and `plugin_syslog_upgrade()`
- `plugin_syslog_version()` and `syslog_check_upgrade()`
- `syslog_connect()` as the compatibility facade for direct `setup.php`
consumers
- `syslog_determine_config()` and `syslog_config_safe()`
- realm/permission upgrade helpers called by `syslog_check_upgrade()`

## Module map

| Module | Owns |
| --- | --- |
| `includes/schema.php` | Schema creation, migration helpers, capacity checks, and table setup |
| `includes/processing.php` | Poller and replication callbacks |
| `includes/settings.php` | Settings definitions, permission configuration, and Settings-page assets |
| `includes/navigation.php` | Tabs, navigation text, refresh handling, and graph buttons |
| `includes/installer.php` | Install/uninstall advisor and confirmation rendering |
| `includes/utilities.php` | Utilities menu/action callbacks and the purge dialog |

`includes/database.php` remains the dual-database `syslog_db_*` wrapper layer;
it is not replaced by `includes/schema.php`.

## Hook ownership

After extraction, registrations must reference the owning module:

| Hook callback group | Owning file |
| --- | --- |
| `syslog_config_settings`, `syslog_settings_bottom`, `syslog_config_arrays`, `syslog_config_insert` | `includes/settings.php` |
| `syslog_show_tab`, `syslog_draw_navigation_text`, `syslog_graph_buttons` | `includes/navigation.php` |
| `syslog_poller_bottom`, `syslog_replicate_out` | `includes/processing.php` |
| `syslog_utilities_list`, `syslog_utilities_action` | `includes/utilities.php` |

Each hook-path change follows the move in a separate commit. The installer
entry points remain registered through `setup.php`.

## Test rule

Source-inspection tests must obtain a function's source through
`plugin_test_read_function_source()` instead of hard-coding `setup.php`.
Whenever ownership changes, update that central map and the test in the same
commit.
70 changes: 52 additions & 18 deletions includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,58 @@ function syslog_validate_storage_engine($engine) {
return 'InnoDB';
}

/**
* Whether any Remote Data Collector option requires InnoDB storage.
*
* @param array<string, mixed> $options The install options, when supplied.
*
* @return bool
*/
function syslog_remote_collector_requires_innodb(array $options = []): bool {
foreach (['syslog_remote_enabled', 'syslog_remote_sync_rules', 'syslog_remote_store_records'] as $option) {
$value = array_key_exists($option, $options) ? $options[$option] : read_config_option($option);

if ($value === 'on') {
return true;
}
}

return false;
}

/**
* Resolve the install storage engine, enforcing InnoDB for collector options.
*
* @param mixed $engine The requested storage engine name.
* @param array<string, mixed> $options The install options, when supplied.
*
* @return string
*/
function syslog_install_storage_engine($engine, array $options = []): string {
$engine = syslog_validate_storage_engine($engine);

if (syslog_remote_collector_requires_innodb($options) && $engine !== 'InnoDB') {
cacti_log('SYSLOG WARNING: Remote Data Collector options require InnoDB storage. Falling back to InnoDB', false, 'SYSLOG');

return 'InnoDB';
Comment thread
bmfmancini marked this conversation as resolved.
}

return $engine;
}

/**
* Whether the requested storage engine is compatible with install options.
*
* @param mixed $engine The requested storage engine name.
* @param array<string, mixed> $options The install options.
*
* @return bool
*/
function syslog_install_storage_engine_is_compatible($engine, array $options = []): bool {
return !syslog_remote_collector_requires_innodb($options)
|| syslog_validate_storage_engine($engine) === 'InnoDB';
}

/**
* syslog_notice_traditional_tables - Raise the deprecation notice for
* traditional (non-partitioned) Syslog tables.
Expand Down Expand Up @@ -2704,24 +2756,6 @@ function syslog_partition_check($table, $time = null) {
}
}

/**
* Report whether a request variable differs from its remembered session value.
*
* @param string $request The request variable name to check.
* @param string $session The session variable name to compare against.
*
* @return int|null 1 when the value changed, or null when unchanged or unset.
*/
function syslog_check_changed(string $request, string $session): ?int {
if ((isset_request_var($request)) && (isset($_SESSION[$session]))) {
if (get_request_var($request) != $_SESSION[$session]) {
return 1;
}
}

return null;
}

/**
* syslog_get_removal_rule_fields - Trusted field map used to compile
* structured filter rules for removal processing and editor validation.
Expand Down
Loading
Loading