driver = $driver ?? config('cache.default'); } /** * Obtiene estadísticas de caché para el driver especificado. */ public function getCacheStats(string $driver = null): array { $driver = $driver ?? $this->driver; if (!$this->isSupportedDriver($driver)) { return $this->response('warning', 'Driver no soportado o no configurado.'); } try { return match ($driver) { 'database' => $this->_getDatabaseStats(), 'file' => $this->_getFilecacheStats(), 'redis' => $this->_getRedisStats(), 'memcached' => $this->_getMemcachedStats(), default => $this->response('info', 'No hay estadísticas disponibles para este driver.'), }; } catch (\Exception $e) { return $this->response('danger', 'Error al obtener estadísticas: ' . $e->getMessage()); } } public function clearCache(string $driver = null): array { $driver = $driver ?? $this->driver; if (!$this->isSupportedDriver($driver)) { return $this->response('warning', 'Driver no soportado o no configurado.'); } try { switch ($driver) { case 'redis': $keysCleared = $this->clearRedisCache(); return $keysCleared ? $this->response('warning', 'Se ha purgado toda la caché de Redis.') : $this->response('info', 'No se encontraron claves en Redis para eliminar.'); case 'memcached': $keysCleared = $this->clearMemcachedCache(); return $keysCleared ? $this->response('warning', 'Se ha purgado toda la caché de Memcached.') : $this->response('info', 'No se encontraron claves en Memcached para eliminar.'); case 'database': $rowsDeleted = $this->clearDatabaseCache(); return $rowsDeleted ? $this->response('warning', 'Se ha purgado toda la caché almacenada en la base de datos.') : $this->response('info', 'No se encontraron registros en la caché de la base de datos.'); case 'file': $filesDeleted = $this->clearFilecache(); return $filesDeleted ? $this->response('warning', 'Se ha purgado toda la caché de archivos.') : $this->response('info', 'No se encontraron archivos en la caché para eliminar.'); default: Cache::flush(); return $this->response('warning', 'Caché purgada.'); } } catch (\Exception $e) { return $this->response('danger', 'Error al limpiar la caché: ' . $e->getMessage()); } } public function getRedisStats() { try { if (!Redis::ping()) { return $this->response('warning', 'No se puede conectar con el servidor Redis.'); } $info = Redis::info(); $databases = $this->getRedisDatabases(); $redisInfo = [ 'server' => config('database.redis.default.host'), 'redis_version' => $info['redis_version'] ?? 'N/A', 'os' => $info['os'] ?? 'N/A', 'tcp_port' => $info['tcp_port'] ?? 'N/A', 'connected_clients' => $info['connected_clients'] ?? 'N/A', 'blocked_clients' => $info['blocked_clients'] ?? 'N/A', 'maxmemory' => $info['maxmemory'] ?? 0, 'used_memory_human' => $info['used_memory_human'] ?? 'N/A', 'used_memory_peak' => $info['used_memory_peak'] ?? 'N/A', 'used_memory_peak_human' => $info['used_memory_peak_human'] ?? 'N/A', 'total_system_memory' => $info['total_system_memory'] ?? 0, 'total_system_memory_human' => $info['total_system_memory_human'] ?? 'N/A', 'maxmemory_human' => $info['maxmemory_human'] !== '0B' ? $info['maxmemory_human'] : 'Sin Límite', 'total_connections_received' => number_format($info['total_connections_received']) ?? 'N/A', 'total_commands_processed' => number_format($info['total_commands_processed']) ?? 'N/A', 'maxmemory_policy' => $info['maxmemory_policy'] ?? 'N/A', 'role' => $info['role'] ?? 'N/A', 'cache_database' => '', 'sessions_database' => '', 'general_database' => ',', 'keys' => $databases['total_keys'], 'used_memory' => $info['used_memory'] ?? 0, 'uptime' => gmdate('H\h i\m s\s', $info['uptime_in_seconds'] ?? 0), 'databases' => $databases, ]; return $this->response('success', 'Se a recargado las estadísticas de Redis.', ['info' => $redisInfo]); } catch (\Exception $e) { return $this->response('danger', 'Error al conectar con el servidor Redis: ' . Redis::getLastError()); } } public function getMemcachedStats() { try { $memcachedStats = []; // Crear instancia del cliente Memcached $memcached = new \Memcached(); $memcached->addServer(config('memcached.host'), config('memcached.port')); // Obtener estadísticas del servidor $stats = $memcached->getStats(); foreach ($stats as $server => $data) { $server = explode(':', $server); $memcachedStats[] = [ 'server' => $server[0], 'tcp_port' => $server[1], 'uptime' => $data['uptime'] ?? 'N/A', 'version' => $data['version'] ?? 'N/A', 'libevent' => $data['libevent'] ?? 'N/A', 'max_connections' => $data['max_connections'] ?? 0, 'total_connections' => $data['total_connections'] ?? 0, 'rejected_connections' => $data['rejected_connections'] ?? 0, 'curr_items' => $data['curr_items'] ?? 0, // Claves almacenadas 'bytes' => $data['bytes'] ?? 0, // Memoria usada 'limit_maxbytes' => $data['limit_maxbytes'] ?? 0, // Memoria máxima 'cmd_get' => $data['cmd_get'] ?? 0, // Comandos GET ejecutados 'cmd_set' => $data['cmd_set'] ?? 0, // Comandos SET ejecutados 'get_hits' => $data['get_hits'] ?? 0, // GET exitosos 'get_misses' => $data['get_misses'] ?? 0, // GET fallidos 'evictions' => $data['evictions'] ?? 0, // Claves expulsadas 'bytes_read' => $data['bytes_read'] ?? 0, // Bytes leídos 'bytes_written' => $data['bytes_written'] ?? 0, // Bytes escritos 'total_items' => $data['total_items'] ?? 0, ]; } return $this->response('success', 'Se a recargado las estadísticas de Memcached.', ['info' => $memcachedStats]); } catch (\Exception $e) { return $this->response('danger', 'Error al conectar con el servidor Memcached: ' . $e->getMessage()); } } /** * Obtiene estadísticas para caché en base de datos. */ private function _getDatabaseStats(): array { try { $recordCount = DB::table('cache')->count(); $tableInfo = DB::select("SHOW TABLE STATUS WHERE Name = 'cache'"); $memory_usage = isset($tableInfo[0]) ? $this->formatBytes($tableInfo[0]->Data_length + $tableInfo[0]->Index_length) : 'N/A'; return $this->response('success', 'Se ha recargado la información de la caché de base de datos.', ['item_count' => $recordCount, 'memory_usage' => $memory_usage]); } catch (\Exception $e) { return $this->response('danger', 'Error al obtener estadísticas de la base de datos: ' . $e->getMessage()); } } /** * Obtiene estadísticas para caché en archivos. */ private function _getFilecacheStats(): array { try { $cachePath = config('cache.stores.file.path'); $files = glob($cachePath . '/*'); $memory_usage = $this->formatBytes(array_sum(array_map('filesize', $files))); return $this->response('success', 'Se ha recargado la información de la caché de archivos.', ['item_count' => count($files), 'memory_usage' => $memory_usage]); } catch (\Exception $e) { return $this->response('danger', 'Error al obtener estadísticas de archivos: ' . $e->getMessage()); } } private function _getRedisStats() { try { $prefix = config('cache.prefix'); // Asegúrate de agregar el sufijo correcto si es necesario $info = Redis::info(); $keys = Redis::connection('cache')->keys($prefix . '*'); $memory_usage = $this->formatBytes($info['used_memory'] ?? 0); return $this->response('success', 'Se ha recargado la información de la caché de Redis.', ['item_count' => count($keys), 'memory_usage' => $memory_usage]); } catch (\Exception $e) { return $this->response('danger', 'Error al obtener estadísticas de Redis: ' . $e->getMessage()); } } public function _getMemcachedStats(): array { try { // Obtener estadísticas generales del servidor $stats = Cache::getStore()->getMemcached()->getStats(); if (empty($stats)) { return $this->response('error', 'No se pudieron obtener las estadísticas del servidor Memcached.', ['item_count' => 0, 'memory_usage' => 0]); } // Usar el primer servidor configurado (en la mayoría de los casos hay uno) $serverStats = array_shift($stats); return $this->response( 'success', 'Estadísticas del servidor Memcached obtenidas correctamente.', [ 'item_count' => $serverStats['curr_items'] ?? 0, // Número total de claves 'memory_usage' => $this->formatBytes($serverStats['bytes'] ?? 0), // Memoria usada 'max_memory' => $this->formatBytes($serverStats['limit_maxbytes'] ?? 0), // Memoria máxima asignada ] ); } catch (\Exception $e) { return $this->response('danger', 'Error al obtener estadísticas de Memcached: ' . $e->getMessage()); } } private function getRedisDatabases(): array { // Verificar si Redis está en uso $isRedisUsed = collect([ config('cache.default'), config('session.driver'), config('queue.default'), ])->contains('redis'); if (!$isRedisUsed) { return []; // Si Redis no está en uso, devolver un arreglo vacío } // Configuraciones de bases de datos de Redis según su uso $databases = [ 'default' => config('database.redis.default.database', 0), // REDIS_DB 'cache' => config('database.redis.cache.database', 0), // REDIS_CACHE_DB 'sessions' => config('database.redis.sessions.database', 0), // REDIS_SESSION_DB ]; $result = []; $totalKeys = 0; // Recorrer solo las bases configuradas y activas foreach ($databases as $type => $db) { Redis::select($db); // Seleccionar la base de datos $keys = Redis::dbsize(); // Contar las claves en la base if ($keys > 0) { $result[$type] = [ 'database' => $db, 'keys' => $keys, ]; $totalKeys += $keys; } } if (!empty($result)) { $result['total_keys'] = $totalKeys; } return $result; } private function clearDatabaseCache(): bool { $count = DB::table(config('cache.stores.database.table'))->count(); if ($count > 0) { DB::table(config('cache.stores.database.table'))->truncate(); return true; } return false; } private function clearFilecache(): bool { $cachePath = config('cache.stores.file.path'); $files = glob($cachePath . '/*'); if (!empty($files)) { File::deleteDirectory($cachePath); return true; } return false; } private function clearRedisCache(): bool { $prefix = config('cache.prefix', ''); $keys = Redis::connection('cache')->keys($prefix . '*'); if (!empty($keys)) { Redis::connection('cache')->flushdb(); // Simulate cache clearing delay sleep(1); return true; } return false; } private function clearMemcachedCache(): bool { // Obtener el cliente Memcached directamente $memcached = Cache::store('memcached')->getStore()->getMemcached(); // Ejecutar flush para eliminar todo if ($memcached->flush()) { // Simulate cache clearing delay sleep(1); return true; } return false; } /** * Verifica si un driver es soportado. */ private function isSupportedDriver(string $driver): bool { return in_array($driver, ['redis', 'memcached', 'database', 'file']); } /** * Convierte bytes en un formato legible. */ private function formatBytes($bytes) { $sizes = ['B', 'KB', 'MB', 'GB', 'TB']; $factor = floor((strlen($bytes) - 1) / 3); return sprintf('%.2f', $bytes / pow(1024, $factor)) . ' ' . $sizes[$factor]; } /** * Genera una respuesta estandarizada. */ private function response(string $status, string $message, array $data = []): array { return array_merge(compact('status', 'message'), $data); } }