'logs/repuve-nacional.log', 'padron-estatal' => 'logs/padron-estatal.log', ]; public function readRepuve(array $filters): array { return $this->read('repuve', $filters); } public function readPadronEstatal(array $filters): array { return $this->read('padron-estatal', $filters); } private function read(string $source, array $filters): array { $path = storage_path($this->sources[$source]); if (!is_file($path) || !is_readable($path)) { return []; } $entries = $this->parseFile($path); return $this->applyFilters($entries, $filters); } private function parseFile(string $path): array { $file = new SplFileObject($path, 'r'); $entries = []; $current = null; while (!$file->eof()) { $line = rtrim((string) $file->fgets(), "\r\n"); if ($line === '') { continue; } $header = $this->parseHeader($line); if ($header) { if ($current) { $entries[] = $this->sanitize($current); } $current = $header; continue; } if ($current) { $current['message'] .= "\n" . $line; } } if ($current) { $entries[] = $this->sanitize($current); } usort($entries, fn($a, $b) => strcmp($b['timestamp'], $a['timestamp'])); return $entries; } private function parseHeader(string $line): ?array { $pattern = '/^\[(?
[^\]]+)\]\s[^\.\s]+\.(?[A-Z]+):\s(?.*)$/'; if (!preg_match($pattern, $line, $m)) { return null; } try { $date = Carbon::parse($m['dt']); } catch (\Throwable $e) { return null; } return [ 'timestamp' => $date->toDateTimeString(), 'level' => strtolower($m['level']), 'message' => $m['message'], ]; } private function applyFilters(array $entries, array $filters): array { $start = !empty($filters['start_date']) ? Carbon::parse($filters['start_date'])->startOfDay() : null; $end = !empty($filters['end_date']) ? Carbon::parse($filters['end_date'])->endOfDay() : null; $level = $filters['level'] ?? null; return array_values(array_filter($entries, function (array $entry) use ($start, $end, $level) { $dt = Carbon::parse($entry['timestamp']); if ($start && $dt->lt($start)) { return false; } if ($end && $dt->gt($end)) { return false; } if ($level && $entry['level'] !== strtolower($level)) { return false; } return true; })); } private function sanitize(array $entry): array { $text = $entry['message']; $patterns = [ '/("password"\s*:\s*")[^"]*(")/i' => '$1***$2', '/("token"\s*:\s*")[^"]*(")/i' => '$1***$2', '/(authorization)\s*[:=]\s*([^,\s]+)/i' => '$1=***', '/()(.*?)(<\/arg0>)/i' => '$1***$3', '/()(.*?)(<\/arg1>)/i' => '$1***$3', ]; foreach ($patterns as $pattern => $replacement) { $text = preg_replace($pattern, $replacement, $text); } $entry['message'] = $text; return $entry; } }