Skip to content

Commit 5dc347e

Browse files
committed
Improve OPCache dashboard
1 parent a18c965 commit 5dc347e

7 files changed

Lines changed: 124 additions & 37 deletions

File tree

assets/css/styles.css

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,10 @@ svg {
799799
table-layout: fixed;
800800
}
801801

802+
.cursor-pointer {
803+
cursor: pointer;
804+
}
805+
802806
.flex-col {
803807
flex-direction: column;
804808
}
@@ -937,9 +941,9 @@ svg {
937941
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
938942
}
939943

940-
.bg-red-500 {
944+
.bg-sky-500 {
941945
--tw-bg-opacity: 1;
942-
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
946+
background-color: rgb(14 165 233 / var(--tw-bg-opacity));
943947
}
944948

945949
.bg-slate-200 {
@@ -952,9 +956,9 @@ svg {
952956
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
953957
}
954958

955-
.bg-sky-500 {
959+
.bg-red-500 {
956960
--tw-bg-opacity: 1;
957-
background-color: rgb(14 165 233 / var(--tw-bg-opacity));
961+
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
958962
}
959963

960964
.bg-orange-500 {
@@ -1526,16 +1530,21 @@ svg {
15261530
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
15271531
}
15281532

1529-
.hover\:bg-red-600:hover {
1533+
.hover\:bg-sky-600:hover {
15301534
--tw-bg-opacity: 1;
1531-
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
1535+
background-color: rgb(2 132 199 / var(--tw-bg-opacity));
15321536
}
15331537

15341538
.hover\:bg-green-600:hover {
15351539
--tw-bg-opacity: 1;
15361540
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
15371541
}
15381542

1543+
.hover\:bg-red-600:hover {
1544+
--tw-bg-opacity: 1;
1545+
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
1546+
}
1547+
15391548
.hover\:bg-slate-600:hover {
15401549
--tw-bg-opacity: 1;
15411550
background-color: rgb(71 85 105 / var(--tw-bg-opacity));
@@ -1546,11 +1555,6 @@ svg {
15461555
background-color: rgb(5 150 105 / var(--tw-bg-opacity));
15471556
}
15481557

1549-
.hover\:bg-sky-600:hover {
1550-
--tw-bg-opacity: 1;
1551-
background-color: rgb(2 132 199 / var(--tw-bg-opacity));
1552-
}
1553-
15541558
.hover\:text-gray-200:hover {
15551559
--tw-text-opacity: 1;
15561560
color: rgb(229 231 235 / var(--tw-text-opacity));
@@ -1611,16 +1615,21 @@ svg {
16111615
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
16121616
}
16131617

1614-
.focus\:ring-red-300:focus {
1618+
.focus\:ring-sky-300:focus {
16151619
--tw-ring-opacity: 1;
1616-
--tw-ring-color: rgb(252 165 165 / var(--tw-ring-opacity));
1620+
--tw-ring-color: rgb(125 211 252 / var(--tw-ring-opacity));
16171621
}
16181622

16191623
.focus\:ring-green-300:focus {
16201624
--tw-ring-opacity: 1;
16211625
--tw-ring-color: rgb(134 239 172 / var(--tw-ring-opacity));
16221626
}
16231627

1628+
.focus\:ring-red-300:focus {
1629+
--tw-ring-opacity: 1;
1630+
--tw-ring-color: rgb(252 165 165 / var(--tw-ring-opacity));
1631+
}
1632+
16241633
.focus\:ring-slate-100:focus {
16251634
--tw-ring-opacity: 1;
16261635
--tw-ring-color: rgb(241 245 249 / var(--tw-ring-opacity));
@@ -1671,11 +1680,6 @@ svg {
16711680
--tw-ring-color: rgb(186 230 253 / var(--tw-ring-opacity));
16721681
}
16731682

1674-
.focus\:ring-sky-300:focus {
1675-
--tw-ring-opacity: 1;
1676-
--tw-ring-color: rgb(125 211 252 / var(--tw-ring-opacity));
1677-
}
1678-
16791683
@media (min-width: 768px) {
16801684
.md\:ml-64 {
16811685
margin-left: 16rem;

assets/icons/reset.svg

Lines changed: 3 additions & 0 deletions
Loading

assets/js/scripts.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,17 @@ if (redis_type) {
209209
document.getElementById('redis_hash_key').style.display = e.target.value === 'hash' ? 'block' : 'none';
210210
});
211211
}
212+
213+
/**
214+
* OPCache table
215+
*/
216+
const scripts = document.querySelectorAll('[data-key]');
217+
scripts.forEach(script => {
218+
let show_path = script.querySelector('.show-path');
219+
220+
if (show_path) {
221+
show_path.addEventListener('click', () => {
222+
document.querySelector('[data-path="' + script.dataset.key + '"]').classList.toggle('hidden');
223+
});
224+
}
225+
});

src/Dashboards/OPCache/OPCacheDashboard.php

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
namespace RobiNN\Pca\Dashboards\OPCache;
1414

15-
use RobiNN\Pca\Config;
1615
use RobiNN\Pca\Dashboards\DashboardInterface;
1716
use RobiNN\Pca\Helpers;
1817
use RobiNN\Pca\Template;
@@ -76,8 +75,13 @@ public function ajax(): string {
7675
*/
7776
public function info(): array {
7877
$status = opcache_get_status();
78+
$directives = opcache_get_configuration()['directives'];
79+
7980
$stats = $status['opcache_statistics'];
81+
82+
$total_memory = $directives['opcache.memory_consumption'];
8083
$memory = $status['memory_usage'];
84+
$memory_usage = ($memory['used_memory'] + $memory['wasted_memory']) / $total_memory;
8185

8286
return [
8387
'panels' => [
@@ -86,27 +90,31 @@ public function info(): array {
8690
'moreinfo' => true,
8791
'data' => [
8892
'JIT' => Helpers::enabledDisabledBadge($this->template, isset($status['jit']) && $status['jit']['enabled']),
89-
'Start time' => date(Config::get('timeformat'), $stats['start_time']),
90-
'Last restart' => $stats['last_restart_time'] === 0 ? 'Never' : date(Config::get('timeformat'), $stats['last_restart_time']),
93+
'Start time' => Helpers::formatTime($stats['start_time']),
94+
'Last restart' => Helpers::formatTime($stats['last_restart_time']),
9195
'Cache full' => Helpers::enabledDisabledBadge($this->template, $status['cache_full'] === false, null, ['No', 'Yes']),
9296
],
9397
],
9498
[
9599
'title' => 'Memory',
96100
'data' => [
101+
'Total' => Helpers::formatBytes($total_memory),
102+
'Usage' => round(100 * $memory_usage).'%',
97103
'Used' => Helpers::formatBytes($memory['used_memory']),
98104
'Free' => Helpers::formatBytes($memory['free_memory']),
99105
'Wasted' => Helpers::formatBytes($memory['wasted_memory']),
100-
'Current wasted' => round($memory['current_wasted_percentage'], 5).'%',
106+
'Current wasted' => round($memory['current_wasted_percentage'], 3).'%',
101107
],
102108
],
103109
[
104110
'title' => 'Stats',
105111
'data' => [
106-
'Cached scripts' => $stats['num_cached_scripts'],
107-
'Cached keys' => $stats['num_cached_keys'],
108-
'Hits' => $stats['hits'],
109-
'Misses' => $stats['misses'],
112+
'Cached scripts' => $stats['num_cached_scripts'],
113+
'Cached keys' => Helpers::formatNumber($stats['num_cached_keys']),
114+
'Max cached keys' => Helpers::formatNumber($stats['max_cached_keys']),
115+
'Hits' => Helpers::formatNumber($stats['hits']),
116+
'Misses' => Helpers::formatNumber($stats['misses']),
117+
'Hit rate' => round($stats['opcache_hit_rate']).'%',
110118
],
111119
],
112120
],

src/Dashboards/OPCache/OPCacheTrait.php

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
namespace RobiNN\Pca\Dashboards\OPCache;
1414

15-
use RobiNN\Pca\Config;
1615
use RobiNN\Pca\Helpers;
1716
use RobiNN\Pca\Http;
1817
use RobiNN\Pca\Paginator;
@@ -47,6 +46,13 @@ private function deleteScript(): string {
4746
private function moreInfo(array $status): string {
4847
unset($status['scripts']);
4948

49+
$directives = opcache_get_configuration()['directives'];
50+
51+
$status['directives'] = array_combine(
52+
array_map(static fn ($key) => str_replace('opcache.', '', $key), array_keys($directives)),
53+
$directives
54+
);
55+
5056
return $this->template->render('partials/info_table', [
5157
'panel_title' => 'OPCache Info',
5258
'array' => Helpers::convertBoolToString($status),
@@ -65,15 +71,21 @@ private function getCachedScripts(array $status): array {
6571

6672
if (isset($status['scripts'])) {
6773
foreach ($status['scripts'] as $script) {
68-
$name = explode('/', str_replace('\\', '/', $script['full_path']));
74+
$full_path = str_replace('\\', '/', $script['full_path']);
75+
$name = explode('/', $full_path);
76+
$script_name = $name[array_key_last($name)];
77+
78+
if ((isset($_GET['ignore']) && $_GET['ignore'] === 'yes') && Helpers::str_starts_with($full_path, $_SERVER['DOCUMENT_ROOT'])) {
79+
continue;
80+
}
6981

7082
$cached_scripts[] = [
71-
'path' => $script['full_path'],
72-
'name' => $name[array_key_last($name)],
73-
'hits' => $script['hits'],
83+
'path' => $full_path,
84+
'name' => $script_name,
85+
'hits' => Helpers::formatNumber($script['hits']),
7486
'memory' => Helpers::formatBytes($script['memory_consumption']),
75-
'last_used' => date(Config::get('timeformat'), $script['last_used_timestamp']),
76-
'created' => date(Config::get('timeformat'), $script['timestamp']),
87+
'last_used' => Helpers::formatTime($script['last_used_timestamp']),
88+
'created' => Helpers::formatTime($script['timestamp']),
7789
'invalidate_url' => base64_encode($script['full_path']),
7890
];
7991
}
@@ -94,9 +106,13 @@ private function mainDashboard(array $status): string {
94106

95107
$paginator = new Paginator($this->template, $cached_scripts);
96108

109+
$is_ignored = isset($_GET['ignore']) && $_GET['ignore'] === 'yes';
110+
97111
return $this->template->render('dashboards/opcache', [
98112
'cached_scripts' => $paginator->getPaginated(),
99113
'paginator' => $paginator->render(),
114+
'ignore_url' => Http::queryString(['pp', 'p'], ['ignore' => $is_ignored ? 'no' : 'yes']),
115+
'is_ignored' => $is_ignored,
100116
]);
101117
}
102118
}

src/Helpers.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
namespace RobiNN\Pca;
1414

15+
use DateTimeImmutable;
16+
use DateTimeZone;
1517
use Exception;
1618

1719
class Helpers {
@@ -116,6 +118,38 @@ public static function formatSeconds(int $time): string {
116118
return implode(' ', $time_parts);
117119
}
118120

121+
/**
122+
* Format timestamp.
123+
*
124+
* @param int $time
125+
*
126+
* @return string
127+
*/
128+
public static function formatTime(int $time): string {
129+
if ($time === 0) {
130+
return 'Never';
131+
}
132+
133+
try {
134+
return (new DateTimeImmutable('@'.$time))
135+
->setTimezone(new DateTimeZone(date_default_timezone_get()))
136+
->format(Config::get('timeformat'));
137+
} catch (Exception $e) {
138+
return date(Config::get('timeformat'), $time);
139+
}
140+
}
141+
142+
/**
143+
* Format number.
144+
*
145+
* @param int $number
146+
*
147+
* @return string
148+
*/
149+
public static function formatNumber(int $number): string {
150+
return number_format($number, 0, ',', ' ');
151+
}
152+
119153
/**
120154
* Return JSON data for ajax.
121155
*

templates/dashboards/opcache.twig

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
<div class="flex md:justify-end gap-1 mb-5">
2+
<a href="{{ ignore_url }}"
3+
class="text-sm py-1.5 px-3 text-white bg-sky-500 hover:bg-sky-600 focus:ring-4 focus:ring-sky-300 font-semibold rounded">
4+
{{ is_ignored ? 'Show' : 'Ignore' }} scripts from this tool
5+
</a>
6+
27
<button type="button" id="delete_all"
3-
class="text-sm py-1.5 px-3 text-white bg-red-500 hover:bg-red-600 focus:ring-4 focus:ring-red-300 font-semibold rounded inline-flex items-center gap-1 [&>svg]:align-middle">
4-
{{ svg('trash') }} Clean cache
8+
class="text-sm py-1.5 px-3 text-white bg-sky-500 hover:bg-sky-600 focus:ring-4 focus:ring-sky-300 font-semibold rounded inline-flex items-center gap-1 [&>svg]:align-middle">
9+
{{ svg('reset') }} Reset cache
510
</button>
611
</div>
712

@@ -22,7 +27,7 @@
2227
{% if cached_scripts %}
2328
{% for script in cached_scripts %}
2429
<tr class="[&:last-child>*]:border-0" data-key="{{ script.invalidate_url }}">
25-
<td class="border-b border-gray-100 px-3 md:px-5 py-2 text-sm" title="{{ script.path }}">{{ script.name }}</td>
30+
<td class="border-b border-gray-100 px-3 md:px-5 py-2 text-sm cursor-pointer show-path">{{ script.name }}</td>
2631
<td class="border-b border-gray-100 px-3 md:px-5 py-2 text-sm">{{ script.hits }}</td>
2732
<td class="border-b border-gray-100 px-3 md:px-5 py-2 text-sm">{{ script.memory }}</td>
2833
<td class="hidden md:table-cell border-b border-gray-100 px-3 md:px-5 py-2 text-sm">{{ script.last_used }}</td>
@@ -31,10 +36,13 @@
3136
<button type="button" class="text-red-500 hover:text-red-700 font-semibold delete-key">Invalidate</button>
3237
</td>
3338
</tr>
39+
<tr class="hidden" data-path="{{ script.invalidate_url }}">
40+
<td colspan="6" class="border-b border-gray-100 px-3 md:px-5 py-2 text-sm">{{ script.path }}</td>
41+
</tr>
3442
{% endfor %}
3543
{% else %}
3644
<tr>
37-
<td colspan="5" class="text-center p-5">No cached scripts.</td>
45+
<td colspan="6" class="text-center p-5">No cached scripts.</td>
3846
</tr>
3947
{% endif %}
4048
</tbody>

0 commit comments

Comments
 (0)