PluginProbe
OPcache Manager / 3.3.0
OPcache Manager v3.3.0
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.2.0 1.3.0 1.3.1 1.3.2 2.0.0 2.1.0 2.10.0 2.11.0 2.12.0 2.13.0 2.13.1 2.14.0 2.2.0 2.3.0 2.3.1 2.3.2 2.4.0 2.5.0 2.6.0 All 36 releases
opcache-manager / includes / features / class-capture.php

class-capture.php in OPcache Manager 3.3.0, at includes/features/class-capture.php

322 lines 14.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OPcacheManager capture
4 *
5 * Handles all captures operations.
6 *
7 * @package Features
8 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
9 * @since 1.0.0
10 */
11
12 namespace OPcacheManager\Plugin\Feature;
13
14 use OPcacheManager\System\Cache;
15 use OPcacheManager\System\Logger;
16 use OPcacheManager\System\OPcache;
17 use OPcacheManager\Plugin\Feature\Schema;
18
19 /**
20 * Define the captures functionality.
21 *
22 * Handles all captures operations.
23 *
24 * @package Features
25 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
26 * @since 1.0.0
27 */
28 class Capture {
29
30 /**
31 * Delta time.
32 *
33 * @since 1.0.0
34 * @var integer $delta The authorized delta time in seconds.
35 */
36 public static $delta = 90;
37
38 /**
39 * Initialize the class and set its properties.
40 *
41 * @since 1.0.0
42 */
43 public function __construct() {
44 }
45
46 /**
47 * Add a new 5 minutes interval capacity to the WP cron feature.
48 *
49 * @since 1.0.0
50 */
51 public static function add_cron_05_minutes_interval( $schedules ) {
52 $schedules['five_minutes'] = [
53 'interval' => 300,
54 'display' => __( 'Every five minutes', 'opcache-manager' ),
55 ];
56 return $schedules;
57 }
58
59 /**
60 * Check status and record it if needed.
61 *
62 * @since 1.0.0
63 */
64 public static function check() {
65 $schema = new Schema();
66 $record = $schema->init_record();
67 $time = time();
68 if ( function_exists( 'opcache_get_status' ) && ! OPcache::is_restricted() ) {
69 $cache_id = '/Data/LastCheck';
70 $old = Cache::get_global( $cache_id );
71 if ( ! isset( $old ) ) {
72 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( 'No OPcache transient.' );
73 } elseif ( ! array_key_exists( 'timestamp', $old ) ) {
74 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( 'No OPcache timestamp.' );
75 } elseif ( 300 - self::$delta > $time - $old['timestamp'] ) {
76 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( sprintf( 'Delta time too short: %d sec. Launching recycling process.', $time - $old['timestamp'] ) );
77 } elseif ( 300 + self::$delta < $time - $old['timestamp'] ) {
78 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( sprintf( 'Delta time too long: %d sec. Launching recycling process.', $time - $old['timestamp'] ) );
79 }
80 if ( isset( $old ) && array_key_exists( 'timestamp', $old ) && ( 300 + self::$delta > $time - $old['timestamp'] ) ) {
81 try {
82 $restart = false;
83 $value = [];
84 $value['raw'] = opcache_get_status( false );
85 $value['timestamp'] = $time;
86 $record['status'] = 'enabled';
87 // Trying to figure out the status.
88 if ( array_key_exists( 'cache_full', $value['raw'] ) && (bool) $value['raw']['cache_full'] ) {
89 $record['status'] = 'cache_full';
90 }
91 if ( array_key_exists( 'restart_pending', $value['raw'] ) && (bool) $value['raw']['restart_pending'] ) {
92 $record['status'] = 'restart_pending';
93 }
94 if ( array_key_exists( 'restart_in_progress', $value['raw'] ) && (bool) $value['raw']['restart_in_progress'] ) {
95 $record['status'] = 'restart_in_progress';
96 }
97 $warmup_timestamp = Cache::get_global( '/Data/WarmupTimestamp' );
98 if ( false !== $warmup_timestamp ) {
99 if ( 300 > $time - $warmup_timestamp ) {
100 $record['status'] = 'warmup';
101 }
102 }
103 $reset_warmup_timestamp = Cache::get_global( '/Data/ResetWarmupTimestamp' );
104 if ( false !== $reset_warmup_timestamp ) {
105 if ( 300 > $time - $reset_warmup_timestamp ) {
106 $record['status'] = 'reset_warmup';
107 }
108 }
109 // Trying to figure out the restart type.
110 if ( array_key_exists( 'opcache_statistics', $old['raw'] ) && array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'oom_restarts', $old['raw']['opcache_statistics'] ) && array_key_exists( 'oom_restarts', $value['raw']['opcache_statistics'] ) ) {
111 if ( (int) $old['raw']['opcache_statistics']['oom_restarts'] !== (int) $value['raw']['opcache_statistics']['oom_restarts'] ) {
112 $restart = true;
113 $record['reset'] = 'oom';
114 }
115 }
116 if ( array_key_exists( 'opcache_statistics', $old['raw'] ) && array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'hash_restarts', $old['raw']['opcache_statistics'] ) && array_key_exists( 'hash_restarts', $value['raw']['opcache_statistics'] ) ) {
117 if ( (int) $old['raw']['opcache_statistics']['hash_restarts'] !== (int) $value['raw']['opcache_statistics']['hash_restarts'] ) {
118 $restart = true;
119 $record['reset'] = 'hash';
120 }
121 }
122 if ( array_key_exists( 'opcache_statistics', $old['raw'] ) && array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'manual_restarts', $old['raw']['opcache_statistics'] ) && array_key_exists( 'manual_restarts', $value['raw']['opcache_statistics'] ) ) {
123 if ( (int) $old['raw']['opcache_statistics']['manual_restarts'] !== (int) $value['raw']['opcache_statistics']['manual_restarts'] ) {
124 $restart = true;
125 $record['reset'] = 'manual';
126 }
127 }
128 if ( array_key_exists( 'memory_usage', $value['raw'] ) && array_key_exists( 'used_memory', $value['raw']['memory_usage'] ) ) {
129 $record['mem_used'] = (int) $value['raw']['memory_usage']['used_memory'];
130 }
131 if ( array_key_exists( 'memory_usage', $value['raw'] ) && array_key_exists( 'wasted_memory', $value['raw']['memory_usage'] ) ) {
132 $record['mem_wasted'] = (int) $value['raw']['memory_usage']['wasted_memory'];
133 }
134 if ( array_key_exists( 'memory_usage', $value['raw'] ) && array_key_exists( 'free_memory', $value['raw']['memory_usage'] ) ) {
135 $free = (int) $value['raw']['memory_usage']['free_memory'];
136 } else {
137 $free = 0;
138 }
139 $record['mem_total'] = $free + $record['mem_used'] + $record['mem_wasted'];
140 if ( array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'max_cached_keys', $value['raw']['opcache_statistics'] ) ) {
141 $record['key_total'] = (int) $value['raw']['opcache_statistics']['max_cached_keys'];
142 }
143 if ( array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'num_cached_keys', $value['raw']['opcache_statistics'] ) ) {
144 $record['key_used'] = (int) $value['raw']['opcache_statistics']['num_cached_keys'];
145 }
146 if ( array_key_exists( 'interned_strings_usage', $value['raw'] ) && array_key_exists( 'buffer_size', $value['raw']['interned_strings_usage'] ) ) {
147 $record['buf_total'] = (int) $value['raw']['interned_strings_usage']['buffer_size'];
148 }
149 if ( array_key_exists( 'interned_strings_usage', $value['raw'] ) && array_key_exists( 'used_memory', $value['raw']['interned_strings_usage'] ) ) {
150 $record['buf_used'] = (int) $value['raw']['interned_strings_usage']['used_memory'];
151 }
152 if ( $restart ) {
153 if ( array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'hits', $value['raw']['opcache_statistics'] ) ) {
154 $record['hit'] = (int) $value['raw']['opcache_statistics']['hits'];
155 }
156 if ( array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'misses', $value['raw']['opcache_statistics'] ) ) {
157 $record['miss'] = (int) $value['raw']['opcache_statistics']['misses'];
158 }
159 } else {
160 if ( array_key_exists( 'opcache_statistics', $old['raw'] ) && array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'hits', $old['raw']['opcache_statistics'] ) && array_key_exists( 'hits', $value['raw']['opcache_statistics'] ) ) {
161 $record['hit'] = (int) $value['raw']['opcache_statistics']['hits'] - (int) $old['raw']['opcache_statistics']['hits'];
162 }
163 if ( array_key_exists( 'opcache_statistics', $old['raw'] ) && array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'misses', $old['raw']['opcache_statistics'] ) && array_key_exists( 'misses', $value['raw']['opcache_statistics'] ) ) {
164 $record['miss'] = (int) $value['raw']['opcache_statistics']['misses'] - (int) $old['raw']['opcache_statistics']['misses'];
165 }
166 }
167 if ( array_key_exists( 'opcache_statistics', $value['raw'] ) && array_key_exists( 'num_cached_scripts', $value['raw']['opcache_statistics'] ) ) {
168 $record['scripts'] = (int) $value['raw']['opcache_statistics']['num_cached_scripts'];
169 }
170 if ( array_key_exists( 'interned_strings_usage', $value['raw'] ) && array_key_exists( 'number_of_strings', $value['raw']['interned_strings_usage'] ) ) {
171 $record['strings'] = (int) $value['raw']['interned_strings_usage']['number_of_strings'];
172 }
173 Cache::set_global( $cache_id, $value, 'check' );
174 $schema->write_statistics_record_to_database( $record );
175 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( 'OPcache is enabled. Statistics recorded.' );
176 } catch ( \Throwable $e ) {
177 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->error( sprintf( 'Unable to query OPcache status: %s.', $e->getMessage() ), [ 'code' => $e->getCode() ] );
178 }
179 } elseif ( isset( $old ) && array_key_exists( 'timestamp', $old ) && ( 300 - self::$delta > $time - $old['timestamp'] ) ) {
180 // What to do when delta is less 59 sec ?
181 } else {
182 try {
183 $value = [];
184 $value['raw'] = opcache_get_status( false );
185 $value['timestamp'] = $time;
186 Cache::set_global( $cache_id, $value, 'check' );
187 $record['status'] = 'recycle_in_progress';
188 $schema->write_statistics_record_to_database( $record );
189 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( 'OPcache is enabled. Recovery cycle.' );
190 } catch ( \Throwable $e ) {
191 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->error( sprintf( 'Unable to query OPcache status: %s.', $e->getMessage() ), [ 'code' => $e->getCode() ] );
192 }
193 }
194 } else {
195 $schema->write_statistics_record_to_database( $record );
196 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( 'OPcache is disabled. No statistics to record.' );
197 }
198 }
199
200 /**
201 * Publish metrics.
202 *
203 * @since 2.3.0
204 */
205 public static function metrics() {
206 if ( function_exists( 'opcache_get_status' ) && ! OPcache::is_restricted() ) {
207 $span = \DecaLog\Engine::tracesLogger( OPCM_SLUG )->startSpan( 'Metrics collation', DECALOG_SPAN_PLUGINS_LOAD );
208 $cache_id = 'metrics/lastcheck';
209 $metrics = Cache::get_global( $cache_id );
210 if ( ! isset( $metrics ) ) {
211 try {
212 $value = opcache_get_status( false );
213 if ( array_key_exists( 'memory_usage', $value ) && array_key_exists( 'used_memory', $value['memory_usage'] ) ) {
214 $used = (int) $value['memory_usage']['used_memory'];
215 } else {
216 $used = 0;
217 }
218 if ( array_key_exists( 'memory_usage', $value ) && array_key_exists( 'wasted_memory', $value['memory_usage'] ) ) {
219 $wasted = (int) $value['memory_usage']['wasted_memory'];
220 } else {
221 $wasted = 0;
222 }
223 if ( array_key_exists( 'memory_usage', $value ) && array_key_exists( 'free_memory', $value['memory_usage'] ) ) {
224 $free = (int) $value['memory_usage']['free_memory'];
225 } else {
226 $free = 0;
227 }
228 $total = $free + $used + $wasted;
229 if ( 0 < $total ) {
230 $metrics['mem'] = $used / $total;
231 $metrics['wasted'] = $wasted / $total;
232 } else {
233 $metrics['mem'] = 0.0;
234 $metrics['wasted'] = 0.0;
235 }
236 if ( array_key_exists( 'opcache_statistics', $value ) && array_key_exists( 'max_cached_keys', $value['opcache_statistics'] ) ) {
237 $key_total = (int) $value['opcache_statistics']['max_cached_keys'];
238 } else {
239 $key_total = 0;
240 }
241 if ( array_key_exists( 'opcache_statistics', $value ) && array_key_exists( 'num_cached_keys', $value['opcache_statistics'] ) ) {
242 $key_used = (int) $value['opcache_statistics']['num_cached_keys'];
243 } else {
244 $key_used = 0;
245 }
246 if ( 0 < $key_total ) {
247 $metrics['key'] = $key_used / $key_total;
248 } else {
249 $metrics['key'] = 0.0;
250 }
251 if ( array_key_exists( 'interned_strings_usage', $value ) && array_key_exists( 'buffer_size', $value['interned_strings_usage'] ) ) {
252 $buf_total = (int) $value['interned_strings_usage']['buffer_size'];
253 } else {
254 $buf_total = 0;
255 }
256 if ( array_key_exists( 'interned_strings_usage', $value ) && array_key_exists( 'used_memory', $value['interned_strings_usage'] ) ) {
257 $buf_used = (int) $value['interned_strings_usage']['used_memory'];
258 } else {
259 $buf_used = 0;
260 }
261 if ( 0 < $buf_total ) {
262 $metrics['buffer'] = $buf_used / $buf_total;
263 } else {
264 $metrics['buffer'] = 0.0;
265 }
266 if ( array_key_exists( 'opcache_statistics', $value ) && array_key_exists( 'hits', $value['opcache_statistics'] ) ) {
267 $hit = (int) $value['opcache_statistics']['hits'];
268 } else {
269 $hit = 0;
270 }
271 if ( array_key_exists( 'opcache_statistics', $value ) && array_key_exists( 'misses', $value['opcache_statistics'] ) ) {
272 $miss = (int) $value['opcache_statistics']['misses'];
273 } else {
274 $miss = 0;
275 }
276 $total = $hit + $miss;
277 if ( 0 < $total ) {
278 $metrics['hit_ratio'] = $hit / $total;
279 } else {
280 $metrics['hit_ratio'] = 0.0;
281 }
282 if ( array_key_exists( 'opcache_statistics', $value ) && array_key_exists( 'num_cached_scripts', $value['opcache_statistics'] ) ) {
283 $metrics['scripts'] = (int) $value['opcache_statistics']['num_cached_scripts'];
284 } else {
285 $metrics['scripts'] = 0;
286 }
287 Cache::set_global( $cache_id, $metrics, 'metrics' );
288 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( 'OPcache is enabled. Statistics recorded.' );
289 } catch ( \Throwable $e ) {
290 $metrics = null;
291 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->error( sprintf( 'Unable to query OPcache status: %s.', $e->getMessage() ), [ 'code' => $e->getCode() ] );
292 }
293 }
294 if ( isset( $metrics ) ) {
295 $monitor = \DecaLog\Engine::metricsLogger( OPCM_SLUG );
296 if ( array_key_exists( 'mem', $metrics ) ) {
297 $monitor->createProdGauge( 'memory_saturation', $metrics['mem'], 'OPcache used memory - [percent]' );
298 }
299 if ( array_key_exists( 'wasted', $metrics ) ) {
300 $monitor->createProdGauge( 'memory_wasted', $metrics['wasted'], 'OPcache wasted memory - [percent]' );
301 }
302 if ( array_key_exists( 'key', $metrics ) ) {
303 $monitor->createProdGauge( 'key_saturation', $metrics['key'], 'OPcache used keys - [percent]' );
304 }
305 if ( array_key_exists( 'buffer', $metrics ) ) {
306 $monitor->createProdGauge( 'buffer_saturation', $metrics['buffer'], 'OPcache used buffers - [percent]' );
307 }
308 if ( array_key_exists( 'hit_ratio', $metrics ) ) {
309 $monitor->createProdGauge( 'hit_ratio', $metrics['hit_ratio'], 'OPcache hit ratio - [percent]' );
310 }
311 if ( array_key_exists( 'scripts', $metrics ) ) {
312 $monitor->createProdGauge( 'script_total', $metrics['scripts'], 'Number of cached scripts - [count]' );
313 }
314 }
315 \DecaLog\Engine::tracesLogger( OPCM_SLUG )->endSpan( $span );
316 } else {
317 \DecaLog\Engine::eventsLogger( OPCM_SLUG )->debug( 'OPcache is disabled. No metrics to collate.' );
318 }
319 }
320
321 }
322