©Sergey Emelyanov 2025 | Alle Rechte vorbehalten
Im Rahmen der PSR-3 Spezifikation spielt der Kontext (context) eine zentrale Rolle. Obwohl viele Entwickler den Parameter $context missbrauchen oder falsch interpretieren, regelt der Standard klar, wie dieser genutzt werden soll. Der Schlüssel liegt darin, dass der Kontext dazu dient, alle zusätzlichen Informationen zu übergeben, die nicht gut in einen reinen Text passen. In diesem Artikel werfen wir einen detaillierten Blick auf den richtigen Umgang mit $context im PSR-3 Logger.
Laut Standard (Abschnitt 1.3.1) akzeptiert jede Log-Methode ein Array als Kontextdaten. Dieses Array kann beliebige Werte enthalten – von Skalarwerten über Arrays bis hin zu Objekten, Closures und Ressourcen. Wichtig ist: Der Implementierer MUSS darauf achten, dass Werte im Kontext keine Fehler, Warnungen oder Notices auslösen. Entwickler sollen also keine eigene Normalisierung vornehmen, denn genau das übernimmt der Logger selbst. Beispielsweise verarbeitet Monolog komplexe Elemente, wie Objekte oder Closures, nachdem sie in ein standardisiertes Format umgewandelt wurden:
Beispiel aus Monolog:
$logger = new Monolog\Logger(
name: 'app',
handlers: [new Monolog\Handler\StreamHandler(STDOUT)],
processors: [new Monolog\Processor\PsrLogMessageProcessor()]
);
final readonly class Foo
{
public function __construct(
public string $public = 'bar',
private string $private = 'baz',
) {}
}
$logger->debug('Message', [
'birthday' => new DateTimeImmutable('06.04.2019'),
'object' => new Foo(),
'closure' => static fn (): int => 1,
'resource' => STDIN,
]);
Das Ergebnis zeigt, dass komplexe Daten strukturiert und lesbar ausgegeben werden.
Ein weiterer zentraler Punkt im Standard (siehe Abschnitt 1.2.2) ist die Verwendung von Platzhaltern in der Log-Nachricht. Platzhalter sollen mit einem einzelnen öffnenden { und schließenden } Zeichen umschlossen sein – etwa so: {pid} oder {time}. Die Schlüssel im Kontextarray müssen genau diesen Platzhaltern entsprechen.
Beispiel:
$logger->notice('Process {pid} started at {time}', [
'pid' => getmypid(),
'time' => new DateTimeImmutable(),
]);
Hier wird der Platzhalter {pid} durch den Wert der getmypid()-Funktion ersetzt und {time} durch das Datum aus DateTimeImmutable. Diese Methode verhindert die Notwendigkeit von sprintf oder manueller Stringinterpolation.
Ein häufig auftretender Fehler beim Loggen ist die unsachgemäße Behandlung von Exceptions. Laut PSR-3 (Abschnitt 1.3.2) MUSS ein Exception-Objekt im Kontext immer unter dem Schlüssel "exception" übergeben werden. Dadurch kann der Logger, falls unterstützt, den kompletten Stacktrace extrahieren. Es ist grundsätzlich zu vermeiden, die Exception-Information manuell in ein Array zu zerschlagen (z. B. mit 'message', 'line', etc.), da Prozessoren und Formatter die Entscheidung über Detailtiefe und Format selbst treffen sollten.
Beispiel:
$logger->critical('Oops!', [
'exception' => new LogicException(
message: 'Level 2',
previous: new RuntimeException('Level 1'),
),
]);
Dadurch wird sichergestellt, dass der Logger die Exception in seiner vollen Komplexität verarbeiten kann.
PSR-3 erlaubt es, im Kontext beliebige Werte zu übergeben. Das bedeutet, dass Sie sowohl einfache Skalare als auch komplexe Objekte, Closures, Arrays oder Ressourcen übergeben können. Der Vorteil ist, dass der Kontext alle zusätzlichen Informationen einschließen kann, die nicht direkt in die Lognachricht passen. Dabei übernimmt der Logger – theoretisch – die Normalisierung. Es liegt in der Verantwortung der Logger-Implementierung, diese Werte korrekt zu behandeln, ohne Fehler auszulösen.
Der Kontext im PSR-3 Logger ist ein mächtiges Instrument zur Übermittlung von Zusatzinformationen. Die wesentlichen Punkte sind:
Indem Sie diese Best Practices befolgen, stellen Sie sicher, dass Ihre Log-Ausgaben konsistent, informativ und robust gegenüber unerwarteten Datentypen bleiben. So tragen Sie nicht nur zur besseren Fehlersuche und Analyse bei, sondern unterstützen auch die Kompatibilität mit anderen PSR-3 konformen Loggern.
©Sergey Emelyanov 2025 | Alle Rechte vorbehalten