Server IP : 172.67.157.199 / Your IP : 18.119.118.206 [ Web Server : Apache System : Linux b70eb322-3aee-0c53-7c82-0db91281f2c6.secureserver.net 6.1.90-1.el9.elrepo.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 2 12:09:22 EDT 2024 x86_64 User : root ( 0) PHP Version : 8.0.30.2 Disable Function : NONE Domains : 0 Domains MySQL : ON | cURL : ON | WGET : ON | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/wp-content/mu-plugins/object-cache-pro/src/Plugin/ |
Upload File : |
<?php /** * Copyright © 2019-2024 Rhubarb Tech Inc. All Rights Reserved. * * The Object Cache Pro Software and its related materials are property and confidential * information of Rhubarb Tech Inc. Any reproduction, use, distribution, or exploitation * of the Object Cache Pro Software and its related materials, in whole or in part, * is strictly forbidden unless prior permission is obtained from Rhubarb Tech Inc. * * In addition, any reproduction, use, distribution, or exploitation of the Object Cache Pro * Software and its related materials, in whole or in part, is subject to the End-User License * Agreement accessible in the included `LICENSE` file, or at: https://objectcache.pro/eula */ declare(strict_types=1); namespace RedisCachePro\Plugin; use const RedisCachePro\Version; use RedisCachePro\ObjectCaches\MeasuredObjectCacheInterface; /** * @mixin \RedisCachePro\Plugin */ trait Analytics { /** * Boot analytics component. * * @return void */ public function bootAnalytics() { global $wp_object_cache; add_action('rest_api_init', [new Api\Analytics, 'register_routes']); if (! $this->analyticsEnabled()) { return; } if (! $wp_object_cache instanceof MeasuredObjectCacheInterface) { return; } add_action('wp_footer', [$this, 'shouldPrintMetricsComment']); add_action('wp_body_open', [$this, 'shouldPrintMetricsComment']); add_action('login_head', [$this, 'shouldPrintMetricsComment']); add_action('in_admin_header', [$this, 'shouldPrintMetricsComment']); add_action('rss_tag_pre', [$this, 'shouldPrintMetricsComment']); add_action('shutdown', [$this, 'maybePrintMetricsComment'], PHP_INT_MAX); add_action('objectcache_prune_analytics', [$this, 'pruneAnalytics']); if (wp_doing_cron() && ! wp_next_scheduled('objectcache_prune_analytics')) { wp_schedule_event(time(), 'hourly', 'objectcache_prune_analytics'); } } /** * Whether analytics are enabled. * * @return bool */ public function analyticsEnabled() { return $this->config->analytics->enabled; } /** * Callback for the scheduled `objectcache_prune_analytics` hook. * * @return void */ public function pruneAnalytics() { global $wp_object_cache; $wp_object_cache->pruneMeasurements(); } /** * Print the request's metrics as HTML comment. * * @return bool|void */ public function shouldPrintMetricsComment() { static $shouldPrint; /** * Filters whether the analytics footnote is printed. * * @param bool $omit Whether to omit printing the analytics footnote. */ if ((bool) apply_filters('objectcache_omit_analytics_footnote', false)) { return; } if (doing_action('shutdown')) { return $shouldPrint; } $shouldPrint = true; } /** * Print the request's metrics as HTML comment. * * @return void */ public function maybePrintMetricsComment() { global $wp_object_cache; if ( ! \WP_DEBUG && ! $this->config->debug && ! $this->config->analytics->footnote ) { return; } if (! $this->shouldPrintMetricsComment()) { return; } if (is_robots() || is_trackback()) { return; } if ( (defined('\WP_CLI') && constant('\WP_CLI')) || (defined('\REST_REQUEST') && constant('\REST_REQUEST')) || (defined('\XMLRPC_REQUEST') && constant('\XMLRPC_REQUEST')) || (defined('\DOING_AJAX') && constant('\DOING_AJAX')) || (defined('\DOING_CRON') && constant('\DOING_CRON')) || (defined('\DOING_AUTOSAVE') && constant('\DOING_AUTOSAVE')) || (function_exists('wp_is_json_request') && wp_is_json_request()) || (function_exists('wp_is_jsonp_request') && wp_is_jsonp_request()) ) { return; } if ($this->incompatibleContentType()) { return; } if (! $measurement = $wp_object_cache->requestMeasurement()) { return; } printf( "\n<!-- plugin=%s client=%s %s -->\n", 'object-cache-pro', strtolower($wp_object_cache->clientName()), (string) $measurement ); } /** * Enqueues the analytics assets. * * @return void */ public function enqueueAnalyticsAssets() { $this->enqueueChartsAssets(); $script = $this->asset('js/metrics.js'); \wp_register_script('objectcache-analytics', $script, ['jquery', 'objectcache-charts'], Version); \wp_enqueue_script('objectcache-analytics'); if (! $script) { \wp_add_inline_script('objectcache-analytics', $this->inlineAsset('js/metrics.js')); } } /** * Enqueues Apex Charts. * * @link https://apexcharts.com * * @return void */ protected function enqueueChartsAssets() { $chartStyles = $this->asset('vendor/apexcharts/apexcharts.min.css'); if ($chartStyles) { wp_enqueue_style('objectcache-charts', $chartStyles, [], Version); } else { wp_enqueue_style('objectcache-charts', 'https://cdnjs.cloudflare.com/ajax/libs/apexcharts/3.33.0/apexcharts.min.css', [], null); wp_script_add_data( 'objectcache-charts', ['crossorigin', 'integrity', 'referrerpolicy'], ['anonymous', 'no-referrer', 'sha512-72LrFm5Wau6YFp7GGd7+qQJYkzRKj5UMQZ4aFuEo3WcRzO0xyAkVjK3NEw8wXjEsEG/skqvXKR5+VgOuzuqPtA=='] ); } $chartScript = $this->asset('vendor/apexcharts/apexcharts.min.js'); if ($chartScript) { wp_enqueue_script('objectcache-charts', $chartScript, [], Version); } else { wp_enqueue_script('objectcache-charts', 'https://cdnjs.cloudflare.com/ajax/libs/apexcharts/3.33.0/apexcharts.min.js', [], null); wp_script_add_data( 'objectcache-charts-js', ['crossorigin', 'integrity', 'referrerpolicy'], ['anonymous', 'no-referrer', 'sha512-s4UlxRFKE4p5qoQ+YnR53ttrA3s6qSmfjAXPMpznp60NLOUYJL1O4hgRfuFq/Dk0Uiw9xrsYzZSuEY8Y3gFsqw=='] ); } } /** * Whether the sent headers are incompatible with HTML comments. * * @see RedisCachePro\Plugin\Analytics::maybePrintMetricsComment() * * @return bool */ protected function incompatibleContentType() { $jsonContentType = static function ($headers) { foreach ($headers as $header => $value) { if (stripos((string) $header, 'content-type') === false) { continue; } if (stripos((string) $value, '/json') === false) { continue; } return true; } return false; }; if (function_exists('headers_list')) { $headers = []; foreach (headers_list() as $header) { [$name, $value] = explode(':', $header); $headers[$name] = $value; } if ($jsonContentType($headers)) { return true; } } if (function_exists('apache_response_headers')) { if ($headers = apache_response_headers()) { return $jsonContentType($headers); } } return false; } /** * Adds placeholder for the new combined charts. * * @return array<string, mixed> */ public function comboMetrics() { $metrics = [ 'requests' => [ 'title' => 'Requests', 'description' => 'The amount of times the cache data was and wasn’t already cached in memory and the in-memory hits-to-misses ratio.', 'group' => 'wp', 'type' => [ 'hits' => 'integer', 'misses' => 'integer', 'hit-ratio' => 'ratio', ], 'labels' => [ 'hits' => 'Hits', 'misses' => 'Misses', 'hit-ratio' => 'Hit ratio', ], ], 'commands' => [ 'title' => 'Commands', 'description' => 'The number of times the cache read from and wrote to the datastore.', 'group' => 'wp', 'type' => [ 'store-reads' => 'integer', 'store-writes' => 'integer', ], 'labels' => [ 'store-reads' => 'Datastore reads', 'store-writes' => 'Datastore writes', ], ], 'response-times' => [ 'title' => 'Response Times', 'description' => 'The amount of time (ms) WordPress took to render the request and waited for the datastore to respond.', 'group' => 'wp', 'type' => [ 'ms-total' => 'time', 'ms-cache' => 'time', 'ms-cache-ratio' => 'ratio', ], 'labels' => [ 'ms-total' => 'Request', 'ms-cache' => 'Cache', 'ms-cache-ratio' => 'Cache ratio', ], ], 'redis-requests' => [ 'title' => 'Requests', 'description' => 'Number of successful and failed key lookups and the hits-to-misses ratio.', 'group' => 'redis', 'type' => [ 'redis-hits' => 'integer', 'redis-misses' => 'integer', 'redis-hit-ratio' => 'ratio', ], 'labels' => [ 'redis-hits' => 'Hits', 'redis-misses' => 'Misses', 'redis-hit-ratio' => 'Hit ratio', ], ], 'redis-memory' => [ 'title' => 'Memory', 'description' => 'The ratio of memory allocated by Redis compared to the maximum amount of memory allocatable by Redis.', 'group' => 'redis', 'type' => [ 'redis-used-memory' => 'bytes', 'redis-memory-ratio' => 'ratio', 'redis-memory-fragmentation-ratio' => 'ratio', ], 'labels' => [ 'redis-used-memory' => 'Used memory', 'redis-memory-ratio' => 'Memory ratio', 'redis-memory-fragmentation-ratio' => 'Fragmentation ratio', ], ], ]; if (! $this->diagnostics()->maxMemory()) { unset($metrics['redis-memory']['type']['redis-memory-ratio']); } if ($this->diagnostics()->usingRelayCache()) { $metrics['relay-requests'] = [ 'title' => 'Requests', 'description' => 'Number of successful and failed key lookups and the hits-to-misses ratio.', 'group' => 'relay', 'type' => [ 'relay-hits' => 'integer', 'relay-misses' => 'integer', 'relay-hit-ratio' => 'ratio', ], 'labels' => [ 'relay-hits' => 'Hits', 'relay-misses' => 'Misses', 'relay-hit-ratio' => 'Hit ratio', ], ]; $metrics['relay-memory'] = [ 'title' => 'Memory', 'description' => 'The ratio between the amount of bytes pointing to live objects including metadata and the total amount of memory mapped into the allocator.', 'group' => 'relay', 'type' => [ 'relay-memory-total' => 'integer', 'relay-memory-used' => 'integer', 'relay-memory-ratio' => 'ratio', ], 'labels' => [ 'relay-memory-total' => 'Total memory', 'relay-memory-used' => 'Used memory', 'relay-memory-ratio' => 'Memory ratio', ], ]; } return $metrics; } }