mirror of
https://github.com/wavelog/wavelog.git
synced 2026-03-22 10:24:14 +00:00
alpha version of cache debug information
This commit is contained in:
@@ -105,6 +105,9 @@ class Debug extends CI_Controller
|
||||
$data['userdata_status'] = $userdata_status;
|
||||
}
|
||||
|
||||
// Cache Info
|
||||
$data['cache_info'] = $this->debug_model->get_cache_info();
|
||||
|
||||
$data['dxcc_update'] = $this->cron_model->cron('update_dxcc')->row();
|
||||
$data['dok_update'] = $this->cron_model->cron('update_update_dok')->row();
|
||||
$data['lotw_user_update'] = $this->cron_model->cron('update_lotw_users')->row();
|
||||
@@ -288,6 +291,22 @@ class Debug extends CI_Controller
|
||||
echo json_encode($commit_hash);
|
||||
}
|
||||
|
||||
public function clear_cache() {
|
||||
$this->load->model('user_model');
|
||||
if ($this->user_model->authorize(2) == false) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => false, 'message' => __("You're not allowed to do that!")]);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->load->model('Debug_model');
|
||||
$status = $this->Debug_model->clear_cache();
|
||||
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['status' => (bool) $status]);
|
||||
return;
|
||||
}
|
||||
|
||||
public function migrate_userdata() {
|
||||
// Check if users logged in
|
||||
$this->load->model('user_model');
|
||||
|
||||
@@ -185,4 +185,261 @@ class Debug_model extends CI_Model
|
||||
$result = $query->result_array();
|
||||
return $result;
|
||||
}
|
||||
|
||||
function get_cache_info() {
|
||||
|
||||
$response = [];
|
||||
|
||||
$cache_path = $this->config->item('cache_path') ?? NULL;
|
||||
if (!$cache_path && $cache_path !== '') {
|
||||
$cache_path = ''; // default path is application/cache
|
||||
$response['config']['cache_path'] = sprintf(__(" %s not set in config, using default path: %s"), "'cache_path'", "application/cache");
|
||||
} else {
|
||||
$response['config']['cache_path'] = $cache_path;
|
||||
}
|
||||
|
||||
$cache_adapter = $this->config->item('cache_adapter') ?? NULL;
|
||||
if (!$cache_adapter) {
|
||||
$cache_adapter = 'file'; // default adapter is file
|
||||
$response['config']['cache_adapter'] = sprintf(__(" %s not set in config, using default adapter: %s"), "'cache_adapter'", "file");
|
||||
} else {
|
||||
$response['config']['cache_adapter'] = $cache_adapter;
|
||||
}
|
||||
|
||||
$cache_backup = $this->config->item('cache_backup') ?? NULL;
|
||||
if (!$cache_backup) {
|
||||
$cache_backup = 'file'; // default backup is file
|
||||
$response['config']['cache_backup'] = sprintf(__(" %s not set in config, using default backup: %s"), "'cache_backup'", "file");
|
||||
} else {
|
||||
$response['config']['cache_backup'] = $cache_backup;
|
||||
}
|
||||
|
||||
$cache_key_prefix = $this->config->item('cache_key_prefix') ?? NULL;
|
||||
if (!$cache_key_prefix) {
|
||||
$cache_key_prefix = ''; // default key prefix is empty
|
||||
$response['config']['cache_key_prefix'] = sprintf(__(" %s not set in config, using default: empty string %s"), "'cache_key_prefix'", "('')");
|
||||
} else {
|
||||
$response['config']['cache_key_prefix'] = $cache_key_prefix;
|
||||
}
|
||||
|
||||
// Load cache driver
|
||||
$this->load->driver('cache', [
|
||||
'adapter' => $cache_adapter,
|
||||
'backup' => $cache_backup,
|
||||
'key_prefix' => $cache_key_prefix
|
||||
]);
|
||||
|
||||
// Get cache details
|
||||
$cache_size = $this->get_cache_size();
|
||||
$cache_keys_count = $this->get_cache_keys_count();
|
||||
|
||||
$response['details']['size'] = $this->format_bytes($cache_size);
|
||||
$response['details']['size_bytes'] = $cache_size;
|
||||
$response['details']['keys_count'] = $cache_keys_count;
|
||||
|
||||
$available_adapters = ['file', 'redis', 'memcached', 'apcu'];
|
||||
foreach ($available_adapters as $adapter) {
|
||||
$response['adapters'][$adapter] = $this->cache->is_supported($adapter);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function clear_cache() {
|
||||
$cache_adapter = $this->config->item('cache_adapter') ?? 'file';
|
||||
$cache_backup = $this->config->item('cache_backup') ?? 'file';
|
||||
$cache_key_prefix = $this->config->item('cache_key_prefix') ?? '';
|
||||
|
||||
$this->load->driver('cache', [
|
||||
'adapter' => $cache_adapter,
|
||||
'backup' => $cache_backup,
|
||||
'key_prefix' => $cache_key_prefix
|
||||
]);
|
||||
|
||||
if ($cache_adapter === 'file') {
|
||||
$cache_path = $this->config->item('cache_path') ?: 'application/cache';
|
||||
$cache_path = realpath(APPPATH . '../') . '/' . $cache_path;
|
||||
|
||||
if (!is_dir($cache_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($cache_path, RecursiveDirectoryIterator::SKIP_DOTS),
|
||||
RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
|
||||
foreach ($files as $file) {
|
||||
if ($file->isFile() && !in_array($file->getFilename(), ['index.html', '.htaccess'])) {
|
||||
@unlink($file->getRealPath());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (method_exists($this->cache, 'clean')) {
|
||||
return $this->cache->clean();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function get_cache_size($adapter = NULL) {
|
||||
$cache_adapter = $adapter ?? ($this->config->item('cache_adapter') ?? 'file');
|
||||
|
||||
switch ($cache_adapter) {
|
||||
case 'file':
|
||||
$cache_path = $this->config->item('cache_path') ?: 'application/cache';
|
||||
$cache_path = realpath(APPPATH . '../') . '/' . $cache_path;
|
||||
|
||||
if (!is_dir($cache_path)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$size = 0;
|
||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($cache_path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST);
|
||||
|
||||
foreach ($files as $file) {
|
||||
if ($file->isFile() && !in_array($file->getFilename(), ['index.html', '.htaccess'])) {
|
||||
$size += $file->getSize();
|
||||
}
|
||||
}
|
||||
|
||||
return $size;
|
||||
|
||||
case 'redis':
|
||||
if ($this->cache->is_supported('redis')) {
|
||||
$redis_info = $this->cache->cache_info('redis');
|
||||
// Note: This returns total Redis server memory usage, not just cache keys with prefix
|
||||
// used_memory_dataset excludes overhead and is more accurate for data size
|
||||
if (isset($redis_info['used_memory_dataset'])) {
|
||||
return (int)$redis_info['used_memory_dataset'];
|
||||
}
|
||||
return isset($redis_info['used_memory']) ? (int)$redis_info['used_memory'] : 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 'memcached':
|
||||
if ($this->cache->is_supported('memcached')) {
|
||||
$memcached_info = $this->cache->cache_info('memcached');
|
||||
log_message('debug', 'Memcached Info: ' . print_r($memcached_info, true));
|
||||
|
||||
// Memcached returns array of servers, each with stats
|
||||
if (is_array($memcached_info)) {
|
||||
$total_bytes = 0;
|
||||
foreach ($memcached_info as $server_stats) {
|
||||
if (is_array($server_stats)) {
|
||||
// bytes is the current bytes used in the cache
|
||||
if (isset($server_stats['bytes'])) {
|
||||
$total_bytes += (int) $server_stats['bytes'];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $total_bytes;
|
||||
}
|
||||
|
||||
// Fallback for single server format
|
||||
if (isset($memcached_info['bytes'])) {
|
||||
return (int) $memcached_info['bytes'];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 'apcu':
|
||||
if ($this->cache->is_supported('apcu')) {
|
||||
$apcu_info = apcu_cache_info();
|
||||
return isset($apcu_info['mem_size']) ? (int)$apcu_info['mem_size'] : 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function get_cache_keys_count($adapter = NULL) {
|
||||
$cache_adapter = $adapter ?? ($this->config->item('cache_adapter') ?? 'file');
|
||||
|
||||
switch ($cache_adapter) {
|
||||
case 'file':
|
||||
$cache_path = $this->config->item('cache_path') ?: 'application/cache';
|
||||
$cache_path = realpath(APPPATH . '../') . '/' . $cache_path;
|
||||
|
||||
if (!is_dir($cache_path)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($cache_path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST);
|
||||
|
||||
foreach ($files as $file) {
|
||||
if ($file->isFile() && !in_array($file->getFilename(), ['index.html', '.htaccess'])) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
|
||||
case 'redis':
|
||||
if ($this->cache->is_supported('redis')) {
|
||||
$redis_info = $this->cache->cache_info('redis');
|
||||
$total_keys = 0;
|
||||
// Parse keyspace info (db0, db1, etc.)
|
||||
foreach ($redis_info as $key => $value) {
|
||||
if (preg_match('/^db(\d+)$/', $key) && is_string($value)) {
|
||||
// Parse "keys=4,expires=4,avg_ttl=43131246" format
|
||||
if (preg_match('/keys=(\d+)/', $value, $matches)) {
|
||||
$total_keys += (int)$matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $total_keys;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 'memcached':
|
||||
if ($this->cache->is_supported('memcached')) {
|
||||
$memcached_info = $this->cache->cache_info('memcached');
|
||||
if (isset($memcached_info['curr_items'])) {
|
||||
return (int) $memcached_info['curr_items'];
|
||||
}
|
||||
|
||||
if (is_array($memcached_info)) {
|
||||
$total_items = 0;
|
||||
foreach ($memcached_info as $server_stats) {
|
||||
if (is_array($server_stats) && isset($server_stats['curr_items'])) {
|
||||
$total_items += (int) $server_stats['curr_items'];
|
||||
}
|
||||
}
|
||||
return $total_items;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 'apcu':
|
||||
if ($this->cache->is_supported('apcu')) {
|
||||
$apcu_info = apcu_cache_info();
|
||||
return isset($apcu_info['num_entries']) ? (int)$apcu_info['num_entries'] : 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function format_bytes($bytes, $precision = 2) {
|
||||
$units = ['B', 'KB', 'MB', 'GB'];
|
||||
$bytes = max($bytes, 0);
|
||||
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
||||
$pow = min($pow, count($units) - 1);
|
||||
$bytes /= (1 << (10 * $pow));
|
||||
|
||||
return round($bytes, $precision) . ' ' . $units[$pow];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,6 +399,74 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Cache Information Card -->
|
||||
<div class="card">
|
||||
<div class="card-header"><?= __("Cache Configuration"); ?></div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<p><u><?= __("Current Configuration"); ?></u></p>
|
||||
<table width="100%" class="table table-sm table-striped">
|
||||
<tr>
|
||||
<td><strong><?= __("Adapter"); ?></strong></td>
|
||||
<td>
|
||||
<span class="badge text-bg-info"><?php echo ucfirst($cache_info['config']['cache_adapter'] ?? 'file'); ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?= __("Backup"); ?></strong></td>
|
||||
<td>
|
||||
<span class="badge text-bg-secondary"><?php echo ucfirst($cache_info['config']['cache_backup'] ?? 'file'); ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?= __("Path"); ?></strong></td>
|
||||
<td><code><?php echo $cache_info['config']['cache_path'] ?: 'application/cache'; ?></code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?= __("Key Prefix"); ?></strong></td>
|
||||
<td><code><?php echo $cache_info['config']['cache_key_prefix'] ?: __("(empty)"); ?></code></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p><u><?= __("Cache Details"); ?></u></p>
|
||||
<table width="100%" class="table table-sm table-striped">
|
||||
<tr>
|
||||
<td><strong><?= __("Total Size"); ?></strong></td>
|
||||
<td>
|
||||
<span class="badge text-bg-primary"><?php echo $cache_info['details']['size'] ?? '0 B'; ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?= __("Number of Keys"); ?></strong></td>
|
||||
<td>
|
||||
<span class="badge text-bg-primary"><?php echo $cache_info['details']['keys_count'] ?? '0'; ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-end">
|
||||
<button type="button" id="clear_cache_button" class="btn btn-sm btn-danger">
|
||||
<?= __("Clear Cache"); ?>
|
||||
</button>
|
||||
</div>
|
||||
<div class="border-top pt-3 mt-3">
|
||||
<p><u><?= __("Available Adapters"); ?></u></p>
|
||||
<div>
|
||||
<?php foreach ($cache_info['adapters'] as $adapter => $supported) { ?>
|
||||
<?php if ($supported) { ?>
|
||||
<span class="badge text-bg-success"><?php echo ucfirst($adapter); ?></span>
|
||||
<?php } else { ?>
|
||||
<span class="badge text-bg-danger"><?php echo ucfirst($adapter); ?></span>
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- HIER -->
|
||||
<?php if (file_exists(realpath(APPPATH . '../') . '/.git') && function_usable('exec')) { ?>
|
||||
<?php
|
||||
//Below is a failsafe where git commands fail
|
||||
|
||||
@@ -101,3 +101,26 @@ function update_version_check(local_branch) {
|
||||
$('#last_version_check').text("Last version check: " + new Date(timestamp).toUTCString());
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#clear_cache_button').on('click', function () {
|
||||
if (!confirm('Cache wirklich löschen?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: base_url + 'index.php/debug/clear_cache',
|
||||
type: 'post',
|
||||
success: function (resu) {
|
||||
if (resu && resu.status) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Cache konnte nicht geleert werden.');
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
alert('Cache konnte nicht geleert werden.');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user