Files
wp-prometheus/src/Metrics/Collector.php

289 lines
7.6 KiB
PHP
Raw Normal View History

<?php
/**
* Metrics collector class.
*
* @package WP_Prometheus
*/
namespace Magdev\WpPrometheus\Metrics;
use Prometheus\CollectorRegistry;
use Prometheus\Storage\InMemory;
use Prometheus\RenderTextFormat;
// Prevent direct file access.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Collector class.
*
* Collects and manages Prometheus metrics.
*/
class Collector {
/**
* Prometheus collector registry.
*
* @var CollectorRegistry
*/
private CollectorRegistry $registry;
/**
* Metric namespace.
*
* @var string
*/
private string $namespace = 'wordpress';
/**
* Constructor.
*/
public function __construct() {
$this->registry = new CollectorRegistry( new InMemory() );
}
/**
* Get the collector registry.
*
* @return CollectorRegistry
*/
public function get_registry(): CollectorRegistry {
return $this->registry;
}
/**
* Get the metric namespace.
*
* @return string
*/
public function get_namespace(): string {
return $this->namespace;
}
/**
* Collect all enabled metrics.
*
* @return void
*/
public function collect(): void {
$enabled_metrics = get_option( 'wp_prometheus_enabled_metrics', array() );
// Always collect WordPress info.
if ( in_array( 'wordpress_info', $enabled_metrics, true ) ) {
$this->collect_wordpress_info();
}
// Collect user metrics.
if ( in_array( 'wordpress_users_total', $enabled_metrics, true ) ) {
$this->collect_users_total();
}
// Collect posts metrics.
if ( in_array( 'wordpress_posts_total', $enabled_metrics, true ) ) {
$this->collect_posts_total();
}
// Collect comments metrics.
if ( in_array( 'wordpress_comments_total', $enabled_metrics, true ) ) {
$this->collect_comments_total();
}
// Collect plugins metrics.
if ( in_array( 'wordpress_plugins_total', $enabled_metrics, true ) ) {
$this->collect_plugins_total();
}
/**
* Fires after default metrics are collected.
*
* @param Collector $collector The metrics collector instance.
*/
do_action( 'wp_prometheus_collect_metrics', $this );
}
/**
* Render metrics in Prometheus text format.
*
* @return string
*/
public function render(): string {
$this->collect();
$renderer = new RenderTextFormat();
return $renderer->render( $this->registry->getMetricFamilySamples() );
}
/**
* Collect WordPress info metric.
*
* @return void
*/
private function collect_wordpress_info(): void {
$gauge = $this->registry->getOrRegisterGauge(
$this->namespace,
'info',
'WordPress installation information',
array( 'version', 'php_version', 'multisite' )
);
$gauge->set(
1,
array(
get_bloginfo( 'version' ),
PHP_VERSION,
is_multisite() ? 'yes' : 'no',
)
);
}
/**
* Collect total users metric.
*
* @return void
*/
private function collect_users_total(): void {
$gauge = $this->registry->getOrRegisterGauge(
$this->namespace,
'users_total',
'Total number of WordPress users',
array( 'role' )
);
$user_count = count_users();
foreach ( $user_count['avail_roles'] as $role => $count ) {
$gauge->set( $count, array( $role ) );
}
}
/**
* Collect total posts metric.
*
* @return void
*/
private function collect_posts_total(): void {
$gauge = $this->registry->getOrRegisterGauge(
$this->namespace,
'posts_total',
'Total number of posts by type and status',
array( 'post_type', 'status' )
);
$post_types = get_post_types( array( 'public' => true ) );
foreach ( $post_types as $post_type ) {
$counts = wp_count_posts( $post_type );
foreach ( get_object_vars( $counts ) as $status => $count ) {
if ( $count > 0 ) {
$gauge->set( (int) $count, array( $post_type, $status ) );
}
}
}
}
/**
* Collect total comments metric.
*
* @return void
*/
private function collect_comments_total(): void {
$gauge = $this->registry->getOrRegisterGauge(
$this->namespace,
'comments_total',
'Total number of comments by status',
array( 'status' )
);
$comments = wp_count_comments();
$statuses = array(
'approved' => $comments->approved,
'moderated' => $comments->moderated,
'spam' => $comments->spam,
'trash' => $comments->trash,
'total_comments' => $comments->total_comments,
);
foreach ( $statuses as $status => $count ) {
$gauge->set( (int) $count, array( $status ) );
}
}
/**
* Collect total plugins metric.
*
* @return void
*/
private function collect_plugins_total(): void {
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
$gauge = $this->registry->getOrRegisterGauge(
$this->namespace,
'plugins_total',
'Total number of plugins by status',
array( 'status' )
);
$all_plugins = get_plugins();
$active_plugins = get_option( 'active_plugins', array() );
$gauge->set( count( $all_plugins ), array( 'installed' ) );
$gauge->set( count( $active_plugins ), array( 'active' ) );
$gauge->set( count( $all_plugins ) - count( $active_plugins ), array( 'inactive' ) );
}
/**
* Register a custom gauge metric.
*
* @param string $name Metric name.
* @param string $help Metric description.
* @param array $labels Label names.
* @return \Prometheus\Gauge
*/
public function register_gauge( string $name, string $help, array $labels = array() ): \Prometheus\Gauge {
return $this->registry->getOrRegisterGauge(
$this->namespace,
$name,
$help,
$labels
);
}
/**
* Register a custom counter metric.
*
* @param string $name Metric name.
* @param string $help Metric description.
* @param array $labels Label names.
* @return \Prometheus\Counter
*/
public function register_counter( string $name, string $help, array $labels = array() ): \Prometheus\Counter {
return $this->registry->getOrRegisterCounter(
$this->namespace,
$name,
$help,
$labels
);
}
/**
* Register a custom histogram metric.
*
* @param string $name Metric name.
* @param string $help Metric description.
* @param array $labels Label names.
* @param array|null $buckets Histogram buckets.
* @return \Prometheus\Histogram
*/
public function register_histogram( string $name, string $help, array $labels = array(), ?array $buckets = null ): \Prometheus\Histogram {
return $this->registry->getOrRegisterHistogram(
$this->namespace,
$name,
$help,
$labels,
$buckets
);
}
}