get_redis_status() && method_exists( $wp_object_cache, 'info' ) && method_exists( $wp_object_cache, 'redis_instance' ); } /** * Retrieves metrics max time * * @return int */ public static function max_time() { if ( defined( 'WP_REDIS_METRICS_MAX_TIME' ) ) { return (int) WP_REDIS_METRICS_MAX_TIME; } return HOUR_IN_SECONDS; } /** * Records metrics and adds them to redis * * @return void */ public static function record() { if ( ! self::is_active() ) { return; } $metrics = new self(); $metrics->collect(); $metrics->save(); } /** * Collect metrics from object cache instance. */ public function collect() { global $wp_object_cache; $info = $wp_object_cache->info(); $this->id = substr( md5( uniqid( strval( mt_rand() ), true ) ), 12 ); $this->hits = $info->hits; $this->misses = $info->misses; $this->ratio = $info->ratio; $this->bytes = $info->bytes; $this->time = round( $info->time, 5 ); $this->calls = $info->calls; $this->timestamp = time(); } /** * Retrieves metrics from redis * * @param int $seconds Number of seconds of the oldest entry to retrieve. * @return Metrics[] */ public static function get( $seconds = null ) { global $wp_object_cache; if ( ! self::is_active() ) { return []; } if ( null === $seconds ) { $seconds = self::max_time(); } try { $raw_metrics = $wp_object_cache->redis_instance()->zrangebyscore( $wp_object_cache->build_key( 'metrics', 'redis-cache' ), time() - $seconds, time() - MINUTE_IN_SECONDS, [ 'withscores' => true ] ); } catch ( Exception $exception ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log error_log( $exception ); return []; } $metrics = []; $prefix = sprintf( 'O:%d:"%s', strlen( self::class ), self::class ); foreach ( $raw_metrics as $serialized => $timestamp ) { // Compatibility: Ignore all non serialized entries as they were used by prior versions. if ( strpos( $serialized, $prefix ) !== 0 ) { continue; } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_unserialize $metrics[] = unserialize( $serialized ); } return $metrics; } /** * Saves the current metrics to redis * * @return void */ public function save() { global $wp_object_cache; try { $wp_object_cache->redis_instance()->zadd( $wp_object_cache->build_key( 'metrics', 'redis-cache' ), $this->timestamp, // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize serialize( $this ) ); } catch ( Exception $exception ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log error_log( $exception ); } } /** * Removes recorded metrics after an hour * * @return void */ public static function discard() { global $wp_object_cache; if ( ! self::is_active() ) { return; } try { $wp_object_cache->redis_instance()->zremrangebyscore( $wp_object_cache->build_key( 'metrics', 'redis-cache' ), 0, time() - self::max_time() ); } catch ( Exception $exception ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log error_log( $exception ); } } /** * Counts the recorded metrics * * @return int */ public static function count() { global $wp_object_cache; if ( ! self::is_active() ) { return 0; } try { return $wp_object_cache->redis_instance()->zcount( $wp_object_cache->build_key( 'metrics', 'redis-cache' ), '-inf', '+inf' ); } catch ( Exception $exception ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log error_log( $exception ); return 0; } } }