139 lines
3.6 KiB
PHP
139 lines
3.6 KiB
PHP
<?php namespace App\Services;
|
|
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Arr;
|
|
use SplFileObject;
|
|
|
|
class LogsService
|
|
{
|
|
private array $sources = [
|
|
'repuve' => '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 = '/^\[(?<dt>[^\]]+)\]\s[^\.\s]+\.(?<level>[A-Z]+):\s(?<message>.*)$/';
|
|
|
|
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>)(.*?)(<\/arg0>)/i' => '$1***$3',
|
|
'/(<arg1>)(.*?)(<\/arg1>)/i' => '$1***$3',
|
|
];
|
|
|
|
foreach ($patterns as $pattern => $replacement) {
|
|
$text = preg_replace($pattern, $replacement, $text);
|
|
}
|
|
|
|
$entry['message'] = $text;
|
|
|
|
return $entry;
|
|
}
|
|
} |