logDir = __DIR__ . '/../../storage/logs'; $this->context = $context; if (!is_dir($this->logDir)) { mkdir($this->logDir, 0755, true); } } public function info(string $message, array $extra = []): void { $this->write(self::INFO, $message, $extra); } public function warning(string $message, array $extra = []): void { $this->write(self::WARNING, $message, $extra); } public function error(string $message, array $extra = []): void { $this->write(self::ERROR, $message, $extra); } private function write(string $level, string $message, array $extra = []): void { $date = date('Y-m-d'); $file = "{$this->logDir}/{$date}.log"; $time = date('Y-m-d H:i:s'); $ip = $this->getClientIp(); $extraStr = empty($extra) ? '' : ' ' . json_encode($extra, JSON_UNESCAPED_UNICODE); $line = "[{$time}] [{$level}] [{$this->context}] [{$ip}] {$message}{$extraStr}" . PHP_EOL; file_put_contents($file, $line, FILE_APPEND | LOCK_EX); } private function getClientIp(): string { foreach (['HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR'] as $key) { if (!empty($_SERVER[$key])) { $ip = trim(explode(',', $_SERVER[$key])[0]); if (filter_var($ip, FILTER_VALIDATE_IP)) { return $ip; } } } return 'unknown'; } public static function cleanOldLogs(int $keepDays = 30): void { $logDir = __DIR__ . '/../../storage/logs'; if (!is_dir($logDir)) { return; } foreach (glob("{$logDir}/*.log") as $file) { if (filemtime($file) < time() - ($keepDays * 86400)) { unlink($file); } } } }