This adds a new graph to the highlight bar along with the ability to turn on/off individual charts.
This commit is contained in:
Andrew Collington 2019-07-13 17:17:52 +01:00
parent 3f1591471d
commit 351525a1a0
3 changed files with 115 additions and 118 deletions

View file

@ -3,10 +3,13 @@
A clean and responsive interface for Zend OPcache information, showing statistics, settings and cached files, and providing a real-time update for the information (using jQuery and React).
[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=acollington&url=https://github.com/amnuts/opcache-gui&title=opcache-gui&language=&tags=github&category=software)
If you like this software or find it helpful then please consider [signing up to Flattr and leaving a micro-donation](https://flattr.com/@acollington). If you don't want to do that, I hope you find it useful anyway! :-).
If you like this software or find it helpful then maybe you'll consider supporting my efforts in some way by [signing up to Flattr and leaving a micro-donation](https://flattr.com/@acollington).
## What's new
**Version 2.5.0**\
Added a new highlight chart to show the cached keys percentage with options to turn on/off the individual highlight graphs.
**Version 2.4.1**\
Mostly bug fixes
* `memory_consumption` and `max_file_size` config settings now display as human-readable sizes
@ -51,15 +54,22 @@ There are two ways to getting started using this gui.
If you want to set the configuration options just alter the array at the top of the script:
```php
$options = [
'allow_filelist' => true, // show/hide the files tab
'allow_invalidate' => true, // give a link to invalidate files
'allow_reset' => true, // give option to reset the whole cache
'allow_realtime' => true, // give option to enable/disable real-time updates
'refresh_time' => 5, // how often the data will refresh, in seconds
'size_precision' => 2, // Digits after decimal point
'size_space' => false, // have '1MB' or '1 MB' when showing sizes
'charts' => true, // show gauge chart or just big numbers
'debounce_rate' => 250 // milliseconds after key press to send keyup event when filtering
'allow_filelist' => true, // show/hide the files tab
'allow_invalidate' => true, // give a link to invalidate files
'allow_reset' => true, // give option to reset the whole cache
'allow_realtime' => true, // give option to enable/disable real-time updates
'refresh_time' => 5, // how often the data will refresh, in seconds
'size_precision' => 2, // Digits after decimal point
'size_space' => false, // have '1MB' or '1 MB' when showing sizes
'charts' => true, // show gauge chart or just big numbers
'debounce_rate' => 250, // milliseconds after key press to send keyup event when filtering
'cookie_name' => 'opcachegui', // name of cookie
'cookie_ttl' => 365, // days to store cookie
'highlight' => [ // highlight charts/big numbers
'memory' => true,
'hits' => true,
'keys' => true
]
];
```

135
index.php
View file

@ -8,7 +8,7 @@ namespace OpcacheGui;
* A simple but effective single-file GUI for the OPcache PHP extension.
*
* @author Andrew Collington, andy@amnuts.com
* @version 2.4.1
* @version 2.5.0
* @link https://github.com/amnuts/opcache-gui
* @license MIT, http://acollington.mit-license.org/
*/
@ -28,7 +28,12 @@ $options = [
'charts' => true, // show gauge chart or just big numbers
'debounce_rate' => 250, // milliseconds after key press to send keyup event when filtering
'cookie_name' => 'opcachegui', // name of cookie
'cookie_ttl' => 365 // days to store cookie
'cookie_ttl' => 365, // days to store cookie
'highlight' => [ // highlight charts/big numbers
'memory' => true,
'hits' => true,
'keys' => true
]
];
/*
@ -188,6 +193,9 @@ class OpCacheService
($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']),
'used_key_percentage' => round(100 * (
$status['opcache_statistics']['num_cached_keys']
/ $status['opcache_statistics']['max_cached_keys'])),
'wasted_percentage' => round($status['memory_usage']['current_wasted_percentage'], 2),
'readable' => [
'total_memory' => $this->size($config['directives']['opcache.memory_consumption']),
@ -416,6 +424,7 @@ $opcache = OpCacheService::init($options);
var opstate = <?php echo json_encode($opcache->getData()); ?>;
var canInvalidate = <?php echo json_encode($opcache->canInvalidate()); ?>;
var useCharts = <?php echo json_encode($opcache->getOption('charts')); ?>;
var highlight = <?php echo json_encode($opcache->getOption('highlight')); ?>;
var allowFiles = <?php echo json_encode($opcache->getOption('allow_filelist')); ?>;
var debounce = function(func, wait, immediate) {
var timeout;
@ -576,64 +585,26 @@ $opcache = OpCacheService::init($options);
$('#frmFilter').bind('keyup', debounce(keyUp, <?php echo $opcache->getOption('debounce_rate'); ?>));
});
var MemoryUsageGraph = React.createClass({
var UsageGraph = React.createClass({
getInitialState: function () {
return {
memoryUsageGauge: null
gauge: null
};
},
componentDidMount: function () {
if (this.props.chart) {
this.state.memoryUsageGauge = new Gauge('#memoryUsageCanvas');
this.state.memoryUsageGauge.setValue(this.props.value);
this.state.gauge = new Gauge('#' + this.props.gaugeId);
this.state.gauge.setValue(this.props.value);
}
},
componentDidUpdate: function () {
if (this.state.memoryUsageGauge != null) {
this.state.memoryUsageGauge.setValue(this.props.value);
if (this.state.gauge != null) {
this.state.gauge.setValue(this.props.value);
}
},
render: function () {
if (this.props.chart == true) {
return React.createElement("canvas", { id: "memoryUsageCanvas", width: "250", height: "250", "data-value": this.props.value });
}
return React.createElement(
"p",
null,
React.createElement(
"span",
{ className: "large" },
this.props.value
),
React.createElement(
"span",
null,
"%"
)
);
}
});
var HitRateGraph = React.createClass({
getInitialState: function () {
return {
hitRateGauge: null
};
},
componentDidMount: function () {
if (this.props.chart) {
this.state.hitRateGauge = new Gauge('#hitRateCanvas');
this.state.hitRateGauge.setValue(this.props.value);
}
},
componentDidUpdate: function () {
if (this.state.hitRateGauge != null) {
this.state.hitRateGauge.setValue(this.props.value);
}
},
render: function () {
if (this.props.chart == true) {
return React.createElement("canvas", { id: "hitRateCanvas", width: "250", height: "250", "data-value": this.props.value });
return React.createElement("canvas", { id: this.props.gaugeId, width: "250", height: "250", "data-value": this.props.value });
}
return React.createElement(
"p",
@ -867,7 +838,8 @@ $opcache = OpCacheService::init($options);
getInitialState: function () {
return {
data: opstate.overview,
chart: useCharts
chart: useCharts,
highlight: highlight
};
},
render: function () {
@ -896,37 +868,58 @@ $opcache = OpCacheService::init($options);
strings_free_memory: this.state.data.readable.interned.strings_free_memory,
number_of_strings: this.state.data.readable.interned.number_of_strings
}) : '';
return React.createElement(
var memoryHighlight = this.state.highlight.memory ? React.createElement(
"div",
null,
React.createElement(
"div",
"h3",
null,
React.createElement(
"h3",
null,
"memory"
),
React.createElement(
"p",
null,
React.createElement(MemoryUsageGraph, { chart: this.state.chart, value: this.state.data.used_memory_percentage })
)
"memory"
),
React.createElement(
"div",
"p",
null,
React.createElement(
"h3",
null,
"hit rate"
),
React.createElement(
"p",
null,
React.createElement(HitRateGraph, { chart: this.state.chart, value: this.state.data.hit_rate_percentage })
)
React.createElement(UsageGraph, { chart: this.state.chart, value: this.state.data.used_memory_percentage, gaugeId: "memoryUsageCanvas" })
)
) : null;
var hitsHighlight = this.state.highlight.hits ? React.createElement(
"div",
null,
React.createElement(
"h3",
null,
"hit rate"
),
React.createElement(
"p",
null,
React.createElement(UsageGraph, { chart: this.state.chart, value: this.state.data.hit_rate_percentage, gaugeId: "hitRateCanvas" })
)
) : null;
var keysHighlight = this.state.highlight.keys ? React.createElement(
"div",
null,
React.createElement(
"h3",
null,
"keys"
),
React.createElement(
"p",
null,
React.createElement(UsageGraph, { chart: this.state.chart, value: this.state.data.used_key_percentage, gaugeId: "keyUsageCanvas" })
)
) : null;
return React.createElement(
"div",
null,
memoryHighlight,
hitsHighlight,
keysHighlight,
React.createElement(MemoryUsagePanel, {
total: this.state.data.readable.total_memory,
used: this.state.data.readable.used_memory,

View file

@ -1,48 +1,23 @@
var MemoryUsageGraph = React.createClass({
var UsageGraph = React.createClass({
getInitialState: function() {
return {
memoryUsageGauge : null
gauge : null
};
},
componentDidMount: function() {
if (this.props.chart) {
this.state.memoryUsageGauge = new Gauge('#memoryUsageCanvas');
this.state.memoryUsageGauge.setValue(this.props.value);
this.state.gauge = new Gauge('#' + this.props.gaugeId);
this.state.gauge.setValue(this.props.value);
}
},
componentDidUpdate: function() {
if (this.state.memoryUsageGauge != null) {
this.state.memoryUsageGauge.setValue(this.props.value);
if (this.state.gauge != null) {
this.state.gauge.setValue(this.props.value);
}
},
render: function() {
if (this.props.chart == true) {
return(<canvas id="memoryUsageCanvas" width="250" height="250" data-value={this.props.value} />);
}
return(<p><span className="large">{this.props.value}</span><span>%</span></p>);
}
});
var HitRateGraph = React.createClass({
getInitialState: function() {
return {
hitRateGauge : null
};
},
componentDidMount: function() {
if (this.props.chart) {
this.state.hitRateGauge = new Gauge('#hitRateCanvas');
this.state.hitRateGauge.setValue(this.props.value)
}
},
componentDidUpdate: function() {
if (this.state.hitRateGauge != null) {
this.state.hitRateGauge.setValue(this.props.value);
}
},
render: function() {
if (this.props.chart == true) {
return(<canvas id="hitRateCanvas" width="250" height="250" data-value={this.props.value} />);
return(<canvas id={this.props.gaugeId} width="250" height="250" data-value={this.props.value} />);
}
return(<p><span className="large">{this.props.value}</span><span>%</span></p>);
}
@ -102,7 +77,8 @@ var OverviewCounts = React.createClass({
getInitialState: function() {
return {
data : opstate.overview,
chart : useCharts
chart : useCharts,
highlight: highlight
};
},
render: function() {
@ -122,16 +98,34 @@ var OverviewCounts = React.createClass({
/>
: ''
);
return (
<div>
var memoryHighlight = this.state.highlight.memory ? (
<div>
<h3>memory</h3>
<p><MemoryUsageGraph chart={this.state.chart} value={this.state.data.used_memory_percentage} /></p>
<p><UsageGraph chart={this.state.chart} value={this.state.data.used_memory_percentage} gaugeId="memoryUsageCanvas"/></p>
</div>
) : null;
var hitsHighlight = this.state.highlight.hits ? (
<div>
<h3>hit rate</h3>
<p><HitRateGraph chart={this.state.chart} value={this.state.data.hit_rate_percentage} /></p>
<p><UsageGraph chart={this.state.chart} value={this.state.data.hit_rate_percentage} gaugeId="hitRateCanvas"/></p>
</div>
) : null;
var keysHighlight = this.state.highlight.keys ? (
<div>
<h3>keys</h3>
<p><UsageGraph chart={this.state.chart} value={this.state.data.used_key_percentage} gaugeId="keyUsageCanvas"/></p>
</div>
) : null;
return (
<div>
{memoryHighlight}
{hitsHighlight}
{keysHighlight}
<MemoryUsagePanel
total={this.state.data.readable.total_memory}
used={this.state.data.readable.used_memory}