You've already forked wp-prometheus
feat: Add custom metric builder, export/import, and Grafana dashboards (v0.3.0)
All checks were successful
Create Release Package / build-release (push) Successful in 59s
All checks were successful
Create Release Package / build-release (push) Successful in 59s
- Custom Metrics Builder with admin UI for gauge metrics - Support for static values and WordPress option-based values - JSON-based export/import with skip/overwrite/rename modes - Three Grafana dashboard templates (overview, runtime, WooCommerce) - New tabs: Custom Metrics and Dashboards - Reset runtime metrics button Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
27
CHANGELOG.md
27
CHANGELOG.md
@@ -5,6 +5,33 @@ 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.3.0] - 2026-02-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Custom Metrics Builder:
|
||||||
|
- Admin UI to define custom gauge metrics
|
||||||
|
- Support for static values and WordPress option-based values
|
||||||
|
- Label support with up to 5 labels and 50 value combinations
|
||||||
|
- Metric validation following Prometheus naming conventions
|
||||||
|
- Metric Export/Import:
|
||||||
|
- JSON-based configuration export for backup
|
||||||
|
- Import with three modes: skip existing, overwrite, or rename duplicates
|
||||||
|
- Version tracking in export format
|
||||||
|
- Grafana Dashboard Templates:
|
||||||
|
- WordPress Overview dashboard (users, posts, comments, cron, transients)
|
||||||
|
- WordPress Runtime dashboard (HTTP requests, database queries)
|
||||||
|
- WordPress WooCommerce dashboard (orders, revenue, products, customers)
|
||||||
|
- Easy download and import instructions
|
||||||
|
- New "Custom Metrics" tab in admin settings
|
||||||
|
- New "Dashboards" tab in admin settings
|
||||||
|
- Reset runtime metrics button to clear accumulated data
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Settings page now has 5 tabs: License, Metrics, Custom Metrics, Dashboards, Help
|
||||||
|
- Updated translations with all new strings
|
||||||
|
|
||||||
## [0.2.2] - 2026-02-02
|
## [0.2.2] - 2026-02-02
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
46
CLAUDE.md
46
CLAUDE.md
@@ -18,6 +18,9 @@ This plugin provides a Prometheus `/metrics` endpoint and an extensible way to a
|
|||||||
- Cron job metrics (scheduled events, overdue, next run)
|
- Cron job metrics (scheduled events, overdue, next run)
|
||||||
- Transient cache metrics (total, expiring, expired)
|
- Transient cache metrics (total, expiring, expired)
|
||||||
- WooCommerce integration (products, orders, revenue, customers)
|
- WooCommerce integration (products, orders, revenue, customers)
|
||||||
|
- Custom metric builder with admin UI (gauges with static or option-based values)
|
||||||
|
- Metric export/import for backup and site migration
|
||||||
|
- Grafana dashboard templates for easy visualization
|
||||||
- Dedicated plugin settings under 'Settings/Metrics' menu
|
- Dedicated plugin settings under 'Settings/Metrics' menu
|
||||||
- Extensible by other plugins using `wp_prometheus_collect_metrics` action hook
|
- Extensible by other plugins using `wp_prometheus_collect_metrics` action hook
|
||||||
- License management integration
|
- License management integration
|
||||||
@@ -30,11 +33,7 @@ This project is proudly **"vibe-coded"** using Claude.AI - the entire codebase w
|
|||||||
|
|
||||||
**Note for AI Assistants:** Clean this section after the specific features are done or new releases are made. Effective changes are tracked in `CHANGELOG.md`. Do not add completed versions here - document them in the Session History section at the end of this file.
|
**Note for AI Assistants:** Clean this section after the specific features are done or new releases are made. Effective changes are tracked in `CHANGELOG.md`. Do not add completed versions here - document them in the Session History section at the end of this file.
|
||||||
|
|
||||||
### Version 0.3.0 (Planned)
|
*No planned features at this time.*
|
||||||
|
|
||||||
- Custom metric builder in admin
|
|
||||||
- Metric export/import
|
|
||||||
- Grafana dashboard templates
|
|
||||||
|
|
||||||
## Technical Stack
|
## Technical Stack
|
||||||
|
|
||||||
@@ -214,6 +213,10 @@ wp-prometheus/
|
|||||||
│ └── release.yml # CI/CD pipeline
|
│ └── release.yml # CI/CD pipeline
|
||||||
├── assets/
|
├── assets/
|
||||||
│ ├── css/ # Admin/Frontend styles
|
│ ├── css/ # Admin/Frontend styles
|
||||||
|
│ ├── dashboards/ # Grafana dashboard templates
|
||||||
|
│ │ ├── wordpress-overview.json
|
||||||
|
│ │ ├── wordpress-runtime.json
|
||||||
|
│ │ └── wordpress-woocommerce.json
|
||||||
│ └── js/
|
│ └── js/
|
||||||
│ └── admin.js # Admin JavaScript
|
│ └── admin.js # Admin JavaScript
|
||||||
├── languages/ # Translation files
|
├── languages/ # Translation files
|
||||||
@@ -222,6 +225,7 @@ wp-prometheus/
|
|||||||
├── releases/ # Release packages
|
├── releases/ # Release packages
|
||||||
├── src/
|
├── src/
|
||||||
│ ├── Admin/
|
│ ├── Admin/
|
||||||
|
│ │ ├── DashboardProvider.php # Grafana dashboard provider
|
||||||
│ │ └── Settings.php # Settings page
|
│ │ └── Settings.php # Settings page
|
||||||
│ ├── Endpoint/
|
│ ├── Endpoint/
|
||||||
│ │ └── MetricsEndpoint.php # /metrics endpoint
|
│ │ └── MetricsEndpoint.php # /metrics endpoint
|
||||||
@@ -229,6 +233,7 @@ wp-prometheus/
|
|||||||
│ │ └── Manager.php # License management
|
│ │ └── Manager.php # License management
|
||||||
│ ├── Metrics/
|
│ ├── Metrics/
|
||||||
│ │ ├── Collector.php # Prometheus metrics collector
|
│ │ ├── Collector.php # Prometheus metrics collector
|
||||||
|
│ │ ├── CustomMetricBuilder.php # Custom metric CRUD
|
||||||
│ │ └── RuntimeCollector.php # Runtime metrics collector
|
│ │ └── RuntimeCollector.php # Runtime metrics collector
|
||||||
│ ├── Installer.php # Activation/Deactivation
|
│ ├── Installer.php # Activation/Deactivation
|
||||||
│ ├── Plugin.php # Main plugin class
|
│ ├── Plugin.php # Main plugin class
|
||||||
@@ -285,6 +290,37 @@ add_action( 'wp_prometheus_collect_metrics', function( $collector ) {
|
|||||||
|
|
||||||
## Session History
|
## Session History
|
||||||
|
|
||||||
|
### 2026-02-02 - Custom Metrics & Dashboards (v0.3.0)
|
||||||
|
|
||||||
|
- Added Custom Metric Builder with full admin UI:
|
||||||
|
- `CustomMetricBuilder.php` - CRUD operations, validation, export/import
|
||||||
|
- Support for static values and WordPress option-based values
|
||||||
|
- Label support (max 5 labels, 50 value combinations)
|
||||||
|
- Prometheus naming convention validation (`[a-zA-Z_:][a-zA-Z0-9_:]*`)
|
||||||
|
- Added Grafana Dashboard Templates:
|
||||||
|
- `DashboardProvider.php` - Dashboard file provider with path traversal protection
|
||||||
|
- `wordpress-overview.json` - General WordPress metrics
|
||||||
|
- `wordpress-runtime.json` - HTTP/DB performance metrics
|
||||||
|
- `wordpress-woocommerce.json` - WooCommerce store metrics
|
||||||
|
- Added export/import functionality:
|
||||||
|
- JSON-based configuration export
|
||||||
|
- Three import modes: skip, overwrite, rename duplicates
|
||||||
|
- Version tracking in export format
|
||||||
|
- Updated Settings page with new tabs:
|
||||||
|
- "Custom Metrics" tab with metric form and table
|
||||||
|
- "Dashboards" tab with download buttons
|
||||||
|
- "Reset Runtime Metrics" button in Metrics tab
|
||||||
|
- Updated `Collector.php` to integrate custom metrics
|
||||||
|
- Updated translation files with all new strings
|
||||||
|
- **Key Learning**: Dynamic form handling in WordPress admin
|
||||||
|
- Use `wp_create_nonce()` with unique nonce names per AJAX action
|
||||||
|
- Localize script with `wp_localize_script()` for nonces and AJAX URL
|
||||||
|
- Always verify `current_user_can('manage_options')` in AJAX handlers
|
||||||
|
- **Key Learning**: Grafana dashboard JSON format
|
||||||
|
- Use `${DS_PROMETHEUS}` for data source variable
|
||||||
|
- Schema version 39 for current Grafana compatibility
|
||||||
|
- Panels use `gridPos` for layout positioning
|
||||||
|
|
||||||
### 2026-02-02 - Extended Metrics (v0.2.0)
|
### 2026-02-02 - Extended Metrics (v0.2.0)
|
||||||
|
|
||||||
- Added WooCommerce integration metrics (only when WooCommerce is active):
|
- Added WooCommerce integration metrics (only when WooCommerce is active):
|
||||||
|
|||||||
@@ -45,3 +45,163 @@
|
|||||||
.wp-prometheus-tab-content .form-table {
|
.wp-prometheus-tab-content .form-table {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Custom metrics form */
|
||||||
|
.wp-prometheus-metric-form {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ccd0d4;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-metric-form h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-metric-form .required {
|
||||||
|
color: #d63638;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Label rows */
|
||||||
|
.metric-label-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-label-row input {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-label-row .remove-label {
|
||||||
|
padding: 0 8px;
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Value rows */
|
||||||
|
.metric-value-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value-row input {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value-row .remove-value-row {
|
||||||
|
padding: 0 8px;
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom metrics table */
|
||||||
|
.wp-prometheus-custom-metrics .wp-list-table code {
|
||||||
|
background: #f0f0f1;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-custom-metrics .wp-list-table td {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-custom-metrics .wp-list-table .dashicons {
|
||||||
|
font-size: 18px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dashboard grid */
|
||||||
|
.wp-prometheus-dashboard-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-dashboard-card {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ccd0d4;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
transition: box-shadow 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-dashboard-card:hover {
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-dashboard-card .dashboard-icon {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-dashboard-card .dashboard-icon .dashicons {
|
||||||
|
font-size: 48px;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
color: #2271b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-dashboard-card h3 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wp-prometheus-dashboard-card p {
|
||||||
|
color: #646970;
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Import options panel */
|
||||||
|
#import-options {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#import-options label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Spinner alignment */
|
||||||
|
.spinner {
|
||||||
|
float: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button groups */
|
||||||
|
.wp-prometheus-tab-content .button + .button {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notice messages in forms */
|
||||||
|
.wp-prometheus-metric-form .notice,
|
||||||
|
.wp-prometheus-custom-metrics .notice {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive adjustments */
|
||||||
|
@media screen and (max-width: 782px) {
|
||||||
|
.wp-prometheus-dashboard-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value-row {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value-row input {
|
||||||
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
851
assets/dashboards/wordpress-overview.json
Normal file
851
assets/dashboards/wordpress-overview.json
Normal file
@@ -0,0 +1,851 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
"panels": [],
|
||||||
|
"title": "System Info",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 0,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "/^version$/",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_info",
|
||||||
|
"format": "table",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "WordPress Version",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 6,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "/^php_version$/",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_info",
|
||||||
|
"format": "table",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "PHP Version",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "blue",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 12,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_users_total)",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total Users",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "blue",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 18,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_plugins_total{status=\"active\"}",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Active Plugins",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 5
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"panels": [],
|
||||||
|
"title": "Content",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": []
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 8,
|
||||||
|
"x": 0,
|
||||||
|
"y": 6
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "right",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"pieType": "pie",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_users_total",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "{{role}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Users by Role",
|
||||||
|
"type": "piechart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": []
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 8,
|
||||||
|
"x": 8,
|
||||||
|
"y": 6
|
||||||
|
},
|
||||||
|
"id": 8,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "right",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"pieType": "pie",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_posts_total{post_type=\"post\"}",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "{{status}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Posts by Status",
|
||||||
|
"type": "piechart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": []
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 8,
|
||||||
|
"x": 16,
|
||||||
|
"y": 6
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "right",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"pieType": "pie",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_comments_total{status!=\"total_comments\"}",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "{{status}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Comments by Status",
|
||||||
|
"type": "piechart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 14
|
||||||
|
},
|
||||||
|
"id": 10,
|
||||||
|
"panels": [],
|
||||||
|
"title": "System Health",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 0,
|
||||||
|
"y": 15
|
||||||
|
},
|
||||||
|
"id": 11,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_cron_overdue_total",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Overdue Cron Events",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "blue",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 6,
|
||||||
|
"y": 15
|
||||||
|
},
|
||||||
|
"id": 12,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_cron_events_total)",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total Cron Events",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "blue",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 12,
|
||||||
|
"y": 15
|
||||||
|
},
|
||||||
|
"id": 13,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "none",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_transients_total{type=\"total\"}",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total Transients",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 18,
|
||||||
|
"y": 15
|
||||||
|
},
|
||||||
|
"id": 14,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_transients_total{type=\"expired\"}",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Expired Transients",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "bars",
|
||||||
|
"fillOpacity": 80,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "linear",
|
||||||
|
"lineWidth": 1,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "auto",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 19
|
||||||
|
},
|
||||||
|
"id": 15,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "topk(10, wordpress_cron_events_total)",
|
||||||
|
"instant": false,
|
||||||
|
"legendFormat": "{{hook}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Top 10 Cron Hooks",
|
||||||
|
"type": "timeseries"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "30s",
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"tags": ["wordpress", "prometheus"],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "Prometheus",
|
||||||
|
"value": "Prometheus"
|
||||||
|
},
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": false,
|
||||||
|
"label": "Data Source",
|
||||||
|
"multi": false,
|
||||||
|
"name": "DS_PROMETHEUS",
|
||||||
|
"options": [],
|
||||||
|
"query": "prometheus",
|
||||||
|
"queryValue": "",
|
||||||
|
"refresh": 1,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"type": "datasource"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "WordPress Overview",
|
||||||
|
"uid": "wp-prometheus-overview",
|
||||||
|
"version": 1,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
987
assets/dashboards/wordpress-runtime.json
Normal file
987
assets/dashboards/wordpress-runtime.json
Normal file
@@ -0,0 +1,987 @@
|
|||||||
|
{
|
||||||
|
"annotations": {
|
||||||
|
"list": []
|
||||||
|
},
|
||||||
|
"editable": true,
|
||||||
|
"fiscalYearStartMonth": 0,
|
||||||
|
"graphTooltip": 0,
|
||||||
|
"id": null,
|
||||||
|
"links": [],
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
"panels": [],
|
||||||
|
"title": "HTTP Requests",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "smooth",
|
||||||
|
"lineWidth": 2,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "reqps"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": ["mean", "max"],
|
||||||
|
"displayMode": "table",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "multi",
|
||||||
|
"sort": "desc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(rate(wordpress_http_requests_total[5m])) by (endpoint)",
|
||||||
|
"legendFormat": "{{endpoint}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Requests per Second by Endpoint",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "smooth",
|
||||||
|
"lineWidth": 2,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "reqps"
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byRegexp",
|
||||||
|
"options": "/2..$/"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "color",
|
||||||
|
"value": {
|
||||||
|
"fixedColor": "green",
|
||||||
|
"mode": "fixed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byRegexp",
|
||||||
|
"options": "/4..$/"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "color",
|
||||||
|
"value": {
|
||||||
|
"fixedColor": "orange",
|
||||||
|
"mode": "fixed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matcher": {
|
||||||
|
"id": "byRegexp",
|
||||||
|
"options": "/5..$/"
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "color",
|
||||||
|
"value": {
|
||||||
|
"fixedColor": "red",
|
||||||
|
"mode": "fixed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 1
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": ["mean", "max"],
|
||||||
|
"displayMode": "table",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "multi",
|
||||||
|
"sort": "desc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(rate(wordpress_http_requests_total[5m])) by (status)",
|
||||||
|
"legendFormat": "{{status}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Requests per Second by Status",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": []
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 8,
|
||||||
|
"x": 0,
|
||||||
|
"y": 9
|
||||||
|
},
|
||||||
|
"id": 4,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "right",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"pieType": "donut",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_http_requests_total) by (method)",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "{{method}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Requests by Method",
|
||||||
|
"type": "piechart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": []
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 8,
|
||||||
|
"x": 8,
|
||||||
|
"y": 9
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "right",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"pieType": "donut",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_http_requests_total) by (endpoint)",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "{{endpoint}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Requests by Endpoint",
|
||||||
|
"type": "piechart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "blue",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 8,
|
||||||
|
"x": 16,
|
||||||
|
"y": 9
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_http_requests_total)",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total Requests (All Time)",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 17
|
||||||
|
},
|
||||||
|
"id": 7,
|
||||||
|
"panels": [],
|
||||||
|
"title": "Request Duration",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "smooth",
|
||||||
|
"lineWidth": 2,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 18
|
||||||
|
},
|
||||||
|
"id": 8,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": ["mean", "max"],
|
||||||
|
"displayMode": "table",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "multi",
|
||||||
|
"sort": "desc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_http_request_duration_seconds_sum / wordpress_http_request_duration_seconds_count",
|
||||||
|
"legendFormat": "{{method}} {{endpoint}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Average Request Duration",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"fillOpacity": 80,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"lineWidth": 1,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 18
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
|
"options": {
|
||||||
|
"barRadius": 0,
|
||||||
|
"barWidth": 0.97,
|
||||||
|
"fullHighlight": false,
|
||||||
|
"groupWidth": 0.7,
|
||||||
|
"legend": {
|
||||||
|
"calcs": [],
|
||||||
|
"displayMode": "list",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"orientation": "horizontal",
|
||||||
|
"showValue": "auto",
|
||||||
|
"stacking": "none",
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "single",
|
||||||
|
"sort": "none"
|
||||||
|
},
|
||||||
|
"xTickLabelRotation": 0,
|
||||||
|
"xTickLabelSpacing": 0
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_http_request_duration_seconds_bucket) by (le)",
|
||||||
|
"format": "table",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "{{le}}",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Request Duration Distribution (Buckets)",
|
||||||
|
"type": "barchart"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsed": false,
|
||||||
|
"gridPos": {
|
||||||
|
"h": 1,
|
||||||
|
"w": 24,
|
||||||
|
"x": 0,
|
||||||
|
"y": 26
|
||||||
|
},
|
||||||
|
"id": 10,
|
||||||
|
"panels": [],
|
||||||
|
"title": "Database Queries",
|
||||||
|
"type": "row"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "smooth",
|
||||||
|
"lineWidth": 2,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 27
|
||||||
|
},
|
||||||
|
"id": 11,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": ["mean", "max"],
|
||||||
|
"displayMode": "table",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "multi",
|
||||||
|
"sort": "desc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "rate(wordpress_db_queries_total[5m])",
|
||||||
|
"legendFormat": "{{endpoint}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Database Queries per Second",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "palette-classic"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"axisBorderShow": false,
|
||||||
|
"axisCenteredZero": false,
|
||||||
|
"axisColorMode": "text",
|
||||||
|
"axisLabel": "",
|
||||||
|
"axisPlacement": "auto",
|
||||||
|
"barAlignment": 0,
|
||||||
|
"drawStyle": "line",
|
||||||
|
"fillOpacity": 10,
|
||||||
|
"gradientMode": "none",
|
||||||
|
"hideFrom": {
|
||||||
|
"legend": false,
|
||||||
|
"tooltip": false,
|
||||||
|
"viz": false
|
||||||
|
},
|
||||||
|
"insertNulls": false,
|
||||||
|
"lineInterpolation": "smooth",
|
||||||
|
"lineWidth": 2,
|
||||||
|
"pointSize": 5,
|
||||||
|
"scaleDistribution": {
|
||||||
|
"type": "linear"
|
||||||
|
},
|
||||||
|
"showPoints": "never",
|
||||||
|
"spanNulls": false,
|
||||||
|
"stacking": {
|
||||||
|
"group": "A",
|
||||||
|
"mode": "none"
|
||||||
|
},
|
||||||
|
"thresholdsStyle": {
|
||||||
|
"mode": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 8,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 27
|
||||||
|
},
|
||||||
|
"id": 12,
|
||||||
|
"options": {
|
||||||
|
"legend": {
|
||||||
|
"calcs": ["mean", "max"],
|
||||||
|
"displayMode": "table",
|
||||||
|
"placement": "bottom",
|
||||||
|
"showLegend": true
|
||||||
|
},
|
||||||
|
"tooltip": {
|
||||||
|
"mode": "multi",
|
||||||
|
"sort": "desc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "wordpress_db_query_duration_seconds_sum / wordpress_db_query_duration_seconds_count",
|
||||||
|
"legendFormat": "{{endpoint}}",
|
||||||
|
"range": true,
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Average Query Duration",
|
||||||
|
"type": "timeseries"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "blue",
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "short"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 12,
|
||||||
|
"x": 0,
|
||||||
|
"y": 35
|
||||||
|
},
|
||||||
|
"id": 13,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_db_queries_total)",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Total Database Queries (All Time)",
|
||||||
|
"type": "stat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 0.5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "s"
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 12,
|
||||||
|
"x": 12,
|
||||||
|
"y": 35
|
||||||
|
},
|
||||||
|
"id": 14,
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "auto",
|
||||||
|
"orientation": "auto",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": ["lastNotNull"],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "auto"
|
||||||
|
},
|
||||||
|
"pluginVersion": "10.0.0",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "${DS_PROMETHEUS}"
|
||||||
|
},
|
||||||
|
"editorMode": "code",
|
||||||
|
"expr": "sum(wordpress_db_query_duration_seconds_sum) / sum(wordpress_db_query_duration_seconds_count)",
|
||||||
|
"instant": true,
|
||||||
|
"legendFormat": "__auto",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Average Query Duration (Overall)",
|
||||||
|
"type": "stat"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "30s",
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"tags": ["wordpress", "prometheus", "performance"],
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"current": {
|
||||||
|
"selected": false,
|
||||||
|
"text": "Prometheus",
|
||||||
|
"value": "Prometheus"
|
||||||
|
},
|
||||||
|
"hide": 0,
|
||||||
|
"includeAll": false,
|
||||||
|
"label": "Data Source",
|
||||||
|
"multi": false,
|
||||||
|
"name": "DS_PROMETHEUS",
|
||||||
|
"options": [],
|
||||||
|
"query": "prometheus",
|
||||||
|
"queryValue": "",
|
||||||
|
"refresh": 1,
|
||||||
|
"regex": "",
|
||||||
|
"skipUrlSync": false,
|
||||||
|
"type": "datasource"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"from": "now-6h",
|
||||||
|
"to": "now"
|
||||||
|
},
|
||||||
|
"timepicker": {},
|
||||||
|
"timezone": "browser",
|
||||||
|
"title": "WordPress Runtime Performance",
|
||||||
|
"uid": "wp-prometheus-runtime",
|
||||||
|
"version": 1,
|
||||||
|
"weekStart": ""
|
||||||
|
}
|
||||||
1296
assets/dashboards/wordpress-woocommerce.json
Normal file
1296
assets/dashboards/wordpress-woocommerce.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,26 @@
|
|||||||
(function($) {
|
(function($) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var importFileContent = null;
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
// License tab handlers.
|
||||||
|
initLicenseHandlers();
|
||||||
|
|
||||||
|
// Custom metrics tab handlers.
|
||||||
|
initCustomMetricsHandlers();
|
||||||
|
|
||||||
|
// Dashboards tab handlers.
|
||||||
|
initDashboardsHandlers();
|
||||||
|
|
||||||
|
// Runtime metrics reset handler.
|
||||||
|
initResetRuntimeHandler();
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize license tab handlers.
|
||||||
|
*/
|
||||||
|
function initLicenseHandlers() {
|
||||||
// Validate license button.
|
// Validate license button.
|
||||||
$('#wp-prometheus-validate-license').on('click', function(e) {
|
$('#wp-prometheus-validate-license').on('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -23,78 +42,575 @@
|
|||||||
// Regenerate token button.
|
// Regenerate token button.
|
||||||
$('#wp-prometheus-regenerate-token').on('click', function(e) {
|
$('#wp-prometheus-regenerate-token').on('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (confirm('Are you sure you want to regenerate the auth token? You will need to update your Prometheus configuration.')) {
|
if (confirm(wpPrometheus.confirmRegenerateToken)) {
|
||||||
var newToken = generateToken(32);
|
var newToken = generateToken(32);
|
||||||
$('#wp_prometheus_auth_token').val(newToken);
|
$('#wp_prometheus_auth_token').val(newToken);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a license action via AJAX.
|
* Initialize custom metrics tab handlers.
|
||||||
*
|
*/
|
||||||
* @param {string} action AJAX action name.
|
function initCustomMetricsHandlers() {
|
||||||
* @param {string} message Loading message.
|
var $formContainer = $('#wp-prometheus-metric-form-container');
|
||||||
*/
|
var $form = $('#wp-prometheus-metric-form');
|
||||||
function performLicenseAction(action, message) {
|
var $showFormBtn = $('#show-metric-form');
|
||||||
var $spinner = $('#wp-prometheus-license-spinner');
|
|
||||||
var $message = $('#wp-prometheus-license-message');
|
|
||||||
|
|
||||||
$spinner.addClass('is-active');
|
// Show metric form.
|
||||||
$message.hide();
|
$showFormBtn.on('click', function() {
|
||||||
|
resetMetricForm();
|
||||||
|
$formContainer.slideDown();
|
||||||
|
$(this).hide();
|
||||||
|
});
|
||||||
|
|
||||||
$.ajax({
|
// Cancel metric form.
|
||||||
url: wpPrometheus.ajaxUrl,
|
$('#cancel-metric-form').on('click', function() {
|
||||||
type: 'POST',
|
$formContainer.slideUp();
|
||||||
data: {
|
$showFormBtn.show();
|
||||||
action: action,
|
// Remove edit parameter from URL.
|
||||||
nonce: wpPrometheus.nonce
|
if (window.location.search.indexOf('edit=') > -1) {
|
||||||
},
|
window.history.pushState({}, '', window.location.pathname + '?page=wp-prometheus&tab=custom');
|
||||||
success: function(response) {
|
}
|
||||||
$spinner.removeClass('is-active');
|
});
|
||||||
|
|
||||||
if (response.success) {
|
// Value type toggle.
|
||||||
$message
|
$('input[name="value_type"]').on('change', function() {
|
||||||
.removeClass('notice-error')
|
var valueType = $(this).val();
|
||||||
.addClass('notice notice-success')
|
if (valueType === 'option') {
|
||||||
.html('<p>' + response.data.message + '</p>')
|
$('#option-config-row').show();
|
||||||
.show();
|
$('#static-values-row').hide();
|
||||||
|
} else {
|
||||||
|
$('#option-config-row').hide();
|
||||||
|
$('#static-values-row').show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Reload page after successful validation/activation.
|
// Add label.
|
||||||
setTimeout(function() {
|
$('#add-label').on('click', function() {
|
||||||
location.reload();
|
var $container = $('#metric-labels-container');
|
||||||
}, 1500);
|
var labelCount = $container.find('.metric-label-row').length;
|
||||||
} else {
|
|
||||||
$message
|
if (labelCount >= 5) {
|
||||||
.removeClass('notice-success')
|
alert('Maximum 5 labels allowed per metric.');
|
||||||
.addClass('notice notice-error')
|
return;
|
||||||
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
}
|
||||||
.show();
|
|
||||||
}
|
var $row = $('<div class="metric-label-row">' +
|
||||||
},
|
'<input type="text" name="labels[]" class="regular-text" placeholder="label_name" pattern="[a-zA-Z_][a-zA-Z0-9_]*">' +
|
||||||
error: function() {
|
'<button type="button" class="button remove-label">×</button>' +
|
||||||
$spinner.removeClass('is-active');
|
'</div>');
|
||||||
|
$container.append($row);
|
||||||
|
updateValueRows();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove label.
|
||||||
|
$(document).on('click', '.remove-label', function() {
|
||||||
|
$(this).closest('.metric-label-row').remove();
|
||||||
|
updateValueRows();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add value row.
|
||||||
|
$('#add-value-row').on('click', function() {
|
||||||
|
var $container = $('#metric-values-container');
|
||||||
|
var rowCount = $container.find('.metric-value-row').length;
|
||||||
|
var labelCount = getLabelCount();
|
||||||
|
|
||||||
|
var $row = $('<div class="metric-value-row"></div>');
|
||||||
|
|
||||||
|
// Add label value inputs.
|
||||||
|
var labels = getLabels();
|
||||||
|
for (var i = 0; i < labelCount; i++) {
|
||||||
|
$row.append('<input type="text" name="label_values[' + rowCount + '][]" class="small-text" placeholder="' + (labels[i] || 'value') + '">');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add metric value input.
|
||||||
|
$row.append('<input type="number" name="label_values[' + rowCount + '][]" class="small-text" step="any" placeholder="Value">');
|
||||||
|
$row.append('<button type="button" class="button remove-value-row">×</button>');
|
||||||
|
|
||||||
|
$container.append($row);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove value row.
|
||||||
|
$(document).on('click', '.remove-value-row', function() {
|
||||||
|
$(this).closest('.metric-value-row').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Submit metric form.
|
||||||
|
$form.on('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
saveCustomMetric();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete metric.
|
||||||
|
$(document).on('click', '.delete-metric', function() {
|
||||||
|
var id = $(this).data('id');
|
||||||
|
if (confirm(wpPrometheus.confirmDelete)) {
|
||||||
|
deleteCustomMetric(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Export metrics.
|
||||||
|
$('#export-metrics').on('click', function() {
|
||||||
|
exportMetrics();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Import metrics - trigger file input.
|
||||||
|
$('#import-metrics-btn').on('click', function() {
|
||||||
|
$('#import-metrics-file').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Import file selected.
|
||||||
|
$('#import-metrics-file').on('change', function(e) {
|
||||||
|
var file = e.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function(e) {
|
||||||
|
importFileContent = e.target.result;
|
||||||
|
$('#import-options').slideDown();
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Confirm import.
|
||||||
|
$('#confirm-import').on('click', function() {
|
||||||
|
var mode = $('input[name="import_mode"]:checked').val();
|
||||||
|
importMetrics(importFileContent, mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cancel import.
|
||||||
|
$('#cancel-import').on('click', function() {
|
||||||
|
$('#import-options').slideUp();
|
||||||
|
$('#import-metrics-file').val('');
|
||||||
|
importFileContent = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize dashboards tab handlers.
|
||||||
|
*/
|
||||||
|
function initDashboardsHandlers() {
|
||||||
|
$(document).on('click', '.download-dashboard', function() {
|
||||||
|
var slug = $(this).data('slug');
|
||||||
|
downloadDashboard(slug);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize reset runtime metrics handler.
|
||||||
|
*/
|
||||||
|
function initResetRuntimeHandler() {
|
||||||
|
$('#wp-prometheus-reset-runtime').on('click', function() {
|
||||||
|
if (confirm(wpPrometheus.confirmReset)) {
|
||||||
|
resetRuntimeMetrics();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a license action via AJAX.
|
||||||
|
*
|
||||||
|
* @param {string} action AJAX action name.
|
||||||
|
* @param {string} message Loading message.
|
||||||
|
*/
|
||||||
|
function performLicenseAction(action, message) {
|
||||||
|
var $spinner = $('#wp-prometheus-license-spinner');
|
||||||
|
var $message = $('#wp-prometheus-license-message');
|
||||||
|
|
||||||
|
$spinner.addClass('is-active');
|
||||||
|
$message.hide();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: wpPrometheus.ajaxUrl,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: action,
|
||||||
|
nonce: wpPrometheus.nonce
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
$message
|
||||||
|
.removeClass('notice-error')
|
||||||
|
.addClass('notice notice-success')
|
||||||
|
.html('<p>' + response.data.message + '</p>')
|
||||||
|
.show();
|
||||||
|
|
||||||
|
// Reload page after successful validation/activation.
|
||||||
|
setTimeout(function() {
|
||||||
|
location.reload();
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
$message
|
$message
|
||||||
.removeClass('notice-success')
|
.removeClass('notice-success')
|
||||||
.addClass('notice notice-error')
|
.addClass('notice notice-error')
|
||||||
.html('<p>Connection error. Please try again.</p>')
|
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
}
|
error: function() {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
/**
|
$message
|
||||||
* Generate a random token.
|
.removeClass('notice-success')
|
||||||
*
|
.addClass('notice notice-error')
|
||||||
* @param {number} length Token length.
|
.html('<p>Connection error. Please try again.</p>')
|
||||||
* @return {string} Generated token.
|
.show();
|
||||||
*/
|
|
||||||
function generateToken(length) {
|
|
||||||
var charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
||||||
var token = '';
|
|
||||||
for (var i = 0; i < length; i++) {
|
|
||||||
token += charset.charAt(Math.floor(Math.random() * charset.length));
|
|
||||||
}
|
}
|
||||||
return token;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save custom metric via AJAX.
|
||||||
|
*/
|
||||||
|
function saveCustomMetric() {
|
||||||
|
var $spinner = $('#wp-prometheus-metric-spinner');
|
||||||
|
var $message = $('#wp-prometheus-metric-message');
|
||||||
|
var $form = $('#wp-prometheus-metric-form');
|
||||||
|
|
||||||
|
$spinner.addClass('is-active');
|
||||||
|
$message.hide();
|
||||||
|
|
||||||
|
var formData = $form.serialize();
|
||||||
|
formData += '&action=wp_prometheus_save_custom_metric';
|
||||||
|
formData += '&nonce=' + wpPrometheus.customMetricNonce;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: wpPrometheus.ajaxUrl,
|
||||||
|
type: 'POST',
|
||||||
|
data: formData,
|
||||||
|
success: function(response) {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
$message
|
||||||
|
.removeClass('notice-error')
|
||||||
|
.addClass('notice notice-success')
|
||||||
|
.html('<p>' + response.data.message + '</p>')
|
||||||
|
.show();
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = window.location.pathname + '?page=wp-prometheus&tab=custom';
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
$message
|
||||||
|
.removeClass('notice-success')
|
||||||
|
.addClass('notice notice-error')
|
||||||
|
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
$message
|
||||||
|
.removeClass('notice-success')
|
||||||
|
.addClass('notice notice-error')
|
||||||
|
.html('<p>Connection error. Please try again.</p>')
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete custom metric via AJAX.
|
||||||
|
*
|
||||||
|
* @param {string} id Metric ID.
|
||||||
|
*/
|
||||||
|
function deleteCustomMetric(id) {
|
||||||
|
$.ajax({
|
||||||
|
url: wpPrometheus.ajaxUrl,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: 'wp_prometheus_delete_custom_metric',
|
||||||
|
nonce: wpPrometheus.customMetricNonce,
|
||||||
|
id: id
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
$('tr[data-metric-id="' + id + '"]').fadeOut(function() {
|
||||||
|
$(this).remove();
|
||||||
|
// Check if table is empty.
|
||||||
|
if ($('.wp-prometheus-custom-metrics tbody tr').length === 0) {
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alert(response.data.message || 'An error occurred.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert('Connection error. Please try again.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export metrics via AJAX.
|
||||||
|
*/
|
||||||
|
function exportMetrics() {
|
||||||
|
$.ajax({
|
||||||
|
url: wpPrometheus.ajaxUrl,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: 'wp_prometheus_export_metrics',
|
||||||
|
nonce: wpPrometheus.exportNonce
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
downloadFile(response.data.json, response.data.filename, 'application/json');
|
||||||
|
} else {
|
||||||
|
alert(response.data.message || 'An error occurred.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert('Connection error. Please try again.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import metrics via AJAX.
|
||||||
|
*
|
||||||
|
* @param {string} json JSON content.
|
||||||
|
* @param {string} mode Import mode.
|
||||||
|
*/
|
||||||
|
function importMetrics(json, mode) {
|
||||||
|
var $spinner = $('#wp-prometheus-import-spinner');
|
||||||
|
var $message = $('#wp-prometheus-import-message');
|
||||||
|
|
||||||
|
$spinner.addClass('is-active');
|
||||||
|
$message.hide();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: wpPrometheus.ajaxUrl,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: 'wp_prometheus_import_metrics',
|
||||||
|
nonce: wpPrometheus.importNonce,
|
||||||
|
json: json,
|
||||||
|
mode: mode
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
$message
|
||||||
|
.removeClass('notice-error')
|
||||||
|
.addClass('notice notice-success')
|
||||||
|
.html('<p>' + response.data.message + '</p>')
|
||||||
|
.show();
|
||||||
|
|
||||||
|
$('#import-options').slideUp();
|
||||||
|
$('#import-metrics-file').val('');
|
||||||
|
importFileContent = null;
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
location.reload();
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
$message
|
||||||
|
.removeClass('notice-success')
|
||||||
|
.addClass('notice notice-error')
|
||||||
|
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
$message
|
||||||
|
.removeClass('notice-success')
|
||||||
|
.addClass('notice notice-error')
|
||||||
|
.html('<p>Connection error. Please try again.</p>')
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download dashboard via AJAX.
|
||||||
|
*
|
||||||
|
* @param {string} slug Dashboard slug.
|
||||||
|
*/
|
||||||
|
function downloadDashboard(slug) {
|
||||||
|
$.ajax({
|
||||||
|
url: wpPrometheus.ajaxUrl,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: 'wp_prometheus_download_dashboard',
|
||||||
|
nonce: wpPrometheus.dashboardNonce,
|
||||||
|
slug: slug
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
if (response.success) {
|
||||||
|
downloadFile(response.data.json, response.data.filename, 'application/json');
|
||||||
|
} else {
|
||||||
|
alert(response.data.message || 'An error occurred.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
alert('Connection error. Please try again.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset runtime metrics via AJAX.
|
||||||
|
*/
|
||||||
|
function resetRuntimeMetrics() {
|
||||||
|
var $spinner = $('#wp-prometheus-reset-spinner');
|
||||||
|
var $message = $('#wp-prometheus-reset-message');
|
||||||
|
|
||||||
|
$spinner.addClass('is-active');
|
||||||
|
$message.hide();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: wpPrometheus.ajaxUrl,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
action: 'wp_prometheus_reset_runtime_metrics',
|
||||||
|
nonce: wpPrometheus.resetRuntimeNonce
|
||||||
|
},
|
||||||
|
success: function(response) {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
$message
|
||||||
|
.removeClass('notice-error')
|
||||||
|
.addClass('notice notice-success')
|
||||||
|
.html('<p>' + response.data.message + '</p>')
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
$message
|
||||||
|
.removeClass('notice-success')
|
||||||
|
.addClass('notice notice-error')
|
||||||
|
.html('<p>' + (response.data.message || 'An error occurred.') + '</p>')
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
$spinner.removeClass('is-active');
|
||||||
|
$message
|
||||||
|
.removeClass('notice-success')
|
||||||
|
.addClass('notice notice-error')
|
||||||
|
.html('<p>Connection error. Please try again.</p>')
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the metric form to default state.
|
||||||
|
*/
|
||||||
|
function resetMetricForm() {
|
||||||
|
var $form = $('#wp-prometheus-metric-form');
|
||||||
|
$form[0].reset();
|
||||||
|
$('#metric-id').val('');
|
||||||
|
$('#wp-prometheus-form-title').text('Add New Metric');
|
||||||
|
$('#option-config-row').hide();
|
||||||
|
$('#static-values-row').show();
|
||||||
|
$('#wp-prometheus-metric-message').hide();
|
||||||
|
|
||||||
|
// Reset labels to single empty row.
|
||||||
|
$('#metric-labels-container').html(
|
||||||
|
'<div class="metric-label-row">' +
|
||||||
|
'<input type="text" name="labels[]" class="regular-text" placeholder="label_name" pattern="[a-zA-Z_][a-zA-Z0-9_]*">' +
|
||||||
|
'<button type="button" class="button remove-label">×</button>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Reset values to single empty row.
|
||||||
|
$('#metric-values-container').html(
|
||||||
|
'<div class="metric-value-row">' +
|
||||||
|
'<input type="number" name="label_values[0][]" class="small-text" step="any" placeholder="Value">' +
|
||||||
|
'<button type="button" class="button remove-value-row">×</button>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update value rows when labels change.
|
||||||
|
*/
|
||||||
|
function updateValueRows() {
|
||||||
|
var labels = getLabels();
|
||||||
|
var labelCount = labels.length;
|
||||||
|
|
||||||
|
$('#metric-values-container .metric-value-row').each(function(rowIndex) {
|
||||||
|
var $row = $(this);
|
||||||
|
var inputs = $row.find('input').toArray();
|
||||||
|
var currentValues = inputs.map(function(input) { return input.value; });
|
||||||
|
|
||||||
|
// Remove all inputs except the value and button.
|
||||||
|
$row.find('input').remove();
|
||||||
|
|
||||||
|
// Re-add label inputs.
|
||||||
|
for (var i = 0; i < labelCount; i++) {
|
||||||
|
var val = currentValues[i] || '';
|
||||||
|
$row.prepend('<input type="text" name="label_values[' + rowIndex + '][]" class="small-text" placeholder="' + (labels[i] || 'value') + '" value="' + val + '">');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-add value input.
|
||||||
|
var metricVal = currentValues[currentValues.length - 1] || '';
|
||||||
|
$row.find('.remove-value-row').before('<input type="number" name="label_values[' + rowIndex + '][]" class="small-text" step="any" placeholder="Value" value="' + metricVal + '">');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current label names.
|
||||||
|
*
|
||||||
|
* @return {string[]} Array of label names.
|
||||||
|
*/
|
||||||
|
function getLabels() {
|
||||||
|
var labels = [];
|
||||||
|
$('#metric-labels-container input[name="labels[]"]').each(function() {
|
||||||
|
var val = $(this).val().trim();
|
||||||
|
if (val) {
|
||||||
|
labels.push(val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current label count.
|
||||||
|
*
|
||||||
|
* @return {number} Number of labels.
|
||||||
|
*/
|
||||||
|
function getLabelCount() {
|
||||||
|
return getLabels().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random token.
|
||||||
|
*
|
||||||
|
* @param {number} length Token length.
|
||||||
|
* @return {string} Generated token.
|
||||||
|
*/
|
||||||
|
function generateToken(length) {
|
||||||
|
var charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||||
|
var token = '';
|
||||||
|
for (var i = 0; i < length; i++) {
|
||||||
|
token += charset.charAt(Math.floor(Math.random() * charset.length));
|
||||||
}
|
}
|
||||||
});
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download a file.
|
||||||
|
*
|
||||||
|
* @param {string} content File content.
|
||||||
|
* @param {string} filename Filename.
|
||||||
|
* @param {string} type MIME type.
|
||||||
|
*/
|
||||||
|
function downloadFile(content, filename, type) {
|
||||||
|
var blob = new Blob([content], { type: type });
|
||||||
|
var url = URL.createObjectURL(blob);
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
document.body.removeChild(a);
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|||||||
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.2.0\n"
|
"Project-Id-Version: WP Prometheus 0.3.0\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"
|
||||||
@@ -31,6 +31,14 @@ msgstr "Lizenz"
|
|||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "Hilfe"
|
msgstr "Hilfe"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Custom Metrics"
|
||||||
|
msgstr "Eigene Metriken"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Dashboards"
|
||||||
|
msgstr "Dashboards"
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
#: src/Admin/Settings.php
|
||||||
msgid "License settings saved."
|
msgid "License settings saved."
|
||||||
msgstr "Lizenz-Einstellungen gespeichert."
|
msgstr "Lizenz-Einstellungen gespeichert."
|
||||||
@@ -213,6 +221,18 @@ msgstr "WooCommerce-Umsatz (gesamt, heute, Monat)"
|
|||||||
msgid "WooCommerce Customers (registered, guest)"
|
msgid "WooCommerce Customers (registered, guest)"
|
||||||
msgstr "WooCommerce-Kunden (registriert, Gast)"
|
msgstr "WooCommerce-Kunden (registriert, Gast)"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Reset Runtime Metrics"
|
||||||
|
msgstr "Laufzeit-Metriken zuruecksetzen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Clear all accumulated runtime metric data."
|
||||||
|
msgstr "Alle gesammelten Laufzeit-Metrikdaten loeschen."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Reset Metrics"
|
||||||
|
msgstr "Metriken zuruecksetzen"
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
#: src/Admin/Settings.php
|
||||||
msgid "Prometheus Configuration"
|
msgid "Prometheus Configuration"
|
||||||
msgstr "Prometheus-Konfiguration"
|
msgstr "Prometheus-Konfiguration"
|
||||||
@@ -329,14 +349,252 @@ msgstr "WooCommerce-Umsatz nach Zeitraum"
|
|||||||
msgid "WooCommerce customers by type"
|
msgid "WooCommerce customers by type"
|
||||||
msgstr "WooCommerce-Kunden nach Typ"
|
msgstr "WooCommerce-Kunden nach Typ"
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
|
||||||
msgid "Custom Metrics"
|
|
||||||
msgstr "Benutzerdefinierte Metriken"
|
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
#: src/Admin/Settings.php
|
||||||
msgid "You can add custom metrics using the wp_prometheus_collect_metrics action:"
|
msgid "You can add custom metrics using the wp_prometheus_collect_metrics action:"
|
||||||
msgstr "Sie koennen benutzerdefinierte Metriken mit der wp_prometheus_collect_metrics-Aktion hinzufuegen:"
|
msgstr "Sie koennen benutzerdefinierte Metriken mit der wp_prometheus_collect_metrics-Aktion hinzufuegen:"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Add Custom Metric"
|
||||||
|
msgstr "Eigene Metrik hinzufuegen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Edit Custom Metric"
|
||||||
|
msgstr "Eigene Metrik bearbeiten"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Metric Name"
|
||||||
|
msgstr "Metrik-Name"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Must follow Prometheus naming conventions."
|
||||||
|
msgstr "Muss den Prometheus-Namenskonventionen entsprechen."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Help Text"
|
||||||
|
msgstr "Hilfetext"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Description shown in Prometheus output."
|
||||||
|
msgstr "Beschreibung in der Prometheus-Ausgabe."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Value Type"
|
||||||
|
msgstr "Werttyp"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Static Value"
|
||||||
|
msgstr "Statischer Wert"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "WordPress Option"
|
||||||
|
msgstr "WordPress-Option"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Static Value:"
|
||||||
|
msgstr "Statischer Wert:"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Option Name:"
|
||||||
|
msgstr "Optionsname:"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "The name of the WordPress option to read."
|
||||||
|
msgstr "Der Name der zu lesenden WordPress-Option."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Labels"
|
||||||
|
msgstr "Labels"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Label name"
|
||||||
|
msgstr "Label-Name"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Add Label"
|
||||||
|
msgstr "Label hinzufuegen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Label Values"
|
||||||
|
msgstr "Label-Werte"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Value"
|
||||||
|
msgstr "Wert"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Add Value Row"
|
||||||
|
msgstr "Wertezeile hinzufuegen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Enabled"
|
||||||
|
msgstr "Aktiviert"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Save Metric"
|
||||||
|
msgstr "Metrik speichern"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Abbrechen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Your Custom Metrics"
|
||||||
|
msgstr "Ihre eigenen Metriken"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Name"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Status"
|
||||||
|
msgstr "Status"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Actions"
|
||||||
|
msgstr "Aktionen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Active"
|
||||||
|
msgstr "Aktiv"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr "Inaktiv"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr "Bearbeiten"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Delete"
|
||||||
|
msgstr "Loeschen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "No custom metrics defined yet."
|
||||||
|
msgstr "Noch keine eigenen Metriken definiert."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Export / Import"
|
||||||
|
msgstr "Export / Import"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Export your custom metrics configuration for backup or transfer to another site."
|
||||||
|
msgstr "Exportieren Sie Ihre Metriken-Konfiguration zur Sicherung oder Uebertragung auf eine andere Website."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Export Metrics"
|
||||||
|
msgstr "Metriken exportieren"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import Metrics"
|
||||||
|
msgstr "Metriken importieren"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import Options"
|
||||||
|
msgstr "Import-Optionen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Skip existing metrics"
|
||||||
|
msgstr "Bestehende Metriken ueberspringen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Overwrite existing metrics"
|
||||||
|
msgstr "Bestehende Metriken ueberschreiben"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Rename duplicates"
|
||||||
|
msgstr "Duplikate umbenennen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import"
|
||||||
|
msgstr "Importieren"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Grafana Dashboard Templates"
|
||||||
|
msgstr "Grafana Dashboard-Vorlagen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Download pre-built Grafana dashboards for visualizing your WordPress metrics."
|
||||||
|
msgstr "Laden Sie vorgefertigte Grafana-Dashboards zur Visualisierung Ihrer WordPress-Metriken herunter."
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Download"
|
||||||
|
msgstr "Herunterladen"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import instructions:"
|
||||||
|
msgstr "Import-Anleitung:"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Download the desired dashboard JSON file"
|
||||||
|
msgstr "Laden Sie die gewuenschte Dashboard-JSON-Datei herunter"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "In Grafana, go to Dashboards > Import"
|
||||||
|
msgstr "Gehen Sie in Grafana zu Dashboards > Import"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Upload the JSON file or paste its contents"
|
||||||
|
msgstr "Laden Sie die JSON-Datei hoch oder fuegen Sie deren Inhalt ein"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Select your Prometheus data source"
|
||||||
|
msgstr "Waehlen Sie Ihre Prometheus-Datenquelle"
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Click Import"
|
||||||
|
msgstr "Klicken Sie auf Import"
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Metric name is required."
|
||||||
|
msgstr "Metrik-Name ist erforderlich."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid metric name format."
|
||||||
|
msgstr "Ungueltiges Metrik-Namensformat."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "A metric with this name already exists."
|
||||||
|
msgstr "Eine Metrik mit diesem Namen existiert bereits."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Help text is required."
|
||||||
|
msgstr "Hilfetext ist erforderlich."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid value type."
|
||||||
|
msgstr "Ungueltiger Werttyp."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Static value must be numeric."
|
||||||
|
msgstr "Statischer Wert muss numerisch sein."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Option name is required for option value type."
|
||||||
|
msgstr "Optionsname ist fuer den Options-Werttyp erforderlich."
|
||||||
|
|
||||||
|
#. translators: %d: Maximum number of labels
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Maximum %d labels allowed."
|
||||||
|
msgstr "Maximal %d Labels erlaubt."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid label name format."
|
||||||
|
msgstr "Ungueltiges Label-Namensformat."
|
||||||
|
|
||||||
|
#. translators: %d: Maximum number of label value combinations
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Maximum %d label value combinations allowed."
|
||||||
|
msgstr "Maximal %d Label-Wert-Kombinationen erlaubt."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid JSON format."
|
||||||
|
msgstr "Ungueltiges JSON-Format."
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid export format."
|
||||||
|
msgstr "Ungueltiges Export-Format."
|
||||||
|
|
||||||
#: src/Plugin.php
|
#: src/Plugin.php
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Einstellungen"
|
msgstr "Einstellungen"
|
||||||
|
|||||||
@@ -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.2.0\n"
|
"Project-Id-Version: WP Prometheus 0.3.0\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"
|
||||||
@@ -28,6 +28,14 @@ msgstr ""
|
|||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Custom Metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Dashboards"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
#: src/Admin/Settings.php
|
||||||
msgid "License settings saved."
|
msgid "License settings saved."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -210,6 +218,18 @@ msgstr ""
|
|||||||
msgid "WooCommerce Customers (registered, guest)"
|
msgid "WooCommerce Customers (registered, guest)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Reset Runtime Metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Clear all accumulated runtime metric data."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Reset Metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
#: src/Admin/Settings.php
|
||||||
msgid "Prometheus Configuration"
|
msgid "Prometheus Configuration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -327,11 +347,249 @@ msgid "WooCommerce customers by type"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
#: src/Admin/Settings.php
|
||||||
msgid "Custom Metrics"
|
msgid "You can add custom metrics using the wp_prometheus_collect_metrics action:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Admin/Settings.php
|
#: src/Admin/Settings.php
|
||||||
msgid "You can add custom metrics using the wp_prometheus_collect_metrics action:"
|
msgid "Add Custom Metric"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Edit Custom Metric"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Metric Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Must follow Prometheus naming conventions."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Help Text"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Description shown in Prometheus output."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Value Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Static Value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "WordPress Option"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Static Value:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Option Name:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "The name of the WordPress option to read."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Labels"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Label name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Add Label"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Label Values"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Add Value Row"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Enabled"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Save Metric"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Your Custom Metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Status"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Actions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Active"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Inactive"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Delete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "No custom metrics defined yet."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Export / Import"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Export your custom metrics configuration for backup or transfer to another site."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Export Metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import Metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import Options"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Skip existing metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Overwrite existing metrics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Rename duplicates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Grafana Dashboard Templates"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Download pre-built Grafana dashboards for visualizing your WordPress metrics."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Download"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Import instructions:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Download the desired dashboard JSON file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "In Grafana, go to Dashboards > Import"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Upload the JSON file or paste its contents"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Select your Prometheus data source"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Admin/Settings.php
|
||||||
|
msgid "Click Import"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Metric name is required."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid metric name format."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "A metric with this name already exists."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Help text is required."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid value type."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Static value must be numeric."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Option name is required for option value type."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. translators: %d: Maximum number of labels
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Maximum %d labels allowed."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid label name format."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. translators: %d: Maximum number of label value combinations
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Maximum %d label value combinations allowed."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid JSON format."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/Metrics/CustomMetricBuilder.php
|
||||||
|
msgid "Invalid export format."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/Plugin.php
|
#: src/Plugin.php
|
||||||
|
|||||||
151
src/Admin/DashboardProvider.php
Normal file
151
src/Admin/DashboardProvider.php
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Dashboard provider class.
|
||||||
|
*
|
||||||
|
* @package WP_Prometheus
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Magdev\WpPrometheus\Admin;
|
||||||
|
|
||||||
|
// Prevent direct file access.
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DashboardProvider class.
|
||||||
|
*
|
||||||
|
* Provides Grafana dashboard templates for download.
|
||||||
|
*/
|
||||||
|
class DashboardProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dashboard directory path.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private string $dashboard_dir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Available dashboard definitions.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private array $dashboards = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$this->dashboard_dir = WP_PROMETHEUS_PATH . 'assets/dashboards/';
|
||||||
|
|
||||||
|
$this->dashboards = array(
|
||||||
|
'wordpress-overview' => array(
|
||||||
|
'title' => __( 'WordPress Overview', 'wp-prometheus' ),
|
||||||
|
'description' => __( 'General WordPress metrics including users, posts, comments, and plugins.', 'wp-prometheus' ),
|
||||||
|
'file' => 'wordpress-overview.json',
|
||||||
|
'icon' => 'dashicons-wordpress',
|
||||||
|
),
|
||||||
|
'wordpress-runtime' => array(
|
||||||
|
'title' => __( 'Runtime Performance', 'wp-prometheus' ),
|
||||||
|
'description' => __( 'HTTP request metrics, database query performance, and response times.', 'wp-prometheus' ),
|
||||||
|
'file' => 'wordpress-runtime.json',
|
||||||
|
'icon' => 'dashicons-performance',
|
||||||
|
),
|
||||||
|
'wordpress-woocommerce' => array(
|
||||||
|
'title' => __( 'WooCommerce Store', 'wp-prometheus' ),
|
||||||
|
'description' => __( 'WooCommerce metrics including products, orders, revenue, and customers.', 'wp-prometheus' ),
|
||||||
|
'file' => 'wordpress-woocommerce.json',
|
||||||
|
'icon' => 'dashicons-cart',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of available dashboards.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_available(): array {
|
||||||
|
$available = array();
|
||||||
|
|
||||||
|
foreach ( $this->dashboards as $slug => $dashboard ) {
|
||||||
|
$file_path = $this->dashboard_dir . $dashboard['file'];
|
||||||
|
if ( file_exists( $file_path ) ) {
|
||||||
|
$available[ $slug ] = $dashboard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $available;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dashboard content by slug.
|
||||||
|
*
|
||||||
|
* @param string $slug Dashboard slug.
|
||||||
|
* @return string|null JSON content or null if not found.
|
||||||
|
*/
|
||||||
|
public function get_dashboard( string $slug ): ?string {
|
||||||
|
// Validate slug to prevent directory traversal.
|
||||||
|
$slug = sanitize_file_name( $slug );
|
||||||
|
|
||||||
|
if ( ! isset( $this->dashboards[ $slug ] ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file_path = $this->dashboard_dir . $this->dashboards[ $slug ]['file'];
|
||||||
|
|
||||||
|
// Security: Ensure file is within dashboard directory.
|
||||||
|
$real_path = realpath( $file_path );
|
||||||
|
$real_dir = realpath( $this->dashboard_dir );
|
||||||
|
|
||||||
|
if ( false === $real_path || false === $real_dir || strpos( $real_path, $real_dir ) !== 0 ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
|
||||||
|
$content = file_get_contents( $file_path );
|
||||||
|
|
||||||
|
if ( false === $content ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dashboard metadata by slug.
|
||||||
|
*
|
||||||
|
* @param string $slug Dashboard slug.
|
||||||
|
* @return array|null Dashboard metadata or null if not found.
|
||||||
|
*/
|
||||||
|
public function get_metadata( string $slug ): ?array {
|
||||||
|
$slug = sanitize_file_name( $slug );
|
||||||
|
|
||||||
|
if ( ! isset( $this->dashboards[ $slug ] ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->dashboards[ $slug ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get filename for download.
|
||||||
|
*
|
||||||
|
* @param string $slug Dashboard slug.
|
||||||
|
* @return string|null Filename or null if not found.
|
||||||
|
*/
|
||||||
|
public function get_filename( string $slug ): ?string {
|
||||||
|
$slug = sanitize_file_name( $slug );
|
||||||
|
|
||||||
|
if ( ! isset( $this->dashboards[ $slug ] ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->dashboards[ $slug ]['file'];
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,7 @@ final class Installer {
|
|||||||
'wp_prometheus_enable_default_metrics',
|
'wp_prometheus_enable_default_metrics',
|
||||||
'wp_prometheus_enabled_metrics',
|
'wp_prometheus_enabled_metrics',
|
||||||
'wp_prometheus_runtime_metrics',
|
'wp_prometheus_runtime_metrics',
|
||||||
|
'wp_prometheus_custom_metrics',
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ( $options as $option ) {
|
foreach ( $options as $option ) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace Magdev\WpPrometheus\Metrics;
|
|||||||
use Prometheus\CollectorRegistry;
|
use Prometheus\CollectorRegistry;
|
||||||
use Prometheus\Storage\InMemory;
|
use Prometheus\Storage\InMemory;
|
||||||
use Prometheus\RenderTextFormat;
|
use Prometheus\RenderTextFormat;
|
||||||
|
use Magdev\WpPrometheus\Metrics\CustomMetricBuilder;
|
||||||
|
|
||||||
// Prevent direct file access.
|
// Prevent direct file access.
|
||||||
if ( ! defined( 'ABSPATH' ) ) {
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
@@ -113,6 +114,10 @@ class Collector {
|
|||||||
// Collect runtime metrics (HTTP requests, DB queries).
|
// Collect runtime metrics (HTTP requests, DB queries).
|
||||||
$this->collect_runtime_metrics( $enabled_metrics );
|
$this->collect_runtime_metrics( $enabled_metrics );
|
||||||
|
|
||||||
|
// Collect custom user-defined metrics.
|
||||||
|
$custom_builder = new CustomMetricBuilder();
|
||||||
|
$custom_builder->register_with_collector( $this );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fires after default metrics are collected.
|
* Fires after default metrics are collected.
|
||||||
*
|
*
|
||||||
|
|||||||
496
src/Metrics/CustomMetricBuilder.php
Normal file
496
src/Metrics/CustomMetricBuilder.php
Normal file
@@ -0,0 +1,496 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Custom metric builder class.
|
||||||
|
*
|
||||||
|
* @package WP_Prometheus
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Magdev\WpPrometheus\Metrics;
|
||||||
|
|
||||||
|
// Prevent direct file access.
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CustomMetricBuilder class.
|
||||||
|
*
|
||||||
|
* Manages custom user-defined Prometheus metrics.
|
||||||
|
*/
|
||||||
|
class CustomMetricBuilder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Option name for storing custom metrics.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const OPTION_NAME = 'wp_prometheus_custom_metrics';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export format version.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const EXPORT_VERSION = '1.0.0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of labels per metric.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const MAX_LABELS = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of label value combinations per metric.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const MAX_LABEL_VALUES = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all custom metrics.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_all(): array {
|
||||||
|
$metrics = get_option( self::OPTION_NAME, array() );
|
||||||
|
return is_array( $metrics ) ? $metrics : array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a single metric by ID.
|
||||||
|
*
|
||||||
|
* @param string $id Metric ID.
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function get( string $id ): ?array {
|
||||||
|
$metrics = $this->get_all();
|
||||||
|
return $metrics[ $id ] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a metric (create or update).
|
||||||
|
*
|
||||||
|
* @param array $metric Metric data.
|
||||||
|
* @return string Metric ID.
|
||||||
|
* @throws \InvalidArgumentException If validation fails.
|
||||||
|
*/
|
||||||
|
public function save( array $metric ): string {
|
||||||
|
$errors = $this->validate( $metric );
|
||||||
|
if ( ! empty( $errors ) ) {
|
||||||
|
throw new \InvalidArgumentException( implode( ', ', $errors ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$metrics = $this->get_all();
|
||||||
|
|
||||||
|
// Generate ID if not provided.
|
||||||
|
if ( empty( $metric['id'] ) ) {
|
||||||
|
$metric['id'] = wp_generate_uuid4();
|
||||||
|
$metric['created_at'] = time();
|
||||||
|
}
|
||||||
|
|
||||||
|
$metric['updated_at'] = time();
|
||||||
|
|
||||||
|
// Sanitize and normalize the metric data.
|
||||||
|
$metric = $this->sanitize_metric( $metric );
|
||||||
|
|
||||||
|
$metrics[ $metric['id'] ] = $metric;
|
||||||
|
update_option( self::OPTION_NAME, $metrics );
|
||||||
|
|
||||||
|
return $metric['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a metric.
|
||||||
|
*
|
||||||
|
* @param string $id Metric ID.
|
||||||
|
* @return bool True if deleted, false if not found.
|
||||||
|
*/
|
||||||
|
public function delete( string $id ): bool {
|
||||||
|
$metrics = $this->get_all();
|
||||||
|
|
||||||
|
if ( ! isset( $metrics[ $id ] ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unset( $metrics[ $id ] );
|
||||||
|
update_option( self::OPTION_NAME, $metrics );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a Prometheus metric name.
|
||||||
|
*
|
||||||
|
* @param string $name Metric name.
|
||||||
|
* @return bool True if valid.
|
||||||
|
*/
|
||||||
|
public function validate_name( string $name ): bool {
|
||||||
|
// Prometheus metric names must match: [a-zA-Z_:][a-zA-Z0-9_:]*
|
||||||
|
return (bool) preg_match( '/^[a-zA-Z_:][a-zA-Z0-9_:]*$/', $name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a Prometheus label name.
|
||||||
|
*
|
||||||
|
* @param string $name Label name.
|
||||||
|
* @return bool True if valid.
|
||||||
|
*/
|
||||||
|
public function validate_label_name( string $name ): bool {
|
||||||
|
// Prometheus label names must match: [a-zA-Z_][a-zA-Z0-9_]*
|
||||||
|
// Labels starting with __ are reserved.
|
||||||
|
if ( strpos( $name, '__' ) === 0 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (bool) preg_match( '/^[a-zA-Z_][a-zA-Z0-9_]*$/', $name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate a complete metric definition.
|
||||||
|
*
|
||||||
|
* @param array $metric Metric data.
|
||||||
|
* @return array Array of error messages (empty if valid).
|
||||||
|
*/
|
||||||
|
public function validate( array $metric ): array {
|
||||||
|
$errors = array();
|
||||||
|
|
||||||
|
// Name is required.
|
||||||
|
if ( empty( $metric['name'] ) ) {
|
||||||
|
$errors[] = __( 'Metric name is required.', 'wp-prometheus' );
|
||||||
|
} elseif ( ! $this->validate_name( $metric['name'] ) ) {
|
||||||
|
$errors[] = __( 'Metric name must start with a letter, underscore, or colon, and contain only letters, numbers, underscores, and colons.', 'wp-prometheus' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for reserved prefixes.
|
||||||
|
if ( ! empty( $metric['name'] ) ) {
|
||||||
|
$reserved_prefixes = array( 'wordpress_', 'go_', 'process_', 'promhttp_' );
|
||||||
|
foreach ( $reserved_prefixes as $prefix ) {
|
||||||
|
if ( strpos( $metric['name'], $prefix ) === 0 ) {
|
||||||
|
$errors[] = sprintf(
|
||||||
|
/* translators: %s: Reserved prefix */
|
||||||
|
__( 'Metric name cannot start with reserved prefix "%s".', 'wp-prometheus' ),
|
||||||
|
$prefix
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for duplicate names (excluding current metric if editing).
|
||||||
|
if ( ! empty( $metric['name'] ) ) {
|
||||||
|
$existing = $this->get_all();
|
||||||
|
foreach ( $existing as $id => $existing_metric ) {
|
||||||
|
if ( $existing_metric['name'] === $metric['name'] && ( empty( $metric['id'] ) || $metric['id'] !== $id ) ) {
|
||||||
|
$errors[] = __( 'A metric with this name already exists.', 'wp-prometheus' );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Help text is required.
|
||||||
|
if ( empty( $metric['help'] ) ) {
|
||||||
|
$errors[] = __( 'Help text is required.', 'wp-prometheus' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate type.
|
||||||
|
$valid_types = array( 'gauge' );
|
||||||
|
if ( empty( $metric['type'] ) || ! in_array( $metric['type'], $valid_types, true ) ) {
|
||||||
|
$errors[] = __( 'Invalid metric type. Only gauge is supported.', 'wp-prometheus' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate labels.
|
||||||
|
if ( ! empty( $metric['labels'] ) ) {
|
||||||
|
if ( ! is_array( $metric['labels'] ) ) {
|
||||||
|
$errors[] = __( 'Labels must be an array.', 'wp-prometheus' );
|
||||||
|
} elseif ( count( $metric['labels'] ) > self::MAX_LABELS ) {
|
||||||
|
$errors[] = sprintf(
|
||||||
|
/* translators: %d: Maximum labels */
|
||||||
|
__( 'Maximum %d labels allowed per metric.', 'wp-prometheus' ),
|
||||||
|
self::MAX_LABELS
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
foreach ( $metric['labels'] as $label ) {
|
||||||
|
if ( ! $this->validate_label_name( $label ) ) {
|
||||||
|
$errors[] = sprintf(
|
||||||
|
/* translators: %s: Label name */
|
||||||
|
__( 'Invalid label name: %s', 'wp-prometheus' ),
|
||||||
|
$label
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate value type.
|
||||||
|
$valid_value_types = array( 'static', 'option' );
|
||||||
|
if ( empty( $metric['value_type'] ) || ! in_array( $metric['value_type'], $valid_value_types, true ) ) {
|
||||||
|
$errors[] = __( 'Invalid value type. Must be "static" or "option".', 'wp-prometheus' );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate value config based on type.
|
||||||
|
if ( ! empty( $metric['value_type'] ) ) {
|
||||||
|
if ( 'static' === $metric['value_type'] ) {
|
||||||
|
// Static values validated in label_values.
|
||||||
|
} elseif ( 'option' === $metric['value_type'] ) {
|
||||||
|
if ( empty( $metric['value_config']['option_name'] ) ) {
|
||||||
|
$errors[] = __( 'Option name is required for option-based metrics.', 'wp-prometheus' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate label values count.
|
||||||
|
if ( ! empty( $metric['label_values'] ) && is_array( $metric['label_values'] ) ) {
|
||||||
|
if ( count( $metric['label_values'] ) > self::MAX_LABEL_VALUES ) {
|
||||||
|
$errors[] = sprintf(
|
||||||
|
/* translators: %d: Maximum label combinations */
|
||||||
|
__( 'Maximum %d label value combinations allowed.', 'wp-prometheus' ),
|
||||||
|
self::MAX_LABEL_VALUES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate each row has correct number of values.
|
||||||
|
$label_count = count( $metric['labels'] ?? array() );
|
||||||
|
foreach ( $metric['label_values'] as $row ) {
|
||||||
|
if ( is_array( $row ) && count( $row ) !== $label_count + 1 ) { // +1 for value.
|
||||||
|
$errors[] = __( 'Each label value row must have values for all labels plus a metric value.', 'wp-prometheus' );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitize metric data.
|
||||||
|
*
|
||||||
|
* @param array $metric Raw metric data.
|
||||||
|
* @return array Sanitized metric data.
|
||||||
|
*/
|
||||||
|
private function sanitize_metric( array $metric ): array {
|
||||||
|
$sanitized = array(
|
||||||
|
'id' => sanitize_key( $metric['id'] ?? '' ),
|
||||||
|
'name' => sanitize_key( $metric['name'] ?? '' ),
|
||||||
|
'help' => sanitize_text_field( $metric['help'] ?? '' ),
|
||||||
|
'type' => sanitize_key( $metric['type'] ?? 'gauge' ),
|
||||||
|
'labels' => array(),
|
||||||
|
'value_type' => sanitize_key( $metric['value_type'] ?? 'static' ),
|
||||||
|
'value_config' => array(),
|
||||||
|
'label_values' => array(),
|
||||||
|
'enabled' => ! empty( $metric['enabled'] ),
|
||||||
|
'created_at' => absint( $metric['created_at'] ?? time() ),
|
||||||
|
'updated_at' => absint( $metric['updated_at'] ?? time() ),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sanitize labels.
|
||||||
|
if ( ! empty( $metric['labels'] ) && is_array( $metric['labels'] ) ) {
|
||||||
|
foreach ( $metric['labels'] as $label ) {
|
||||||
|
$sanitized['labels'][] = sanitize_key( $label );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize value config.
|
||||||
|
if ( 'static' === $sanitized['value_type'] ) {
|
||||||
|
$sanitized['value_config'] = array();
|
||||||
|
} elseif ( 'option' === $sanitized['value_type'] ) {
|
||||||
|
$sanitized['value_config'] = array(
|
||||||
|
'option_name' => sanitize_key( $metric['value_config']['option_name'] ?? '' ),
|
||||||
|
'default' => floatval( $metric['value_config']['default'] ?? 0 ),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize label values.
|
||||||
|
if ( ! empty( $metric['label_values'] ) && is_array( $metric['label_values'] ) ) {
|
||||||
|
foreach ( $metric['label_values'] as $row ) {
|
||||||
|
if ( is_array( $row ) ) {
|
||||||
|
$sanitized_row = array();
|
||||||
|
foreach ( $row as $index => $value ) {
|
||||||
|
// Last value is the metric value (numeric).
|
||||||
|
if ( $index === count( $row ) - 1 ) {
|
||||||
|
$sanitized_row[] = floatval( $value );
|
||||||
|
} else {
|
||||||
|
$sanitized_row[] = sanitize_text_field( $value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sanitized['label_values'][] = $sanitized_row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sanitized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export all metrics to JSON.
|
||||||
|
*
|
||||||
|
* @return string JSON string.
|
||||||
|
*/
|
||||||
|
public function export(): string {
|
||||||
|
$metrics = $this->get_all();
|
||||||
|
|
||||||
|
$export_data = array(
|
||||||
|
'version' => self::EXPORT_VERSION,
|
||||||
|
'plugin_version' => WP_PROMETHEUS_VERSION,
|
||||||
|
'exported_at' => gmdate( 'c' ),
|
||||||
|
'site_url' => home_url(),
|
||||||
|
'metrics' => array_values( $metrics ),
|
||||||
|
);
|
||||||
|
|
||||||
|
return wp_json_encode( $export_data, JSON_PRETTY_PRINT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import metrics from JSON.
|
||||||
|
*
|
||||||
|
* @param string $json JSON string.
|
||||||
|
* @param string $mode Import mode: 'skip', 'overwrite', or 'rename'.
|
||||||
|
* @return array Result with 'imported', 'skipped', 'errors' counts.
|
||||||
|
* @throws \InvalidArgumentException If JSON is invalid.
|
||||||
|
*/
|
||||||
|
public function import( string $json, string $mode = 'skip' ): array {
|
||||||
|
$data = json_decode( $json, true );
|
||||||
|
|
||||||
|
if ( json_last_error() !== JSON_ERROR_NONE ) {
|
||||||
|
throw new \InvalidArgumentException( __( 'Invalid JSON format.', 'wp-prometheus' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( $data['metrics'] ) || ! is_array( $data['metrics'] ) ) {
|
||||||
|
throw new \InvalidArgumentException( __( 'No metrics found in import file.', 'wp-prometheus' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = array(
|
||||||
|
'imported' => 0,
|
||||||
|
'skipped' => 0,
|
||||||
|
'errors' => 0,
|
||||||
|
'messages' => array(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$existing_metrics = $this->get_all();
|
||||||
|
$existing_names = array_column( $existing_metrics, 'name', 'id' );
|
||||||
|
|
||||||
|
foreach ( $data['metrics'] as $metric ) {
|
||||||
|
if ( empty( $metric['name'] ) ) {
|
||||||
|
$result['errors']++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for name collision.
|
||||||
|
$name_exists = in_array( $metric['name'], $existing_names, true );
|
||||||
|
|
||||||
|
if ( $name_exists ) {
|
||||||
|
if ( 'skip' === $mode ) {
|
||||||
|
$result['skipped']++;
|
||||||
|
$result['messages'][] = sprintf(
|
||||||
|
/* translators: %s: Metric name */
|
||||||
|
__( 'Skipped "%s" (already exists).', 'wp-prometheus' ),
|
||||||
|
$metric['name']
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
} elseif ( 'rename' === $mode ) {
|
||||||
|
// Generate unique name.
|
||||||
|
$base_name = $metric['name'];
|
||||||
|
$counter = 1;
|
||||||
|
while ( in_array( $metric['name'], $existing_names, true ) ) {
|
||||||
|
$metric['name'] = $base_name . '_imported_' . $counter;
|
||||||
|
$counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 'overwrite' mode: continue with same name, will overwrite below.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear ID to create new metric (unless overwriting).
|
||||||
|
if ( 'overwrite' === $mode && $name_exists ) {
|
||||||
|
// Find existing ID by name.
|
||||||
|
$metric['id'] = array_search( $metric['name'], $existing_names, true );
|
||||||
|
} else {
|
||||||
|
unset( $metric['id'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->save( $metric );
|
||||||
|
$result['imported']++;
|
||||||
|
|
||||||
|
// Update existing names for subsequent collision checks.
|
||||||
|
$existing_names = array_column( $this->get_all(), 'name', 'id' );
|
||||||
|
} catch ( \InvalidArgumentException $e ) {
|
||||||
|
$result['errors']++;
|
||||||
|
$result['messages'][] = sprintf(
|
||||||
|
/* translators: 1: Metric name, 2: Error message */
|
||||||
|
__( 'Error importing "%1$s": %2$s', 'wp-prometheus' ),
|
||||||
|
$metric['name'],
|
||||||
|
$e->getMessage()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register custom metrics with the Collector.
|
||||||
|
*
|
||||||
|
* @param Collector $collector The metrics collector instance.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register_with_collector( Collector $collector ): void {
|
||||||
|
$metrics = $this->get_all();
|
||||||
|
|
||||||
|
foreach ( $metrics as $metric ) {
|
||||||
|
if ( empty( $metric['enabled'] ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$gauge = $collector->register_gauge(
|
||||||
|
$metric['name'],
|
||||||
|
$metric['help'],
|
||||||
|
$metric['labels'] ?? array()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set values based on value type.
|
||||||
|
if ( 'option' === $metric['value_type'] ) {
|
||||||
|
// Option-based metric: read from WordPress option.
|
||||||
|
$option_name = $metric['value_config']['option_name'] ?? '';
|
||||||
|
$default = $metric['value_config']['default'] ?? 0;
|
||||||
|
|
||||||
|
if ( ! empty( $option_name ) ) {
|
||||||
|
$value = get_option( $option_name, $default );
|
||||||
|
$value = is_numeric( $value ) ? floatval( $value ) : $default;
|
||||||
|
|
||||||
|
// For option-based, use empty labels if no labels defined.
|
||||||
|
$label_values = array();
|
||||||
|
if ( ! empty( $metric['labels'] ) && ! empty( $metric['label_values'][0] ) ) {
|
||||||
|
// Use first row of labels (without the value).
|
||||||
|
$label_values = array_slice( $metric['label_values'][0], 0, count( $metric['labels'] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$gauge->set( $value, $label_values );
|
||||||
|
}
|
||||||
|
} elseif ( 'static' === $metric['value_type'] ) {
|
||||||
|
// Static metric: use predefined label values.
|
||||||
|
if ( ! empty( $metric['label_values'] ) ) {
|
||||||
|
foreach ( $metric['label_values'] as $row ) {
|
||||||
|
if ( ! is_array( $row ) || count( $row ) < 1 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last element is the value.
|
||||||
|
$value = array_pop( $row );
|
||||||
|
|
||||||
|
// Remaining elements are label values.
|
||||||
|
$gauge->set( floatval( $value ), $row );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No labels, single value.
|
||||||
|
$gauge->set( 0, array() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch ( \Exception $e ) {
|
||||||
|
// Log error but don't break metric collection.
|
||||||
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||||
|
error_log( sprintf( 'WP Prometheus: Failed to register custom metric "%s": %s', $metric['name'], $e->getMessage() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.2.2
|
* Version: 0.3.0
|
||||||
* Requires at least: 6.4
|
* Requires at least: 6.4
|
||||||
* Requires PHP: 8.3
|
* Requires PHP: 8.3
|
||||||
* Author: Marco Graetsch
|
* Author: Marco Graetsch
|
||||||
@@ -26,7 +26,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
define( 'WP_PROMETHEUS_VERSION', '0.2.2' );
|
define( 'WP_PROMETHEUS_VERSION', '0.3.0' );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin file path.
|
* Plugin file path.
|
||||||
|
|||||||
Reference in New Issue
Block a user