2013-04-08 15:40:06 +00:00
|
|
|
<?php
|
|
|
|
|
2013-08-09 14:06:45 +00:00
|
|
|
/**
|
|
|
|
* OPcache GUI
|
2014-11-23 01:07:38 +00:00
|
|
|
*
|
2013-08-09 14:06:45 +00:00
|
|
|
* A simple but effective single-file GUI for the OPcache PHP extension.
|
2014-11-23 01:07:38 +00:00
|
|
|
*
|
2013-08-09 14:06:45 +00:00
|
|
|
* @author Andrew Collington, andy@amnuts.com
|
|
|
|
* @license MIT, http://acollington.mit-license.org/
|
|
|
|
*/
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
if (!extension_loaded('Zend OPcache')) {
|
2013-04-26 10:56:54 +00:00
|
|
|
die('The Zend OPcache extension does not appear to be installed');
|
2013-04-08 15:40:06 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
class OpCacheService
|
|
|
|
{
|
2014-11-25 13:20:33 +00:00
|
|
|
protected $data;
|
|
|
|
protected $options = [
|
|
|
|
'allow_invalidate' => true
|
|
|
|
];
|
2013-04-26 10:56:54 +00:00
|
|
|
|
2014-11-25 13:20:33 +00:00
|
|
|
private function __construct($options = [])
|
2014-11-23 01:07:38 +00:00
|
|
|
{
|
|
|
|
$this->data = $this->compileState();
|
2014-11-25 13:20:33 +00:00
|
|
|
$this->options = array_merge($this->options, $options);
|
2013-08-09 14:06:45 +00:00
|
|
|
}
|
2013-04-08 15:40:06 +00:00
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
public static function init()
|
|
|
|
{
|
|
|
|
$self = new self;
|
|
|
|
if (!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
|
|
|
|
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'
|
|
|
|
) {
|
|
|
|
echo json_encode($self->getData(@$_GET['section'] ?: null));
|
|
|
|
exit;
|
|
|
|
} else if ((isset($_GET['reset']))) {
|
|
|
|
$self->resetCache();
|
|
|
|
} else if ((isset($_GET['invalidate']))) {
|
|
|
|
$self->resetCache($_GET['invalidate']);
|
|
|
|
}
|
|
|
|
return $self;
|
|
|
|
}
|
2013-04-08 15:40:06 +00:00
|
|
|
|
2014-11-25 13:20:33 +00:00
|
|
|
public function getOption($name = null)
|
|
|
|
{
|
|
|
|
if ($name === null) {
|
|
|
|
return $this->options;
|
|
|
|
}
|
|
|
|
return (isset($this->options[$name])
|
|
|
|
? $this->options[$name]
|
|
|
|
: null
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
public function getData($section = null)
|
|
|
|
{
|
|
|
|
if ($section === null) {
|
|
|
|
return $this->data;
|
|
|
|
}
|
|
|
|
$section = strtolower($section);
|
|
|
|
return (isset($this->data[$section])
|
|
|
|
? $this->data[$section]
|
|
|
|
: null
|
|
|
|
);
|
2013-04-08 15:40:06 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
public function resetCache($file = null)
|
|
|
|
{
|
|
|
|
$success = false;
|
|
|
|
if ($file === null) {
|
|
|
|
$success = opcache_reset();
|
|
|
|
} else if (function_exists('opcache_invalidate')) {
|
|
|
|
$success = opcache_invalidate(urldecode($file), true);
|
|
|
|
}
|
|
|
|
if ($success) {
|
|
|
|
$this->compileState();
|
|
|
|
}
|
|
|
|
return $success;
|
2013-04-08 15:40:06 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
protected function compileState()
|
|
|
|
{
|
2014-11-25 13:20:33 +00:00
|
|
|
$status = opcache_get_status();
|
2014-11-23 01:07:38 +00:00
|
|
|
$config = opcache_get_configuration();
|
|
|
|
$memsize = function($size, $precision = 3, $space = false)
|
|
|
|
{
|
|
|
|
$i = 0;
|
|
|
|
$val = array(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
|
|
|
|
while (($size / 1024) > 1) {
|
|
|
|
$size /= 1024;
|
|
|
|
++$i;
|
|
|
|
}
|
|
|
|
return sprintf("%.{$precision}f%s%s", $size, (($space && $i) ? ' ' : ''), $val[$i]);
|
|
|
|
};
|
2013-04-22 12:28:29 +00:00
|
|
|
|
2014-11-25 13:20:33 +00:00
|
|
|
$files = [];
|
2014-11-23 01:07:38 +00:00
|
|
|
if (!empty($status['scripts'])) {
|
|
|
|
uasort($status['scripts'], function($a, $b) {
|
|
|
|
return $a['hits'] < $b['hits'];
|
|
|
|
});
|
2014-11-25 13:20:33 +00:00
|
|
|
foreach ($status['scripts'] as &$file) {
|
|
|
|
$file['full_path'] = str_replace('\\', '/', $file['full_path']);
|
|
|
|
$file['readable'] = [
|
|
|
|
'hits' => number_format($file['hits']),
|
|
|
|
'memory_consumption' => $memsize($file['memory_consumption'])
|
|
|
|
];
|
|
|
|
}
|
|
|
|
$files = array_values($status['scripts']);
|
2014-11-23 01:07:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$overview = array_merge(
|
|
|
|
$status['memory_usage'], $status['opcache_statistics'], [
|
|
|
|
'used_memory_percentage' => round(100 * (
|
|
|
|
($status['memory_usage']['used_memory'] + $status['memory_usage']['wasted_memory'])
|
|
|
|
/ $config['directives']['opcache.memory_consumption'])),
|
|
|
|
'hit_rate_percentage' => round($status['opcache_statistics']['opcache_hit_rate']),
|
|
|
|
'wasted_percentage' => round($status['memory_usage']['current_wasted_percentage'], 2),
|
|
|
|
'readable' => [
|
|
|
|
'total_memory' => $memsize($config['directives']['opcache.memory_consumption']),
|
|
|
|
'used_memory' => $memsize($status['memory_usage']['used_memory']),
|
|
|
|
'free_memory' => $memsize($status['memory_usage']['free_memory']),
|
|
|
|
'wasted_memory' => $memsize($status['memory_usage']['wasted_memory']),
|
|
|
|
'num_cached_scripts' => number_format($status['opcache_statistics']['num_cached_scripts']),
|
|
|
|
'hits' => number_format($status['opcache_statistics']['hits']),
|
|
|
|
'misses' => number_format($status['opcache_statistics']['misses']),
|
|
|
|
'blacklist_miss' => number_format($status['opcache_statistics']['blacklist_misses']),
|
|
|
|
'num_cached_keys' => number_format($status['opcache_statistics']['num_cached_keys']),
|
|
|
|
'max_cached_keys' => number_format($status['opcache_statistics']['max_cached_keys']),
|
|
|
|
'start_time' => date_format(date_create("@{$status['opcache_statistics']['start_time']}"), 'Y-m-d H:i:s'),
|
|
|
|
'last_restart_time' => ($status['opcache_statistics']['last_restart_time'] == 0
|
|
|
|
? 'never'
|
|
|
|
: date_format(date_create("@{$status['opcache_statistics']['last_restart_time']}"), 'Y-m-d H:i:s')
|
|
|
|
)
|
|
|
|
]
|
|
|
|
]
|
|
|
|
);
|
2013-04-08 15:40:06 +00:00
|
|
|
|
2014-11-24 00:09:48 +00:00
|
|
|
$directives = [];
|
2014-11-23 01:07:38 +00:00
|
|
|
ksort($config['directives']);
|
2014-11-24 00:09:48 +00:00
|
|
|
foreach ($config['directives'] as $k => $v) {
|
|
|
|
$directives[] = ['k' => $k, 'v' => $v];
|
|
|
|
}
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
$version = array_merge(
|
|
|
|
$config['version'],
|
|
|
|
[
|
|
|
|
'php' => phpversion(),
|
|
|
|
'server' => $_SERVER['SERVER_SOFTWARE'],
|
|
|
|
'host' => (function_exists('gethostname')
|
|
|
|
? gethostname()
|
|
|
|
: (php_uname('n')
|
|
|
|
?: (empty($_SERVER['SERVER_NAME'])
|
|
|
|
? $_SERVER['HOST_NAME']
|
|
|
|
: $_SERVER['SERVER_NAME']
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
]
|
|
|
|
);
|
|
|
|
|
|
|
|
return [
|
|
|
|
'version' => $version,
|
|
|
|
'overview' => $overview,
|
2014-11-25 13:20:33 +00:00
|
|
|
'files' => $files,
|
2014-11-24 00:09:48 +00:00
|
|
|
'directives' => $directives,
|
2014-11-23 01:07:38 +00:00
|
|
|
'blacklist' => $config['blacklist'],
|
|
|
|
'functions' => get_extension_funcs('Zend OPcache')
|
|
|
|
];
|
|
|
|
}
|
2013-04-08 15:40:06 +00:00
|
|
|
}
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
$opcache = OpCacheService::init();
|
2013-04-09 15:44:50 +00:00
|
|
|
|
2013-04-08 15:40:06 +00:00
|
|
|
?>
|
|
|
|
<!doctype html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta charset="UTF-8"/>
|
|
|
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
2014-11-24 00:09:48 +00:00
|
|
|
<script src="http://fb.me/react-0.12.1.js"></script>
|
|
|
|
<script src="http://fb.me/JSXTransformer-0.12.1.js"></script>
|
|
|
|
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
|
2013-04-08 15:40:06 +00:00
|
|
|
<style type="text/css">
|
2014-11-23 01:07:38 +00:00
|
|
|
body {
|
|
|
|
font-family:sans-serif;
|
2014-11-25 13:20:33 +00:00
|
|
|
font-size:90%;
|
|
|
|
padding: 0;
|
|
|
|
margin: 0
|
|
|
|
}
|
|
|
|
|
|
|
|
#tabs { padding: 2em; }
|
|
|
|
#tabs > div {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
#tabs > div#overview {
|
|
|
|
display:block;
|
|
|
|
}
|
|
|
|
|
|
|
|
nav { padding-top: 20px; }
|
|
|
|
nav > ul {
|
|
|
|
list-style-type: none;
|
|
|
|
padding-left: 8px;
|
|
|
|
margin: 0;
|
|
|
|
border-bottom: 1px solid #ccc;
|
|
|
|
}
|
|
|
|
nav > ul > li {
|
|
|
|
display: inline-block;
|
|
|
|
padding: 0;
|
|
|
|
margin: 0 0 -1px 0;
|
2014-11-23 01:07:38 +00:00
|
|
|
}
|
2014-11-25 13:20:33 +00:00
|
|
|
nav > ul > li > a {
|
|
|
|
display: block;
|
|
|
|
margin: 0 10px;
|
|
|
|
padding: 20px 40px;
|
|
|
|
border: 1px solid transparent;
|
|
|
|
border-bottom-color: #ccc;
|
2014-11-23 01:07:38 +00:00
|
|
|
}
|
2014-11-25 13:20:33 +00:00
|
|
|
nav > ul > li > a[data-for].active {
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
border-bottom-color: #ffffff;
|
|
|
|
border-top: 3px solid #6ca6ef;
|
|
|
|
}
|
|
|
|
#resetCache, #toggleRealtime {
|
|
|
|
background-position: 15px 50%;
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
background-color: transparent;
|
|
|
|
}
|
|
|
|
#resetCache {
|
|
|
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjBFMUMyMjI3NDlGMTFFNEE3QzNGNjQ0OEFDQzQ1MkMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjBFMUMyMjM3NDlGMTFFNEE3QzNGNjQ0OEFDQzQ1MkMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MEUxQzIyMDc0OUYxMUU0QTdDM0Y2NDQ4QUNDNDUyQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2MEUxQzIyMTc0OUYxMUU0QTdDM0Y2NDQ4QUNDNDUyQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PplZ+ZkAAAD1SURBVHjazFPtDYJADIUJZAMZ4UbACWQENjBO4Ao6AW5AnODcADZQJwAnwJ55NbWhB/6zycsdpX39uDZNpsURtjgzwkDoCBecs5ITPGGMwCNAkIrQw+8ri36GhBHsavFdpILEo4wEpZxRigy009EhG760gr0VhFoyZfvJKPwsheIWIeGejBZRIxRVhMRFevbuUXBew/iE/lhlBduV0j8Jx+TvJEWPphq8n5li9utgaw6cW/h6NSt/JcnVBhQxotIgKTBrbNvIHo2G0x1rwlKqTDusxiAz6hHNL1zayTVqVKRKpa/LPljPH1sJh6l/oNSrZfwSYABtq3tFdZA5BAAAAABJRU5ErkJggg==');
|
|
|
|
}
|
|
|
|
#toggleRealtime {
|
|
|
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAUCAYAAACAl21KAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODE5RUU4NUE3NDlGMTFFNDkyMzA4QzY1RjRBQkIzQjUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODE5RUU4NUI3NDlGMTFFNDkyMzA4QzY1RjRBQkIzQjUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4MTlFRTg1ODc0OUYxMUU0OTIzMDhDNjVGNEFCQjNCNSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4MTlFRTg1OTc0OUYxMUU0OTIzMDhDNjVGNEFCQjNCNSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PpXjpvMAAAD2SURBVHjarFQBEcMgDKR3E1AJldA5wMEqAQmTgINqmILdFCChdUAdMAeMcukuSwnQbbnLlZLwJPkQIcrSiT/IGNQHNb8CGQDyRw+2QWUBqC+luzo4OKQZIAVrB+ssyKp3Bkijf0+ijzIh4wQppoBauMSjyDZfMSCDxYZMsfHF120T36AqWZMkgyguQ3GOfottJ5TKnHC+wfeRsC2oDVayPgr3bbN2tHBH3tWuJCPa0JUgKtFzMQrcZH3FNHAc0yOp1cCASALyngoN6lhDopkJWxdifwY9A3u7l29ImpxOFSWIOVsGwHKENIWxss2eBVKdOeeXAAMAk/Z9h4QhXmUAAAAASUVORK5CYII=');
|
|
|
|
}
|
|
|
|
#counts {
|
|
|
|
width: 270px;
|
|
|
|
float: right;
|
|
|
|
}
|
|
|
|
#counts > div > div {
|
|
|
|
background-color: #ededed;
|
|
|
|
margin-bottom: 10px;
|
|
|
|
}
|
|
|
|
#counts > div > div > h3 {
|
|
|
|
background-color: #cdcdcd;
|
|
|
|
padding: 10px;
|
|
|
|
margin: 0;
|
|
|
|
}
|
|
|
|
#counts > div > div > p {
|
|
|
|
margin: 0;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
#counts > div > div > p > span.large ~ span {
|
|
|
|
font-size: 20pt;
|
|
|
|
margin: 0;
|
|
|
|
}
|
|
|
|
#counts > div > div > p > span.large {
|
|
|
|
font-size: 80pt;
|
2014-11-23 01:07:38 +00:00
|
|
|
margin: 0;
|
2014-11-25 13:20:33 +00:00
|
|
|
padding: 0;
|
|
|
|
text-align: center;
|
2014-11-23 01:07:38 +00:00
|
|
|
}
|
2014-11-25 13:20:33 +00:00
|
|
|
#moreinfo { padding: 10px; }
|
|
|
|
#moreinfo > p {
|
|
|
|
text-align: left !important;
|
|
|
|
line-height: 180%;
|
2013-04-08 15:40:06 +00:00
|
|
|
}
|
2014-11-25 13:20:33 +00:00
|
|
|
#info { margin-right: 280px; }
|
2014-11-23 01:07:38 +00:00
|
|
|
|
2013-04-09 15:44:50 +00:00
|
|
|
table { margin: 0 0 1em 0; border-collapse: collapse; border-color: #fff; width: 100%; }
|
2014-11-23 01:07:38 +00:00
|
|
|
table caption { text-align: left; font-size: 1.5em; }
|
2013-04-09 15:44:50 +00:00
|
|
|
table tr { background-color: #99D0DF; border-color: #fff; }
|
|
|
|
table th { text-align: left; padding: 6px; background-color: #0BA0C8; color: #fff; border-color: #fff; }
|
|
|
|
table td { padding: 4px 6px; line-height: 1.4em; vertical-align: top; border-color: #fff; }
|
2014-11-23 01:07:38 +00:00
|
|
|
table tr:nth-child(odd) { background-color: #EFFEFF; }
|
|
|
|
table tr:nth-child(even) { background-color: #E0ECEF; }
|
2014-11-25 13:20:33 +00:00
|
|
|
td.pathname { width: 70%; }
|
2014-11-23 01:07:38 +00:00
|
|
|
|
2013-04-08 15:40:06 +00:00
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
2014-11-23 01:07:38 +00:00
|
|
|
<nav>
|
|
|
|
<ul>
|
|
|
|
<li><a data-for="overview" href="#overview" class="active">Overview</a></li>
|
|
|
|
<li><a data-for="files" href="#files">File usage</a></li>
|
2014-11-25 13:20:33 +00:00
|
|
|
<li><a href="?reset=1" id="resetCache" onclick="return confirm('Are you sure you want to reset the cache?');">Reset cache</a></li>
|
|
|
|
<li><a href="#" id="toggleRealtime">Enable real-time update of stats</a></li>
|
2014-11-23 01:07:38 +00:00
|
|
|
</ul>
|
|
|
|
</nav>
|
2013-04-09 15:44:50 +00:00
|
|
|
|
2014-11-25 13:20:33 +00:00
|
|
|
<div id="tabs">
|
|
|
|
<div id="overview">
|
|
|
|
<div class="container">
|
|
|
|
<div id="counts"></div>
|
|
|
|
<div id="info">
|
|
|
|
<div id="generalInfo"></div>
|
|
|
|
<div id="directives"></div>
|
|
|
|
<div id="functions"></div>
|
|
|
|
<br style="clear:both;" />
|
|
|
|
</div>
|
2013-04-08 15:40:06 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
2014-11-25 13:20:33 +00:00
|
|
|
<div id="files">
|
|
|
|
<p><label>Start typing to filter on script path<br/><input type="text" style="width:40em;" name="filter" id="frmFilter" /><label></p>
|
|
|
|
<div class="container" id="filelist"></div>
|
2013-04-09 15:44:50 +00:00
|
|
|
</div>
|
2014-11-23 01:07:38 +00:00
|
|
|
</div>
|
|
|
|
|
2014-11-24 00:09:48 +00:00
|
|
|
<script type="text/jsx">
|
|
|
|
var opstate = <?php echo json_encode($opcache->getData()); ?>;
|
2014-11-25 13:20:33 +00:00
|
|
|
var realtime = false;
|
2014-11-24 00:09:48 +00:00
|
|
|
|
|
|
|
var OverviewCounts = React.createClass({
|
|
|
|
getInitialState: function() {
|
|
|
|
return { data : opstate.overview };
|
|
|
|
},
|
|
|
|
render: function() {
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<div>
|
|
|
|
<h3>memory usage</h3>
|
2014-11-25 13:20:33 +00:00
|
|
|
<p><span className="large">{this.state.data.used_memory_percentage}</span><span>%</span></p>
|
2014-11-24 00:09:48 +00:00
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<h3>hit rate</h3>
|
2014-11-25 13:20:33 +00:00
|
|
|
<p><span className="large">{this.state.data.hit_rate_percentage}</span><span>%</span></p>
|
2014-11-24 00:09:48 +00:00
|
|
|
</div>
|
2014-11-25 13:20:33 +00:00
|
|
|
<div id="moreinfo">
|
2014-11-24 00:09:48 +00:00
|
|
|
<p><b>total memory:</b>{this.state.data.readable.total_memory}</p>
|
|
|
|
<p><b>used memory:</b>{this.state.data.readable.used_memory}</p>
|
|
|
|
<p><b>free memory:</b>{this.state.data.readable.free_memory}</p>
|
|
|
|
<p><b>wasted memory:</b>{this.state.data.readable.wasted_memory} ({this.state.data.wasted_percentage}%)</p>
|
|
|
|
<p><b>number of cached files:</b>{this.state.data.readable.num_cached_scripts}</p>
|
|
|
|
<p><b>number of hits:</b>{this.state.data.readable.hits}</p>
|
|
|
|
<p><b>number of misses:</b>{this.state.data.readable.misses}</p>
|
|
|
|
<p><b>blacklist misses:</b>{this.state.data.readable.blacklist_miss}</p>
|
|
|
|
<p><b>number of cached keys:</b>{this.state.data.readable.num_cached_keys}</p>
|
|
|
|
<p><b>max cached keys:</b>{this.state.data.readable.max_cached_keys}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var GeneralInfo = React.createClass({
|
|
|
|
getInitialState: function() {
|
|
|
|
return {
|
|
|
|
version : opstate.version,
|
|
|
|
start : opstate.overview.readable.start_time,
|
|
|
|
reset : opstate.overview.readable.last_restart_time,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
render: function() {
|
|
|
|
return (
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr><th colSpan="2">General info</th></tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
|
|
|
<tr><td>Zend OPcache</td><td>{this.state.version.version}</td></tr>
|
|
|
|
<tr><td>PHP</td><td>{this.state.version.php}</td></tr>
|
|
|
|
<tr><td>Host</td><td>{this.state.version.host}</td></tr>
|
|
|
|
<tr><td>Server Software</td><td>{this.state.version.server}</td></tr>
|
|
|
|
<tr><td>Start time</td><td>{this.state.start}</td></tr>
|
|
|
|
<tr><td>Last reset</td><td>{this.state.reset}</td></tr>
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var Directives = React.createClass({
|
|
|
|
getInitialState: function() {
|
|
|
|
return { data : opstate.directives };
|
|
|
|
},
|
|
|
|
render: function() {
|
|
|
|
var directiveNodes = this.state.data.map(function(directive) {
|
|
|
|
var map = { 'opcache.':'', '_':' ' };
|
|
|
|
var dShow = directive.k.replace(/opcache\.|_/gi, function(matched){
|
|
|
|
return map[matched];
|
|
|
|
});
|
|
|
|
var vShow;
|
|
|
|
if (directive.v === true || directive.v === false) {
|
|
|
|
vShow = React.createElement('i', {}, directive.v.toString());
|
|
|
|
} else if (directive.v == '') {
|
|
|
|
vShow = React.createElement('i', {}, 'no value');
|
|
|
|
} else {
|
|
|
|
vShow = directive.v;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
<td title="{directive.k}">{dShow}</td>
|
|
|
|
<td>{vShow}</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr><th colSpan="2">Directives</th></tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>{directiveNodes}</tbody>
|
|
|
|
</table>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var Functions = React.createClass({
|
|
|
|
getInitialState: function() {
|
|
|
|
return { data : opstate.functions };
|
|
|
|
},
|
|
|
|
render: function() {
|
|
|
|
var functionNodes = this.state.data.map(function(func) {
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
<td><a href="http://php.net/{func}" title="View manual page" target="_blank">{func}</a></td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr><th>Available functions</th></tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>{functionNodes}</tbody>
|
|
|
|
</table>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2014-11-25 13:20:33 +00:00
|
|
|
var Files = React.createClass({
|
|
|
|
getInitialState: function() {
|
|
|
|
return {
|
|
|
|
data : opstate.files,
|
|
|
|
count_formatted : opstate.overview.readable.num_cached_scripts,
|
|
|
|
count : opstate.overview.num_cached_scripts
|
|
|
|
};
|
|
|
|
},
|
|
|
|
render: function() {
|
|
|
|
var fileNodes = this.state.data.map(function (file) {
|
|
|
|
var invalidated;
|
|
|
|
console.log(file);
|
|
|
|
if (file.timestamp == 0) {
|
|
|
|
invalidated = <span>
|
|
|
|
<i className="invalid">has been invalidated</i>
|
|
|
|
</span>;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
<td className="pathname">
|
|
|
|
<p>{file.full_path}</p>
|
|
|
|
<?php if ($opcache->getOption('allow_invalidate') && function_exists('opcache_invalidate')): ?>
|
|
|
|
<p><a href="?invalidate={file.full_path}">Force file invalidation</a></p>
|
|
|
|
<?php endif; ?>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<p>
|
|
|
|
<span>hits: {file.readable.hits},</span>
|
|
|
|
<span>memory: {file.readable.memory_consumption}</span>
|
|
|
|
<br />
|
|
|
|
<span>last used: {file.last_used}</span>
|
|
|
|
{invalidated}
|
|
|
|
</p>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<h3>{this.state.count_formatted} file{this.state.count == 1 ? '' : 's'} cached
|
|
|
|
<span id="filterShowing"></span>
|
|
|
|
</h3>
|
|
|
|
<table>
|
|
|
|
<thead>
|
|
|
|
<tr>
|
|
|
|
<th>Script</th>
|
|
|
|
<th>Details</th>
|
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>{fileNodes}</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var overviewCountsObj = React.render(<OverviewCounts/>, document.getElementById('counts'));
|
|
|
|
var generalInfoObj = React.render(<GeneralInfo/>, document.getElementById('generalInfo'));
|
|
|
|
var filesObj = React.render(<Files/>, document.getElementById('filelist'));
|
2014-11-24 00:09:48 +00:00
|
|
|
React.render(<Directives/>, document.getElementById('directives'));
|
|
|
|
React.render(<Functions/>, document.getElementById('functions'));
|
|
|
|
|
2014-11-25 13:20:33 +00:00
|
|
|
$(function() {
|
|
|
|
function updateStatus() {
|
2014-11-23 01:07:38 +00:00
|
|
|
$.ajax({
|
|
|
|
url: "#",
|
|
|
|
dataType: "json",
|
|
|
|
cache: false,
|
2014-11-25 13:20:33 +00:00
|
|
|
success: function(data) {
|
|
|
|
opstate = data;
|
|
|
|
overviewCountsObj.setState({
|
|
|
|
data : opstate.overview
|
|
|
|
});
|
|
|
|
generalInfoObj.setState({
|
|
|
|
version : opstate.version,
|
|
|
|
start : opstate.overview.readable.start_time,
|
|
|
|
reset : opstate.overview.readable.last_restart_time
|
|
|
|
});
|
|
|
|
filesObj.setState({
|
|
|
|
data : opstate.files,
|
|
|
|
count_formatted : opstate.overview.readable.num_cached_scripts,
|
|
|
|
count : opstate.overview.num_cached_scripts
|
2014-11-23 01:07:38 +00:00
|
|
|
});
|
2013-08-09 14:06:45 +00:00
|
|
|
}
|
|
|
|
});
|
2014-11-23 01:07:38 +00:00
|
|
|
}
|
|
|
|
$('#toggleRealtime').click(function(){
|
|
|
|
if (realtime === false) {
|
2014-11-25 13:20:33 +00:00
|
|
|
realtime = setInterval(function(){updateStatus()}, 5000);
|
2014-11-23 01:07:38 +00:00
|
|
|
$(this).text('Disable real-time update of stats');
|
|
|
|
} else {
|
|
|
|
clearInterval(realtime);
|
|
|
|
realtime = false;
|
|
|
|
$(this).text('Enable real-time update of stats');
|
|
|
|
}
|
|
|
|
});
|
2014-11-25 13:20:33 +00:00
|
|
|
$('nav a[data-for]').click(function(){
|
|
|
|
$('#tabs > div').hide();
|
|
|
|
$('#' + $(this).data('for')).show();
|
|
|
|
$('nav a[data-for]').removeClass('active');
|
|
|
|
$(this).addClass('active');
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<script type="text/javascript">
|
|
|
|
$(function(){
|
2014-11-23 01:07:38 +00:00
|
|
|
$('span.showmore span.button').click(function(){
|
|
|
|
if ($(this).next().is(":visible")) {
|
|
|
|
$(this).next().hide();
|
|
|
|
$(this).css('padding-top', '0').text('…');
|
|
|
|
} else {
|
|
|
|
$(this).next().show();
|
|
|
|
$(this).css('padding-top', '2px').text('«');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
$('.container table').bind('paint', function(event, params) {
|
|
|
|
var trs = $('tr:visible', $(this)).not(':first');
|
|
|
|
trs.removeClass('odd even')
|
|
|
|
.filter(':odd').addClass('odd')
|
|
|
|
.end()
|
|
|
|
.filter(':even').addClass('even');
|
|
|
|
$('#filterShowing').text(($('#frmFilter').val().length
|
|
|
|
? trs.length + ' showing due to filter'
|
|
|
|
: ''
|
|
|
|
));
|
|
|
|
});
|
|
|
|
$('#frmFilter').bind('keyup', function(event){
|
|
|
|
$('td.pathname p').each(function(index){
|
|
|
|
if ($(this).text().toLowerCase().indexOf($('#frmFilter').val().toLowerCase()) == -1) {
|
|
|
|
$(this).closest('tr').hide();
|
|
|
|
} else {
|
|
|
|
$(this).closest('tr').show();
|
|
|
|
}
|
2013-04-26 11:56:30 +00:00
|
|
|
});
|
2014-11-23 01:07:38 +00:00
|
|
|
$('.container table').trigger('paint');
|
2013-04-26 11:56:30 +00:00
|
|
|
});
|
2014-11-23 01:07:38 +00:00
|
|
|
});
|
|
|
|
</script>
|
2013-04-08 15:40:06 +00:00
|
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|