- Enhance logging handlers (Console, DockerJson, File, JsonFile, MultiFile) - Improve exception and line formatters - Update logger initialization and processor management - Add Ansible playbooks for staging 502 error troubleshooting - Update deployment documentation - Fix serializer and queue components - Update error kernel and queued log handler
159 lines
4.4 KiB
PHP
159 lines
4.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Framework\Logging\Handlers;
|
|
|
|
use App\Framework\Config\Environment;
|
|
use App\Framework\Core\PathProvider;
|
|
use App\Framework\Logging\LogHandler;
|
|
use App\Framework\Logging\Formatter\JsonFormatter;
|
|
use App\Framework\Logging\Formatter\LogFormatter;
|
|
use App\Framework\Logging\LogLevel;
|
|
use App\Framework\Logging\LogRecord;
|
|
|
|
/**
|
|
* Handler für die Ausgabe von Log-Einträgen als JSON in Dateien.
|
|
* Besonders nützlich für maschinelle Verarbeitung und Log-Aggregatoren.
|
|
*
|
|
* Nutzt JsonFormatter für einheitliche JSON-Ausgabe.
|
|
*
|
|
* Standard-Felder für Log-Aggregatoren:
|
|
* - @timestamp: Elasticsearch-konformes Zeitstempelfeld
|
|
* - severity: RFC 5424 Severity Level (0-7)
|
|
* - environment: Deployment-Umgebung (production, staging, development)
|
|
* - host: Server-Hostname
|
|
* - service: Service-/Anwendungsname
|
|
*/
|
|
class JsonFileHandler implements LogHandler
|
|
{
|
|
/**
|
|
* @var LogLevel Minimales Level, ab dem dieser Handler aktiv wird
|
|
*/
|
|
private LogLevel $minLevel;
|
|
|
|
/**
|
|
* @var string Pfad zur Log-Datei
|
|
*/
|
|
private string $logFile;
|
|
|
|
/**
|
|
* @var JsonFormatter Formatter für die JSON-Ausgabe
|
|
*/
|
|
private JsonFormatter $formatter;
|
|
|
|
/**
|
|
* @var PathProvider|null PathProvider für die Auflösung von Pfaden
|
|
*/
|
|
private ?PathProvider $pathProvider = null;
|
|
|
|
/**
|
|
* Erstellt einen neuen JsonFileHandler
|
|
*
|
|
* @param JsonFormatter $formatter Formatter für die JSON-Ausgabe
|
|
* @param string $logFile Pfad zur Log-Datei
|
|
* @param LogLevel|int $minLevel Minimales Level, ab dem dieser Handler aktiv wird
|
|
* @param PathProvider|null $pathProvider Optional: PathProvider für die Auflösung von Pfaden
|
|
*/
|
|
public function __construct(
|
|
JsonFormatter $formatter,
|
|
string $logFile,
|
|
LogLevel|int $minLevel = LogLevel::INFO,
|
|
?PathProvider $pathProvider = null
|
|
) {
|
|
$this->pathProvider = $pathProvider;
|
|
$this->formatter = $formatter;
|
|
|
|
// Pfad auflösen, falls PathProvider vorhanden
|
|
if ($this->pathProvider !== null && ! str_starts_with($logFile, '/')) {
|
|
$logFile = $this->pathProvider->resolvePath($logFile);
|
|
}
|
|
|
|
$this->logFile = $logFile;
|
|
$this->minLevel = $minLevel instanceof LogLevel ? $minLevel : LogLevel::fromValue($minLevel);
|
|
|
|
// Stelle sicher, dass das Verzeichnis existiert
|
|
$this->ensureDirectoryExists(dirname($logFile));
|
|
}
|
|
|
|
/**
|
|
* Überprüft, ob dieser Handler den Log-Eintrag verarbeiten soll
|
|
*/
|
|
public function isHandling(LogRecord $record): bool
|
|
{
|
|
return $record->getLevel()->value >= $this->minLevel->value;
|
|
}
|
|
|
|
/**
|
|
* Verarbeitet einen Log-Eintrag
|
|
*/
|
|
public function handle(LogRecord $record): void
|
|
{
|
|
// Formatter verwenden für JSON-Formatierung
|
|
$json = ($this->formatter)($record);
|
|
|
|
// JsonFormatter gibt immer string zurück
|
|
$output = is_string($json) ? $json : json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
|
|
|
|
// Stelle sicher, dass ein Newline vorhanden ist
|
|
if (!str_ends_with($output, PHP_EOL)) {
|
|
$output .= PHP_EOL;
|
|
}
|
|
|
|
$this->write($output);
|
|
}
|
|
|
|
/**
|
|
* Gibt den Formatter zurück
|
|
*/
|
|
public function getFormatter(): LogFormatter
|
|
{
|
|
return $this->formatter;
|
|
}
|
|
|
|
/**
|
|
* Schreibt einen String in die Log-Datei
|
|
*/
|
|
protected function write(string $output): void
|
|
{
|
|
file_put_contents($this->logFile, $output, FILE_APPEND);
|
|
}
|
|
|
|
/**
|
|
* Stellt sicher, dass ein Verzeichnis existiert
|
|
*/
|
|
private function ensureDirectoryExists(string $dir): void
|
|
{
|
|
if (! file_exists($dir)) {
|
|
mkdir($dir, 0777, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Minimales Log-Level setzen
|
|
*/
|
|
public function setMinLevel(LogLevel|int $level): self
|
|
{
|
|
$this->minLevel = $level instanceof LogLevel ? $level : LogLevel::fromValue($level);
|
|
|
|
return $this;
|
|
}
|
|
|
|
|
|
/**
|
|
* Log-Datei setzen
|
|
*/
|
|
public function setLogFile(string $logFile): self
|
|
{
|
|
// Pfad auflösen, falls PathProvider vorhanden
|
|
if ($this->pathProvider !== null && ! str_starts_with($logFile, '/')) {
|
|
$logFile = $this->pathProvider->resolvePath($logFile);
|
|
}
|
|
|
|
$this->logFile = $logFile;
|
|
$this->ensureDirectoryExists(dirname($logFile));
|
|
|
|
return $this;
|
|
}
|
|
}
|