149 lines
3.9 KiB
PHP
Executable File
149 lines
3.9 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace ServerManager\Core;
|
|
|
|
class Logger
|
|
{
|
|
private static ?Logger $instance = null;
|
|
private string $logPath;
|
|
private string $logLevel;
|
|
private array $levels = [
|
|
'debug' => 0,
|
|
'info' => 1,
|
|
'notice' => 2,
|
|
'warning' => 3,
|
|
'error' => 4,
|
|
'critical' => 5,
|
|
'alert' => 6,
|
|
'emergency' => 7,
|
|
];
|
|
|
|
private function __construct()
|
|
{
|
|
}
|
|
|
|
public static function getInstance(): self
|
|
{
|
|
if (self::$instance === null) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public static function init(string $path, string $level = 'warning'): void
|
|
{
|
|
$instance = self::getInstance();
|
|
$instance->logPath = rtrim($path, '/') . '/';
|
|
$instance->logLevel = $level;
|
|
|
|
if (!is_dir($instance->logPath)) {
|
|
mkdir($instance->logPath, 0750, true);
|
|
}
|
|
|
|
if (!is_writable($instance->logPath)) {
|
|
throw new \RuntimeException("Log path is not writable: {$instance->logPath}");
|
|
}
|
|
}
|
|
|
|
public function log(string $level, string $message, array $context = []): void
|
|
{
|
|
if (!$this->shouldLog($level)) {
|
|
return;
|
|
}
|
|
|
|
$timestamp = date('Y-m-d H:i:s');
|
|
$contextJson = !empty($context) ? ' ' . json_encode($context, JSON_UNESCAPED_SLASHES) : '';
|
|
$userInfo = $this->getUserInfo();
|
|
|
|
$logEntry = sprintf(
|
|
"[%s] %s.%s: %s%s %s\n",
|
|
$timestamp,
|
|
strtoupper($level),
|
|
$userInfo,
|
|
$message,
|
|
$contextJson,
|
|
$this->getRequestInfo()
|
|
);
|
|
|
|
$this->write($level, $logEntry);
|
|
}
|
|
|
|
public function debug(string $message, array $context = []): void
|
|
{
|
|
$this->log('debug', $message, $context);
|
|
}
|
|
|
|
public function info(string $message, array $context = []): void
|
|
{
|
|
$this->log('info', $message, $context);
|
|
}
|
|
|
|
public function notice(string $message, array $context = []): void
|
|
{
|
|
$this->log('notice', $message, $context);
|
|
}
|
|
|
|
public function warning(string $message, array $context = []): void
|
|
{
|
|
$this->log('warning', $message, $context);
|
|
}
|
|
|
|
public function error(string $message, array $context = []): void
|
|
{
|
|
$this->log('error', $message, $context);
|
|
}
|
|
|
|
public function critical(string $message, array $context = []): void
|
|
{
|
|
$this->log('critical', $message, $context);
|
|
}
|
|
|
|
public function alert(string $message, array $context = []): void
|
|
{
|
|
$this->log('alert', $message, $context);
|
|
}
|
|
|
|
public function emergency(string $message, array $context = []): void
|
|
{
|
|
$this->log('emergency', $message, $context);
|
|
}
|
|
|
|
private function shouldLog(string $level): bool
|
|
{
|
|
$currentLevel = $this->levels[$this->logLevel] ?? 3;
|
|
$messageLevel = $this->levels[$level] ?? 3;
|
|
return $messageLevel >= $currentLevel;
|
|
}
|
|
|
|
private function write(string $level, string $entry): void
|
|
{
|
|
$filename = $this->logPath . 'app-' . date('Y-m-d') . '.log';
|
|
file_put_contents($filename, $entry, FILE_APPEND | LOCK_EX);
|
|
|
|
if (in_array($level, ['error', 'critical', 'alert', 'emergency'], true)) {
|
|
$errorFile = $this->logPath . 'error-' . date('Y-m-d') . '.log';
|
|
file_put_contents($errorFile, $entry, FILE_APPEND | LOCK_EX);
|
|
}
|
|
}
|
|
|
|
private function getUserInfo(): string
|
|
{
|
|
$userId = Session::get('user_id');
|
|
$username = Session::get('username');
|
|
if ($userId) {
|
|
return "[User:{$userId}:{$username}]";
|
|
}
|
|
return '[Guest]';
|
|
}
|
|
|
|
private function getRequestInfo(): string
|
|
{
|
|
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
|
$method = $_SERVER['REQUEST_METHOD'] ?? 'CLI';
|
|
$uri = $_SERVER['REQUEST_URI'] ?? '';
|
|
return "[{$ip}] [{$method} {$uri}]";
|
|
}
|
|
}
|