You've already forked wp-prometheus
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e5f2edbafa | |||
| 7f0b6ec8a6 | |||
| 192da4588a | |||
| cf1797d4bf | |||
| 19d75ab7b2 | |||
| fa63857f5f |
59
CHANGELOG.md
59
CHANGELOG.md
@@ -5,6 +5,65 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.4.5] - 2026-02-02
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Settings now persist correctly across Metrics sub-tabs
|
||||||
|
- Auth token no longer gets cleared when saving from Selection sub-tab
|
||||||
|
- Enabled metrics no longer get cleared when saving from Endpoint sub-tab
|
||||||
|
- Isolated mode setting no longer gets cleared when saving from other sub-tabs
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Split Metrics settings into separate WordPress option groups per sub-tab
|
||||||
|
- Each sub-tab now uses its own settings group to prevent cross-tab overwrites
|
||||||
|
|
||||||
|
## [0.4.4] - 2026-02-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Safe mode for metrics collection (default):
|
||||||
|
- Removes problematic content filters early
|
||||||
|
- Allows third-party plugins to register `wp_prometheus_collect_metrics` hooks
|
||||||
|
- Wraps custom hooks in output buffering and try-catch for protection
|
||||||
|
- Isolated mode option for maximum compatibility:
|
||||||
|
- Outputs metrics before other plugins fully load
|
||||||
|
- Use only if Safe mode causes issues
|
||||||
|
- `WP_PROMETHEUS_ISOLATED_MODE` environment variable support
|
||||||
|
- Mode comparison table in admin settings
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Replaced "early mode" with two clear modes: Safe (default) and Isolated
|
||||||
|
- Custom metrics hooks now fire by default with protection against recursion
|
||||||
|
- Filter removal now also includes `the_content_feed` and `comment_text`
|
||||||
|
- Updated admin UI with clearer explanations of each mode
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Third-party plugins can now add custom metrics without memory issues
|
||||||
|
- Twig-based plugins (like wp-fedistream) no longer cause recursion
|
||||||
|
|
||||||
|
## [0.4.3] - 2026-02-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Sub-tabs navigation within Metrics tab (Endpoint, Selection, Runtime, Advanced)
|
||||||
|
- Option to disable early mode in admin settings (Metrics → Advanced)
|
||||||
|
- Support for `WP_PROMETHEUS_DISABLE_EARLY_MODE` environment variable
|
||||||
|
- Early mode status display in settings
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Early mode setting now saves correctly (moved into form with proper settings group)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Reorganized Metrics tab into logical sub-sections for better usability
|
||||||
|
- Early mode can now be disabled for users who need the `wp_prometheus_collect_metrics` hook
|
||||||
|
- Updated translations with sub-tab and early mode strings (English and German)
|
||||||
|
|
||||||
## [0.4.1] - 2026-02-02
|
## [0.4.1] - 2026-02-02
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
106
CLAUDE.md
106
CLAUDE.md
@@ -291,6 +291,112 @@ add_action( 'wp_prometheus_collect_metrics', function( $collector ) {
|
|||||||
|
|
||||||
## Session History
|
## Session History
|
||||||
|
|
||||||
|
### 2026-02-02 - Settings Persistence Fix (v0.4.5)
|
||||||
|
|
||||||
|
- Fixed critical bug where settings would get cleared when saving from different Metrics sub-tabs
|
||||||
|
- Root cause: All settings were registered under single `wp_prometheus_metrics_settings` group
|
||||||
|
- When saving from "Endpoint" sub-tab, only auth token was in POST data
|
||||||
|
- WordPress Settings API would process all registered settings in the group
|
||||||
|
- Missing fields (enabled_metrics, isolated_mode) would receive null/undefined
|
||||||
|
- Sanitize callbacks returned empty values, overwriting existing settings
|
||||||
|
- Solution: Split into separate settings groups per sub-tab:
|
||||||
|
- `wp_prometheus_endpoint_settings` for auth token
|
||||||
|
- `wp_prometheus_selection_settings` for enabled metrics
|
||||||
|
- `wp_prometheus_advanced_settings` for isolated mode
|
||||||
|
- **Key Learning**: WordPress Settings API and multiple forms
|
||||||
|
- When multiple forms share the same settings group, saving one form can clear settings from another
|
||||||
|
- Each form with `settings_fields()` should use a unique option group
|
||||||
|
- `register_setting()` group name must match `settings_fields()` group name
|
||||||
|
|
||||||
|
### 2026-02-02 - Safe Mode & Custom Hooks Fix (v0.4.4)
|
||||||
|
|
||||||
|
- Redesigned metrics collection to support both plugin compatibility AND custom metrics:
|
||||||
|
- **Safe Mode (default)**: Removes content filters early but lets WordPress load normally
|
||||||
|
- **Isolated Mode**: Legacy early mode that skips custom hooks entirely
|
||||||
|
- Implementation:
|
||||||
|
- `WP_PROMETHEUS_METRICS_REQUEST` constant set for any /metrics request
|
||||||
|
- Content filters removed via `plugins_loaded` hook at priority 0
|
||||||
|
- Collector fires `wp_prometheus_collect_metrics` with protection (output buffering, try-catch)
|
||||||
|
- `wp_prometheus_isolated_mode` option replaces `wp_prometheus_disable_early_mode`
|
||||||
|
- `WP_PROMETHEUS_ISOLATED_MODE` environment variable for containerized deployments
|
||||||
|
- Collector now wraps custom hooks in `fire_custom_metrics_hook()` method:
|
||||||
|
- Removes content filters again before hook (in case re-added)
|
||||||
|
- Uses output buffering to discard accidental output
|
||||||
|
- Catches exceptions to prevent breaking metrics output
|
||||||
|
- Logs errors when WP_DEBUG is enabled
|
||||||
|
- Updated admin UI with mode comparison table
|
||||||
|
- **Key Learning**: Hybrid approach for plugin compatibility
|
||||||
|
- The memory issue comes from content filter recursion, not just plugin loading
|
||||||
|
- Removing filters early (before any plugin can trigger them) prevents recursion
|
||||||
|
- Plugins still load and can register their `wp_prometheus_collect_metrics` hooks
|
||||||
|
- Hooks fire after filters are removed, in a protected context
|
||||||
|
- **Key Learning**: Defense in depth for custom hooks
|
||||||
|
- Remove filters again right before hook fires (plugins may re-add them)
|
||||||
|
- Output buffering catches any echo/print from misbehaving plugins
|
||||||
|
- Try-catch prevents one broken plugin from breaking metrics entirely
|
||||||
|
|
||||||
|
### 2026-02-02 - Sub-tabs & Early Mode Fix (v0.4.3)
|
||||||
|
|
||||||
|
- Split Metrics tab into sub-tabs for better organization:
|
||||||
|
- **Endpoint**: Authentication token configuration
|
||||||
|
- **Selection**: Enable/disable individual metrics
|
||||||
|
- **Runtime**: Reset runtime metrics data
|
||||||
|
- **Advanced**: Early mode toggle and status
|
||||||
|
- Fixed early mode setting not being saved (was outside form element)
|
||||||
|
- Added CSS styling for horizontal sub-tab navigation
|
||||||
|
- **Key Learning**: WordPress Settings API form structure
|
||||||
|
- Settings must be inside `<form action="options.php">` with `settings_fields()` call
|
||||||
|
- Each sub-tab needs its own form wrapper for proper saving
|
||||||
|
- Sub-tabs use URL query parameter (`subtab`) within the main tab
|
||||||
|
- **Key Learning**: WordPress plugin versioning requires TWO updates
|
||||||
|
- Plugin header comment `Version: x.x.x` (line ~6) - used by WordPress admin
|
||||||
|
- PHP constant `WP_PROMETHEUS_VERSION` (line ~133) - used internally
|
||||||
|
- CI/CD checks both must match the git tag, causing release failures if mismatched
|
||||||
|
|
||||||
|
### 2026-02-02 - Early Mode Toggle (v0.4.2)
|
||||||
|
|
||||||
|
- Added option to disable early mode for users who need extensibility
|
||||||
|
- Implementation:
|
||||||
|
- Added `wp_prometheus_disable_early_mode` WordPress option
|
||||||
|
- Added `WP_PROMETHEUS_DISABLE_EARLY_MODE` environment variable support
|
||||||
|
- Option check in `wp_prometheus_early_metrics_check()` before early interception
|
||||||
|
- Environment variable accepts `1`, `true`, `yes`, `on` (case-insensitive)
|
||||||
|
- Admin UI in Metrics tab:
|
||||||
|
- "Early Mode" section with description of functionality
|
||||||
|
- Checkbox to disable early metrics interception
|
||||||
|
- Environment override notice when env var is set
|
||||||
|
- Current status indicator showing early mode state
|
||||||
|
- **Key Learning**: Balancing compatibility vs extensibility
|
||||||
|
- Early mode fixes memory issues but disables `wp_prometheus_collect_metrics` hook
|
||||||
|
- Users with custom metrics need the hook, so early mode must be optional
|
||||||
|
- Default remains enabled (safe) with explicit opt-out for advanced users
|
||||||
|
|
||||||
|
### 2026-02-02 - Plugin Compatibility Fix (v0.4.1)
|
||||||
|
|
||||||
|
- Fixed memory exhaustion (1GB limit) when wp-fedistream (Twig-based) plugin is active
|
||||||
|
- Root cause: Infinite recursion through WordPress hook system when content filters trigger Twig rendering
|
||||||
|
- Solution: Early metrics endpoint interception before full WordPress initialization
|
||||||
|
- Implementation changes:
|
||||||
|
- Added `wp_prometheus_early_metrics_check()` in bootstrap file (wp-prometheus.php)
|
||||||
|
- Checks REQUEST_URI for `/metrics` pattern before `plugins_loaded` fires
|
||||||
|
- Defines `WP_PROMETHEUS_EARLY_METRICS` constant to signal early mode
|
||||||
|
- Removes content filters (`the_content`, `the_excerpt`, `get_the_excerpt`, `the_title`)
|
||||||
|
- Collector skips `wp_prometheus_collect_metrics` action in early mode
|
||||||
|
- Changed MetricsEndpoint from `template_redirect` to `parse_request` hook
|
||||||
|
- **Key Learning**: WordPress plugin loading order and hook timing
|
||||||
|
- Plugins load alphabetically, so wp-fedistream ('f') loads before wp-prometheus ('p')
|
||||||
|
- `template_redirect` fires too late - after themes and Twig initialize
|
||||||
|
- `parse_request` fires earlier but still after plugin files load
|
||||||
|
- Earliest interception point: top-level code in plugin bootstrap file
|
||||||
|
- **Key Learning**: Content filter recursion in WordPress
|
||||||
|
- `get_the_excerpt()` internally triggers `apply_filters('the_content', ...)`
|
||||||
|
- This creates unexpected recursion vectors when Twig templates process content
|
||||||
|
- Solution: Remove all content-related filters before metrics collection
|
||||||
|
- **Key Learning**: Isolating metrics collection from WordPress template system
|
||||||
|
- Use `remove_all_filters()` to clear problematic filter chains
|
||||||
|
- Skip extensibility hooks (`do_action`) when in isolated early mode
|
||||||
|
- Exit immediately after output to prevent further WordPress processing
|
||||||
|
|
||||||
### 2026-02-02 - Persistent Storage (v0.4.0)
|
### 2026-02-02 - Persistent Storage (v0.4.0)
|
||||||
|
|
||||||
- Added persistent storage support for metrics:
|
- Added persistent storage support for metrics:
|
||||||
|
|||||||
@@ -9,6 +9,61 @@
|
|||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sub-tabs navigation */
|
||||||
|
.wp-prometheus-subtabs {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-subtab-nav {
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
border-bottom: 1px solid #c3c4c7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-subtab-item {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-subtab-item a {
|
||||||
|
display: block;
|
||||||
|
padding: 8px 16px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #50575e;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-bottom: none;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
background: transparent;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-subtab-item a:hover {
|
||||||
|
color: #2271b1;
|
||||||
|
background: #f6f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-subtab-item.active a {
|
||||||
|
color: #1d2327;
|
||||||
|
background: #fff;
|
||||||
|
border-color: #c3c4c7;
|
||||||
|
border-bottom-color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-subtab-content {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #c3c4c7;
|
||||||
|
border-top: none;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-subtab-content h3:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* License status box */
|
/* License status box */
|
||||||
.wp-prometheus-license-status {
|
.wp-prometheus-license-status {
|
||||||
margin: 15px 0;
|
margin: 15px 0;
|
||||||
|
|||||||
Binary file not shown.
@@ -3,7 +3,7 @@
|
|||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WP Prometheus 0.4.0\n"
|
"Project-Id-Version: WP Prometheus 0.4.2\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/magdev/wp-prometheus/issues\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/magdev/wp-prometheus/issues\n"
|
||||||
"POT-Creation-Date: 2026-02-02T00:00:00+00:00\n"
|
"POT-Creation-Date: 2026-02-02T00:00:00+00:00\n"
|
||||||
"PO-Revision-Date: 2026-02-02T00:00:00+00:00\n"
|
"PO-Revision-Date: 2026-02-02T00:00:00+00:00\n"
|
||||||
@@ -879,3 +879,71 @@ msgstr "APCu funktioniert. Speicher: %s belegt."
|
|||||||
#: src/Metrics/StorageFactory.php
|
#: src/Metrics/StorageFactory.php
|
||||||
msgid "APCu fetch operation returned unexpected value."
|
msgid "APCu fetch operation returned unexpected value."
|
||||||
msgstr "APCu-Abrufoperation hat unerwarteten Wert zurueckgegeben."
|
msgstr "APCu-Abrufoperation hat unerwarteten Wert zurueckgegeben."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early Mode"
|
||||||
|
msgstr "Fruehzeitiger Modus"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode intercepts /metrics requests before full WordPress initialization. This prevents memory exhaustion issues caused by some plugins (e.g., Twig-based themes/plugins) but disables the wp_prometheus_collect_metrics hook for custom metrics."
|
||||||
|
msgstr "Der fruehzeitige Modus faengt /metrics-Anfragen vor der vollstaendigen WordPress-Initialisierung ab. Dies verhindert Speichererschoepfungsprobleme, die durch einige Plugins verursacht werden (z.B. Twig-basierte Themes/Plugins), deaktiviert jedoch den wp_prometheus_collect_metrics-Hook fuer benutzerdefinierte Metriken."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is configured via WP_PROMETHEUS_DISABLE_EARLY_MODE environment variable. Admin settings will be ignored."
|
||||||
|
msgstr "Der fruehzeitige Modus ist ueber die Umgebungsvariable WP_PROMETHEUS_DISABLE_EARLY_MODE konfiguriert. Admin-Einstellungen werden ignoriert."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Disable Early Mode"
|
||||||
|
msgstr "Fruehzeitigen Modus deaktivieren"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Disable early metrics interception"
|
||||||
|
msgstr "Fruehzeitige Metriken-Abfangung deaktivieren"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "When disabled, metrics are collected through normal WordPress template loading. This enables the wp_prometheus_collect_metrics hook for custom metrics but may cause issues with some plugins."
|
||||||
|
msgstr "Wenn deaktiviert, werden Metriken ueber das normale WordPress-Template-Laden erfasst. Dies aktiviert den wp_prometheus_collect_metrics-Hook fuer benutzerdefinierte Metriken, kann jedoch Probleme mit einigen Plugins verursachen."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is active (this request was served via early interception)"
|
||||||
|
msgstr "Fruehzeitiger Modus ist aktiv (diese Anfrage wurde ueber fruehzeitige Abfangung verarbeitet)"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is disabled"
|
||||||
|
msgstr "Fruehzeitiger Modus ist deaktiviert"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is enabled (active for /metrics requests)"
|
||||||
|
msgstr "Fruehzeitiger Modus ist aktiviert (aktiv fuer /metrics-Anfragen)"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Clear all accumulated runtime metric data (HTTP requests, database queries). This is useful for testing or starting fresh."
|
||||||
|
msgstr "Alle gesammelten Laufzeit-Metrikdaten loeschen (HTTP-Anfragen, Datenbank-Abfragen). Dies ist nuetzlich zum Testen oder fuer einen Neuanfang."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Endpoint"
|
||||||
|
msgstr "Endpunkt"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Selection"
|
||||||
|
msgstr "Auswahl"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Runtime"
|
||||||
|
msgstr "Laufzeit"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Advanced"
|
||||||
|
msgstr "Erweitert"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Runtime Metrics Management"
|
||||||
|
msgstr "Laufzeit-Metriken Verwaltung"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Runtime metrics track HTTP requests and database queries across requests. Use this section to manage accumulated data."
|
||||||
|
msgstr "Laufzeit-Metriken erfassen HTTP-Anfragen und Datenbank-Abfragen ueber mehrere Anfragen hinweg. Verwenden Sie diesen Bereich zur Verwaltung der gesammelten Daten."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Reset Data"
|
||||||
|
msgstr "Daten zuruecksetzen"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# This file is distributed under the GPL v2 or later.
|
# This file is distributed under the GPL v2 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: WP Prometheus 0.4.0\n"
|
"Project-Id-Version: WP Prometheus 0.4.2\n"
|
||||||
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/magdev/wp-prometheus/issues\n"
|
"Report-Msgid-Bugs-To: https://src.bundespruefstelle.ch/magdev/wp-prometheus/issues\n"
|
||||||
"POT-Creation-Date: 2026-02-02T00:00:00+00:00\n"
|
"POT-Creation-Date: 2026-02-02T00:00:00+00:00\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -876,3 +876,71 @@ msgstr ""
|
|||||||
#: src/Metrics/StorageFactory.php
|
#: src/Metrics/StorageFactory.php
|
||||||
msgid "APCu fetch operation returned unexpected value."
|
msgid "APCu fetch operation returned unexpected value."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode intercepts /metrics requests before full WordPress initialization. This prevents memory exhaustion issues caused by some plugins (e.g., Twig-based themes/plugins) but disables the wp_prometheus_collect_metrics hook for custom metrics."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is configured via WP_PROMETHEUS_DISABLE_EARLY_MODE environment variable. Admin settings will be ignored."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Disable Early Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Disable early metrics interception"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "When disabled, metrics are collected through normal WordPress template loading. This enables the wp_prometheus_collect_metrics hook for custom metrics but may cause issues with some plugins."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is active (this request was served via early interception)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is disabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Early mode is enabled (active for /metrics requests)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Clear all accumulated runtime metric data (HTTP requests, database queries). This is useful for testing or starting fresh."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Endpoint"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Selection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Runtime"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Advanced"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Runtime Metrics Management"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Runtime metrics track HTTP requests and database queries across requests. Use this section to manage accumulated data."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Reset Data"
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@@ -107,17 +107,25 @@ class Settings {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_settings(): void {
|
public function register_settings(): void {
|
||||||
// Register settings for metrics tab.
|
// Register settings for endpoint sub-tab.
|
||||||
register_setting( 'wp_prometheus_metrics_settings', 'wp_prometheus_auth_token', array(
|
register_setting( 'wp_prometheus_endpoint_settings', 'wp_prometheus_auth_token', array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'sanitize_callback' => 'sanitize_text_field',
|
'sanitize_callback' => 'sanitize_text_field',
|
||||||
) );
|
) );
|
||||||
|
|
||||||
register_setting( 'wp_prometheus_metrics_settings', 'wp_prometheus_enabled_metrics', array(
|
// Register settings for selection sub-tab.
|
||||||
|
register_setting( 'wp_prometheus_selection_settings', 'wp_prometheus_enabled_metrics', array(
|
||||||
'type' => 'array',
|
'type' => 'array',
|
||||||
'sanitize_callback' => array( $this, 'sanitize_metrics' ),
|
'sanitize_callback' => array( $this, 'sanitize_metrics' ),
|
||||||
) );
|
) );
|
||||||
|
|
||||||
|
// Register settings for advanced sub-tab.
|
||||||
|
register_setting( 'wp_prometheus_advanced_settings', 'wp_prometheus_isolated_mode', array(
|
||||||
|
'type' => 'boolean',
|
||||||
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
||||||
|
'default' => false,
|
||||||
|
) );
|
||||||
|
|
||||||
// Auth token section.
|
// Auth token section.
|
||||||
add_settings_section(
|
add_settings_section(
|
||||||
'wp_prometheus_auth_section',
|
'wp_prometheus_auth_section',
|
||||||
@@ -394,32 +402,261 @@ class Settings {
|
|||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get metrics sub-tabs.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function get_metrics_subtabs(): array {
|
||||||
|
return array(
|
||||||
|
'endpoint' => __( 'Endpoint', 'wp-prometheus' ),
|
||||||
|
'selection' => __( 'Selection', 'wp-prometheus' ),
|
||||||
|
'runtime' => __( 'Runtime', 'wp-prometheus' ),
|
||||||
|
'advanced' => __( 'Advanced', 'wp-prometheus' ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current metrics sub-tab.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function get_current_metrics_subtab(): string {
|
||||||
|
$subtab = isset( $_GET['subtab'] ) ? sanitize_key( $_GET['subtab'] ) : 'endpoint';
|
||||||
|
$subtabs = $this->get_metrics_subtabs();
|
||||||
|
return array_key_exists( $subtab, $subtabs ) ? $subtab : 'endpoint';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render metrics tab content.
|
* Render metrics tab content.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function render_metrics_tab(): void {
|
private function render_metrics_tab(): void {
|
||||||
|
$subtabs = $this->get_metrics_subtabs();
|
||||||
|
$current_subtab = $this->get_current_metrics_subtab();
|
||||||
|
?>
|
||||||
|
<div class="wp-prometheus-subtabs">
|
||||||
|
<ul class="wp-prometheus-subtab-nav">
|
||||||
|
<?php foreach ( $subtabs as $subtab_id => $subtab_name ) : ?>
|
||||||
|
<?php
|
||||||
|
$subtab_url = add_query_arg(
|
||||||
|
array(
|
||||||
|
'page' => 'wp-prometheus',
|
||||||
|
'tab' => 'metrics',
|
||||||
|
'subtab' => $subtab_id,
|
||||||
|
),
|
||||||
|
admin_url( 'options-general.php' )
|
||||||
|
);
|
||||||
|
$active_class = ( $current_subtab === $subtab_id ) ? ' active' : '';
|
||||||
|
?>
|
||||||
|
<li class="wp-prometheus-subtab-item<?php echo esc_attr( $active_class ); ?>">
|
||||||
|
<a href="<?php echo esc_url( $subtab_url ); ?>"><?php echo esc_html( $subtab_name ); ?></a>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="wp-prometheus-subtab-content">
|
||||||
|
<?php
|
||||||
|
switch ( $current_subtab ) {
|
||||||
|
case 'endpoint':
|
||||||
|
$this->render_metrics_endpoint_subtab();
|
||||||
|
break;
|
||||||
|
case 'selection':
|
||||||
|
$this->render_metrics_selection_subtab();
|
||||||
|
break;
|
||||||
|
case 'runtime':
|
||||||
|
$this->render_metrics_runtime_subtab();
|
||||||
|
break;
|
||||||
|
case 'advanced':
|
||||||
|
$this->render_metrics_advanced_subtab();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render metrics endpoint sub-tab.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function render_metrics_endpoint_subtab(): void {
|
||||||
?>
|
?>
|
||||||
<form method="post" action="options.php">
|
<form method="post" action="options.php">
|
||||||
<?php
|
<?php settings_fields( 'wp_prometheus_endpoint_settings' ); ?>
|
||||||
settings_fields( 'wp_prometheus_metrics_settings' );
|
|
||||||
do_settings_sections( 'wp-prometheus-metrics' );
|
<h3><?php esc_html_e( 'Authentication', 'wp-prometheus' ); ?></h3>
|
||||||
submit_button();
|
<p class="description"><?php esc_html_e( 'Configure authentication for the /metrics endpoint.', 'wp-prometheus' ); ?></p>
|
||||||
?>
|
|
||||||
|
<table class="form-table" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<label for="wp_prometheus_auth_token"><?php esc_html_e( 'Auth Token', 'wp-prometheus' ); ?></label>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<?php $this->render_auth_token_field(); ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php submit_button(); ?>
|
||||||
</form>
|
</form>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
<hr style="margin: 30px 0;">
|
/**
|
||||||
|
* Render metrics selection sub-tab.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function render_metrics_selection_subtab(): void {
|
||||||
|
?>
|
||||||
|
<form method="post" action="options.php">
|
||||||
|
<?php settings_fields( 'wp_prometheus_selection_settings' ); ?>
|
||||||
|
|
||||||
<h3><?php esc_html_e( 'Reset Runtime Metrics', 'wp-prometheus' ); ?></h3>
|
<h3><?php esc_html_e( 'Enabled Metrics', 'wp-prometheus' ); ?></h3>
|
||||||
<p class="description"><?php esc_html_e( 'Clear all accumulated runtime metric data (HTTP requests, database queries). This is useful for testing or starting fresh.', 'wp-prometheus' ); ?></p>
|
<p class="description"><?php esc_html_e( 'Select which metrics to expose on the /metrics endpoint.', 'wp-prometheus' ); ?></p>
|
||||||
<p>
|
|
||||||
<button type="button" id="wp-prometheus-reset-runtime" class="button button-secondary">
|
<table class="form-table" role="presentation">
|
||||||
<?php esc_html_e( 'Reset Runtime Metrics', 'wp-prometheus' ); ?>
|
<tr>
|
||||||
</button>
|
<th scope="row"><?php esc_html_e( 'Select Metrics', 'wp-prometheus' ); ?></th>
|
||||||
<span id="wp-prometheus-reset-spinner" class="spinner" style="float: none;"></span>
|
<td>
|
||||||
</p>
|
<?php $this->render_enabled_metrics_field(); ?>
|
||||||
<div id="wp-prometheus-reset-message" style="display: none; margin-top: 10px;"></div>
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php submit_button(); ?>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render metrics runtime sub-tab.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function render_metrics_runtime_subtab(): void {
|
||||||
|
?>
|
||||||
|
<h3><?php esc_html_e( 'Runtime Metrics Management', 'wp-prometheus' ); ?></h3>
|
||||||
|
<p class="description"><?php esc_html_e( 'Runtime metrics track HTTP requests and database queries across requests. Use this section to manage accumulated data.', 'wp-prometheus' ); ?></p>
|
||||||
|
|
||||||
|
<table class="form-table" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Reset Data', 'wp-prometheus' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<p class="description" style="margin-bottom: 10px;">
|
||||||
|
<?php esc_html_e( 'Clear all accumulated runtime metric data (HTTP requests, database queries). This is useful for testing or starting fresh.', 'wp-prometheus' ); ?>
|
||||||
|
</p>
|
||||||
|
<button type="button" id="wp-prometheus-reset-runtime" class="button button-secondary">
|
||||||
|
<?php esc_html_e( 'Reset Runtime Metrics', 'wp-prometheus' ); ?>
|
||||||
|
</button>
|
||||||
|
<span id="wp-prometheus-reset-spinner" class="spinner" style="float: none;"></span>
|
||||||
|
<div id="wp-prometheus-reset-message" style="display: none; margin-top: 10px;"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render metrics advanced sub-tab.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function render_metrics_advanced_subtab(): void {
|
||||||
|
$isolated_mode = get_option( 'wp_prometheus_isolated_mode', false );
|
||||||
|
$env_override = false !== getenv( 'WP_PROMETHEUS_ISOLATED_MODE' );
|
||||||
|
$is_metrics_request = defined( 'WP_PROMETHEUS_METRICS_REQUEST' ) && WP_PROMETHEUS_METRICS_REQUEST;
|
||||||
|
$is_isolated = defined( 'WP_PROMETHEUS_ISOLATED_MODE' ) && WP_PROMETHEUS_ISOLATED_MODE;
|
||||||
|
?>
|
||||||
|
<form method="post" action="options.php">
|
||||||
|
<?php settings_fields( 'wp_prometheus_advanced_settings' ); ?>
|
||||||
|
|
||||||
|
<h3><?php esc_html_e( 'Metrics Collection Mode', 'wp-prometheus' ); ?></h3>
|
||||||
|
|
||||||
|
<div class="notice notice-info inline" style="padding: 12px; margin: 15px 0;">
|
||||||
|
<p><strong><?php esc_html_e( 'Safe Mode (Default)', 'wp-prometheus' ); ?></strong></p>
|
||||||
|
<p><?php esc_html_e( 'Content filters are removed early to prevent memory issues with Twig-based plugins, but WordPress loads normally. Third-party plugins can add custom metrics via the wp_prometheus_collect_metrics hook.', 'wp-prometheus' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ( $env_override ) : ?>
|
||||||
|
<div class="notice notice-warning inline" style="padding: 12px; margin: 15px 0;">
|
||||||
|
<strong><?php esc_html_e( 'Environment Override Active', 'wp-prometheus' ); ?></strong>
|
||||||
|
<p><?php esc_html_e( 'Mode is configured via WP_PROMETHEUS_ISOLATED_MODE environment variable. Admin settings will be ignored.', 'wp-prometheus' ); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<table class="form-table" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Isolated Mode', 'wp-prometheus' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="wp_prometheus_isolated_mode" value="1"
|
||||||
|
<?php checked( $isolated_mode ); ?>
|
||||||
|
<?php disabled( $env_override ); ?>>
|
||||||
|
<?php esc_html_e( 'Enable isolated mode', 'wp-prometheus' ); ?>
|
||||||
|
</label>
|
||||||
|
<p class="description">
|
||||||
|
<?php esc_html_e( 'Isolated mode outputs metrics immediately before other plugins fully load. This provides maximum isolation but disables the wp_prometheus_collect_metrics hook. Use this only if you experience issues with Safe Mode.', 'wp-prometheus' ); ?>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Current Status', 'wp-prometheus' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<?php if ( $is_isolated ) : ?>
|
||||||
|
<span class="dashicons dashicons-lock" style="color: orange;"></span>
|
||||||
|
<?php esc_html_e( 'Isolated mode active - custom hooks are disabled', 'wp-prometheus' ); ?>
|
||||||
|
<?php elseif ( $is_metrics_request ) : ?>
|
||||||
|
<span class="dashicons dashicons-yes-alt" style="color: green;"></span>
|
||||||
|
<?php esc_html_e( 'Safe mode active - custom hooks enabled with filter protection', 'wp-prometheus' ); ?>
|
||||||
|
<?php elseif ( $isolated_mode ) : ?>
|
||||||
|
<span class="dashicons dashicons-lock" style="color: orange;"></span>
|
||||||
|
<?php esc_html_e( 'Isolated mode enabled (active for /metrics requests)', 'wp-prometheus' ); ?>
|
||||||
|
<?php else : ?>
|
||||||
|
<span class="dashicons dashicons-yes-alt" style="color: green;"></span>
|
||||||
|
<?php esc_html_e( 'Safe mode enabled (default) - custom hooks with filter protection', 'wp-prometheus' ); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<hr style="margin: 20px 0;">
|
||||||
|
|
||||||
|
<h4><?php esc_html_e( 'Mode Comparison', 'wp-prometheus' ); ?></h4>
|
||||||
|
<table class="widefat striped" style="max-width: 700px;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><?php esc_html_e( 'Feature', 'wp-prometheus' ); ?></th>
|
||||||
|
<th><?php esc_html_e( 'Safe Mode', 'wp-prometheus' ); ?></th>
|
||||||
|
<th><?php esc_html_e( 'Isolated Mode', 'wp-prometheus' ); ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Custom metrics hook', 'wp-prometheus' ); ?></td>
|
||||||
|
<td><span class="dashicons dashicons-yes" style="color: green;"></span></td>
|
||||||
|
<td><span class="dashicons dashicons-no" style="color: red;"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Plugin compatibility', 'wp-prometheus' ); ?></td>
|
||||||
|
<td><?php esc_html_e( 'High', 'wp-prometheus' ); ?></td>
|
||||||
|
<td><?php esc_html_e( 'Maximum', 'wp-prometheus' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><?php esc_html_e( 'Memory usage', 'wp-prometheus' ); ?></td>
|
||||||
|
<td><?php esc_html_e( 'Normal', 'wp-prometheus' ); ?></td>
|
||||||
|
<td><?php esc_html_e( 'Minimal', 'wp-prometheus' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php submit_button(); ?>
|
||||||
|
</form>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,14 +121,62 @@ class Collector {
|
|||||||
/**
|
/**
|
||||||
* Fires after default metrics are collected.
|
* Fires after default metrics are collected.
|
||||||
*
|
*
|
||||||
* Skip in early metrics mode to avoid triggering third-party hooks
|
* In isolated mode, skip custom hooks to avoid any potential issues.
|
||||||
* that may cause recursion issues (e.g., Twig-based plugins).
|
* In safe mode (default), fire hooks with protection against recursion.
|
||||||
*
|
*
|
||||||
* @param Collector $collector The metrics collector instance.
|
* @param Collector $collector The metrics collector instance.
|
||||||
*/
|
*/
|
||||||
if ( ! defined( 'WP_PROMETHEUS_EARLY_METRICS' ) || ! WP_PROMETHEUS_EARLY_METRICS ) {
|
if ( defined( 'WP_PROMETHEUS_ISOLATED_MODE' ) && WP_PROMETHEUS_ISOLATED_MODE ) {
|
||||||
do_action( 'wp_prometheus_collect_metrics', $this );
|
// Isolated mode: skip all third-party hooks for maximum safety.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safe mode: fire custom hooks with protection.
|
||||||
|
$this->fire_custom_metrics_hook();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fire custom metrics hook with protection against recursion.
|
||||||
|
*
|
||||||
|
* Removes potentially problematic filters, uses output buffering,
|
||||||
|
* and catches any errors from third-party plugins.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function fire_custom_metrics_hook(): void {
|
||||||
|
// Remove content filters again (in case any plugin re-added them).
|
||||||
|
if ( function_exists( 'wp_prometheus_remove_content_filters' ) ) {
|
||||||
|
wp_prometheus_remove_content_filters();
|
||||||
|
} else {
|
||||||
|
// Fallback if function doesn't exist.
|
||||||
|
remove_all_filters( 'the_content' );
|
||||||
|
remove_all_filters( 'the_excerpt' );
|
||||||
|
remove_all_filters( 'get_the_excerpt' );
|
||||||
|
remove_all_filters( 'the_title' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use output buffering to prevent any accidental output from plugins.
|
||||||
|
ob_start();
|
||||||
|
|
||||||
|
try {
|
||||||
|
/**
|
||||||
|
* Fires after default metrics are collected.
|
||||||
|
*
|
||||||
|
* Third-party plugins can use this hook to add custom metrics.
|
||||||
|
*
|
||||||
|
* @param Collector $collector The metrics collector instance.
|
||||||
|
*/
|
||||||
|
do_action( 'wp_prometheus_collect_metrics', $this );
|
||||||
|
} catch ( \Throwable $e ) {
|
||||||
|
// Log the error but don't let it break metrics output.
|
||||||
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||||
|
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
|
||||||
|
error_log( 'WP Prometheus: Error in custom metrics hook: ' . $e->getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard any output from plugins.
|
||||||
|
ob_end_clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Plugin Name: WP Prometheus
|
* Plugin Name: WP Prometheus
|
||||||
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wp-prometheus
|
* Plugin URI: https://src.bundespruefstelle.ch/magdev/wp-prometheus
|
||||||
* Description: Prometheus metrics endpoint for WordPress with extensible hooks for custom metrics.
|
* Description: Prometheus metrics endpoint for WordPress with extensible hooks for custom metrics.
|
||||||
* Version: 0.4.1
|
* Version: 0.4.5
|
||||||
* Requires at least: 6.4
|
* Requires at least: 6.4
|
||||||
* Requires PHP: 8.3
|
* Requires PHP: 8.3
|
||||||
* Author: Marco Graetsch
|
* Author: Marco Graetsch
|
||||||
@@ -22,11 +22,16 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Early metrics endpoint handler.
|
* Early metrics request detection.
|
||||||
*
|
*
|
||||||
* Intercepts /metrics requests before full WordPress initialization to avoid
|
* Detects /metrics requests early and removes problematic content filters
|
||||||
* conflicts with other plugins that may cause issues during template loading.
|
* to prevent recursion issues with Twig-based plugins. Unlike the previous
|
||||||
* This runs at plugin load time, before plugins_loaded hook.
|
* "early mode", this allows WordPress to continue loading so that third-party
|
||||||
|
* plugins can register their wp_prometheus_collect_metrics hooks.
|
||||||
|
*
|
||||||
|
* Two modes are available:
|
||||||
|
* - Safe mode (default): Removes filters early, lets WP load, fires custom hooks
|
||||||
|
* - Isolated mode: Outputs metrics immediately without custom hooks (legacy early mode)
|
||||||
*/
|
*/
|
||||||
function wp_prometheus_early_metrics_check(): void {
|
function wp_prometheus_early_metrics_check(): void {
|
||||||
// Only handle /metrics requests.
|
// Only handle /metrics requests.
|
||||||
@@ -37,6 +42,58 @@ function wp_prometheus_early_metrics_check(): void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set flag to indicate we're handling a metrics request.
|
||||||
|
define( 'WP_PROMETHEUS_METRICS_REQUEST', true );
|
||||||
|
|
||||||
|
// Check if isolated mode is enabled via environment variable.
|
||||||
|
$env_isolated = getenv( 'WP_PROMETHEUS_ISOLATED_MODE' );
|
||||||
|
$isolated_mode = false !== $env_isolated && in_array( strtolower( $env_isolated ), array( '1', 'true', 'yes', 'on' ), true );
|
||||||
|
|
||||||
|
// Check if isolated mode is enabled via option (legacy "early mode" setting).
|
||||||
|
if ( ! $isolated_mode && ! get_option( 'wp_prometheus_disable_early_mode', false ) ) {
|
||||||
|
// Check for legacy isolated mode option.
|
||||||
|
$isolated_mode = (bool) get_option( 'wp_prometheus_isolated_mode', false );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all content filters immediately to prevent recursion with Twig-based plugins.
|
||||||
|
// This is done for BOTH safe mode and isolated mode.
|
||||||
|
add_action( 'plugins_loaded', 'wp_prometheus_remove_content_filters', 0 );
|
||||||
|
|
||||||
|
// Also remove filters now in case they were added by mu-plugins.
|
||||||
|
wp_prometheus_remove_content_filters();
|
||||||
|
|
||||||
|
// If isolated mode is enabled, handle metrics immediately without waiting for plugins.
|
||||||
|
if ( $isolated_mode ) {
|
||||||
|
wp_prometheus_isolated_metrics_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove content filters that can cause recursion.
|
||||||
|
*
|
||||||
|
* Called early during metrics requests to prevent infinite loops
|
||||||
|
* with Twig-based plugins that hook into content filters.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function wp_prometheus_remove_content_filters(): void {
|
||||||
|
remove_all_filters( 'the_content' );
|
||||||
|
remove_all_filters( 'the_excerpt' );
|
||||||
|
remove_all_filters( 'get_the_excerpt' );
|
||||||
|
remove_all_filters( 'the_title' );
|
||||||
|
remove_all_filters( 'the_content_feed' );
|
||||||
|
remove_all_filters( 'comment_text' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle metrics in isolated mode (no custom hooks).
|
||||||
|
*
|
||||||
|
* This is the legacy "early mode" that outputs metrics immediately
|
||||||
|
* without allowing third-party plugins to add custom metrics.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function wp_prometheus_isolated_metrics_handler(): void {
|
||||||
// Check if autoloader exists.
|
// Check if autoloader exists.
|
||||||
$autoloader = __DIR__ . '/vendor/autoload.php';
|
$autoloader = __DIR__ . '/vendor/autoload.php';
|
||||||
if ( ! file_exists( $autoloader ) ) {
|
if ( ! file_exists( $autoloader ) ) {
|
||||||
@@ -87,14 +144,8 @@ function wp_prometheus_early_metrics_check(): void {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set flag to indicate early metrics mode - Collector will skip extensibility hooks.
|
// Set flag to indicate isolated mode - Collector will skip extensibility hooks.
|
||||||
define( 'WP_PROMETHEUS_EARLY_METRICS', true );
|
define( 'WP_PROMETHEUS_ISOLATED_MODE', true );
|
||||||
|
|
||||||
// Remove all content filters to prevent recursion with Twig-based plugins.
|
|
||||||
remove_all_filters( 'the_content' );
|
|
||||||
remove_all_filters( 'the_excerpt' );
|
|
||||||
remove_all_filters( 'get_the_excerpt' );
|
|
||||||
remove_all_filters( 'the_title' );
|
|
||||||
|
|
||||||
// Output metrics and exit immediately.
|
// Output metrics and exit immediately.
|
||||||
$collector = new \Magdev\WpPrometheus\Metrics\Collector();
|
$collector = new \Magdev\WpPrometheus\Metrics\Collector();
|
||||||
@@ -118,7 +169,7 @@ wp_prometheus_early_metrics_check();
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
define( 'WP_PROMETHEUS_VERSION', '0.4.1' );
|
define( 'WP_PROMETHEUS_VERSION', '0.4.5' );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin file path.
|
* Plugin file path.
|
||||||
|
|||||||
Reference in New Issue
Block a user