Bei der Entwicklung einer modernen Anwendung sollte die Protokollierung ganz oben auf der Prioritätenliste stehen.

Die Protokollierung bietet eine Möglichkeit, deine Anwendung sowohl in der Entwicklung als auch in der Produktion zu visualisieren und ermöglicht Transparenz und Sichtbarkeit. Mit einer gut strukturierten Protokollierung können moderne Anwendungen leichter gewartet werden, da wir proaktiv Fehlerstellen und Leistungsengpässe in unserer Anwendung erkennen können.

Das Laravel-Framework verfügt über ein robustes Logging-System, das alle Hürden bei der Konfiguration eines gut strukturierten Logging-Systems von Haus aus meistert. Dieses neue Logging-System, das mit Laravel 6.5 eingeführt wurde, ist sehr leistungsfähig und wir werden es in diesem Artikel genauer untersuchen.

In diesem Artikel geht es um die Grundlagen des Laravel-Loggings und warum du Laravel-Logging in deinem nächsten Projekt einsetzen solltest. Wir werden das strukturierte Logging und das zentralisierte Logging im Detail besprechen. Außerdem erfahren wir, wie du das Laravel-Logging implementierst, indem du eine Todo-Anwendung erstellst.

Du hast mehr von diesem Artikel, wenn du bereits über die folgenden Kenntnisse verfügst:

Was ist Laravel Logging?

Bei Laravel Logging geht es darum, wie Laravel das Logging oder die automatische Problemmeldung mit Hilfe eines viralen PHP-Logging-Systems namens Monolog handhabt. Aufgrund der Laravel-Philosophie, beliebte bestehende Bibliotheken für die Implementierung verschiedener Framework-Funktionen zu nutzen, verwendet Laravel Monolog für alle Logging-Anforderungen.

Monolog ist eine äußerst flexible und beliebte PHP-Logging-Bibliothek, die wir so konfigurieren können, dass sie deine Logs an Dateien, Sockets, Datenbanken und andere Webservices sendet. Monolog bietet eine vertraute Schnittstelle für das Schreiben von Logs aus Standard-Textdateien bis hin zu fortschrittlichen Log-Management-Diensten von Drittanbietern. Laravel richtet Monolog normalerweise so ein, dass es eine Standardkonfigurationsdatei für das Logging verwendet.

Weitere Informationen über Monolog und seine Funktionen findest du in der offiziellen Dokumentation, da dies den Rahmen dieses Artikels sprengen würde.

Bevor wir uns mit der Konfiguration und Implementierung des Laravel-Loggings mit Monolog beschäftigen, wollen wir mehr über die Gründe für die Verwendung des Laravel-Loggings und die verschiedenen Arten erfahren.

Warum Laravel Logging verwenden?

Warum ist Logging notwendig?

Im Manifest der Zwölf-Faktoren-App wird das Logging als eines der wichtigsten Anliegen einer modernen Anwendung behandelt, da Logging ein Schlüssel zur Leistung und Überwachung ist.

Logs helfen dabei, Fehler, die in der Produktion auftreten, im Detail zu verstehen und herauszufinden, woher sie kommen. Mit den richtigen Log-Strukturen können sie außerdem den jeweiligen Nutzer, die Aktion, die den Fehler verursacht hat, und die mögliche Lösung für eine schnellere Fehlerbehebung und Wartung aufzeigen.

Die strukturierte Protokollierung ist ein Lebensretter in Produktionsanwendungen, denn sie hilft bei der Fehlersuche und der Lösung von Problemen in der Produktion. Außerdem kannst du alle deine Log-Meldungen in Echtzeit mit speziellen Logging-Tools für Live-Analysen und Berichte überwachen und sammeln.

Aus diesen Gründen solltest du der strukturierten Protokollierung bei deinem nächsten modernen Anwendungsprojekt oberste Priorität einräumen.

Schauen wir uns einen Überblick über die verschiedenen Logging-Stile an.

Grundlagen des Laravel-Loggings

Wenn du die Grundlagen des Loggings kennst, wirst du verstehen, wie Laravel das Logging handhabt und wie du deine strukturierten Logging-Praktiken verbessern kannst.

Schauen wir uns zwei wesentliche Konzepte des Loggings an, um besser zu verstehen, wie wir unsere Logging-Verfahren implementieren können.

Laravel Strukturierte Protokollierung

In der Softwareentwicklung bedeutet strukturiertes Logging die Implementierung eines vorgegebenen und konsistenten Nachrichtenformats für Anwendungsprotokolle. Dieses Format ermöglicht es, die Meldungen als Daten zu behandeln, die viel besser überwacht, bearbeitet und visualisiert werden können als das normale Textformat.

Du musst in deiner modernen Anwendungsentwicklung einen strukturierten Logging-Ansatz einführen, denn Logdateien sind für Entwicklerinnen und Entwickler von entscheidender Bedeutung, wenn in deiner Anwendung in der Produktion etwas schief läuft.

Da Laravel Monolog verwendet, können Entwickler/innen schnell eine strukturierte Protokollierung implementieren, indem sie den Logger so konfigurieren, dass er bestimmte Arten von Informationen empfängt, die Protokolldateien in verschiedenen Formaten speichert und die Protokolle zur Visualisierung an verschiedene Log-Management-Dienste von Drittanbietern sendet.

Zentrales Logging in Laravel

Bei einem zentralisierten Logging-System werden die Logs aus verschiedenen Quellen zur einfachen Konsolidierung und Visualisierung an zentrale Log-Management-Lösungen (CLM) gesendet. CLM ist jedoch eine spezielle Logger-Lösung, die Log-Meldungen aus verschiedenen Quellen sammelt und die Daten für eine einfache Verarbeitung und Visualisierung konsolidiert.

Neben der Datenerfassung soll CLM auch die Analyse der Logdaten und die übersichtliche Darstellung der Daten nach der Analyse unterstützen.

Strukturiertes Logging vs. Basic Logging

Schauen wir uns den Unterschied zwischen strukturiertem Logging und einfachem (unstrukturiertem) Logging an und warum du strukturiertes Logging in deinem Laravel-Projekt verwenden solltest.

Einfache Protokollierung

Bei der einfachen Protokollierung werden die Protokolldateien in einem Rohformat mit begrenzten Daten zur Abfrage und Identifizierung einzelner Protokolle gespeichert.

Bei der Verwendung von Basic Logging können Entwickler keine Analysetools von Drittanbietern zum Lesen, Anzeigen und Analysieren von Logs verwenden, es sei denn, sie entwickeln ein eigenes Tool oder bleiben bei einem begrenzten Tool, das ihr Log-Format unterstützt.

Es gibt drei wichtige Gründe, die gegen die Verwendung von Basic Logging sprechen:

  1. Zentralisierte Log-Management-Systeme können ohne zusätzliche Unterstützung nicht mit den Daten arbeiten.
  2. Um die Daten einer einfachen Logging-Lösung zu lesen und zu analysieren, ist eine maßgeschneiderte Lösung erforderlich.
  3. Für Administratoren kann es eine Herausforderung sein, einfache Logging-Daten zu lesen, da sie roh und unstrukturiert sind.

Strukturiertes Logging

Strukturiertes Logging spart Entwicklern Zeit, indem sie Open-Source-Analyse-Tools von Drittanbietern verwenden, die eine Standard-Protokollstruktur zum Lesen, Anzeigen und Analysieren von Protokollen unterstützen.

Logs sind hilfreich, wenn sie die richtigen, unten aufgeführten Daten enthalten, und das ist das Ziel des strukturierten Loggings. Mit den Daten aus der strukturierten Protokollierung können wir Dashboards, Grafiken, Diagramme und andere hilfreiche Visualisierungen erstellen, um den Zustand der Anwendung zu ermitteln.

Dies sind nur einige Beispiele für Informationen, die in strukturierte Logmeldungen aufgenommen werden können. Darüber hinaus kannst du die Daten vollständig an deine Bedürfnisse anpassen.

Hier sind einige Beispiele für Daten, die du mit der strukturierten Protokollierung sammeln kannst:

  1. Der Port, der zur Ausführung der Funktion verwendet wurde
  2. Das Datum und die Uhrzeit des Ereignisses
  3. Den Benutzernamen oder die ID des Clients
  4. Eine Beschreibung des Ereignisses (Protokollnachricht)
  5. Das Protokoll, das zur Ausführung der Funktion verwendet wurde
  6. Der Ort des ausgelösten Ereignisses (API oder laufende App angeben)
  7. Die eindeutige Ereignis-ID
  8. Die Art der ausgelösten Aktion (Protokollebene)

Die Logs sollten genügend Daten enthalten, um die Lösung oder den Grund für das Log-Ereignis leicht zu visualisieren. Beachte auch, dass du nicht alle Arten von Informationen wie Passwörter oder sensible Daten in den Protokollen speichern solltest.

Nachdem wir nun einen Einblick in das Laravel-Logging bekommen haben, wollen wir uns nun der Implementierung des Laravel-Loggings widmen, indem wir eine Anwendung mit Logging als Bürger erster Klasse erstellen.

Wie man Laravel Logging mit Todo App implementiert

Jetzt wenden wir an, was wir bisher gelernt haben, indem wir ein neues Laravel-Projekt erstellen und Laravel-Logging implementieren.

Wenn du noch nie mit Laravel gearbeitet hast, kannst du nachlesen, was Laravel ist, oder einen Blick auf unsere Liste mit hervorragenden Laravel-Tutorials werfen, um den Einstieg zu finden.

Laravel einrichten

Zuerst erstellen wir mit dem unten stehenden Befehl eine neue Laravel-Instanz. Du kannst in der offiziellen Dokumentation nachschauen, um mehr zu erfahren.

Öffne deine Konsole und navigiere zu dem Ort, an dem du deine PHP-Projekte speicherst, bevor du die unten stehenden Befehle ausführst. Vergewissere dich, dass der Composer installiert und richtig konfiguriert ist.

composer create-project laravel/laravel laravel-logging-app
cd laravel-logging-app // Change directory to current Laravel installation
php artisan serve // Start Laravel development server

Konfigurieren und Seeding der Datenbank

Als Nächstes richten wir unsere Datenbank ein, erstellen ein neues Todo Modell und legen 200 Fake-Daten zum Testen an.

Öffne deinen Datenbank-Client und erstelle eine neue Datenbank. Wir tun dasselbe mit dem Namen laravel_logging_app_db und füllen dann unsere .env-Datei mit den Datenbank-Anmeldedaten:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_logging_app_db
DB_USERNAME=//DB USERNAME HERE
DB_PASSWORD=//DB PASSWORD HERE

Als Nächstes führen wir den folgenden Befehl aus, um die Migration und das Modell Todo gleichzeitig zu erstellen:

php artisan make:model Todo -mc

Öffne die neu erstellte Migration database/migrations/xxx-create-todos-xxx.php und füge die folgenden Codes ein:

<?php
use IlluminateSupportFacadesSchema;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;
class CreateTodosTable extends Migration
{
  /**
  * Run the migrations.
  *
  * @return void
  */
  public function up()
  {
    Schema::create('todos', function (Blueprint $table) {
      $table->id();
      $table->string('title');
      $table->text('description')->nullable();
      $table->boolean('is_completed')->default(false);
      $table->timestamps();
    });
  }
  /**
  * Reverse the migrations.
  *
  * @return void
  */
  public function down()
  {
    Schema::dropIfExists('todos');
  }
}

Du kannst deine Todos mit Faker-Daten seeden, indem du lernst, deine Datenbanken in Laravel mit Faker zu seeden.

Überblick über Monolog

Mit Laravel Monolog kannst du strukturierte Logs streamen und an verschiedene Kanäle wie E-Mails, Slack, Dateien, Sockets, Posteingänge, Datenbanken und verschiedene Webservices senden. In Laravel kannst du die Protokollierung in einer einzigen Konfigurationsdatei konfigurieren, die sich in config/logging.php befindet.

Die Konfigurationsdatei enthält vordefinierte Log-Treiber, aus denen du auswählen kannst. Der Standardtreiber ist stack, der den Kanal single verwendet, um in eine laravel.log-Datei im Ordner storage/logs zu loggen. Wir werden die strukturierte Protokollierung anhand einiger der Laravel-Log-Treiber demonstrieren.

Laravel bietet eine Handvoll Methoden, um mit Logs zu interagieren, wie wir in der Controller-Datei TodosController.php kurz demonstrieren.

Schreiben von Log-Meldungen im Controller

Öffne die neu erstellte Controller-Datei TodosController.php im Ordner app/Http/Controllers und füge die folgenden Codes ein:


<?php
namespace AppHttpControllers;
use AppModelsTodo;
use IlluminateHttpRequest;
use AppHttpControllersController;
use IlluminateSupportFacadesAuth;
use IlluminateSupportFacadesLog;
class TodosController extends Controller
{
  public function index(Request $request)
  {
    $todos = Todo::all();
    Log::warning('User is accessing all the Todos', ['user' => Auth::user()->id]);
    return view('dashboard')->with(['todos' => $todos]);
  }
  public function byUserId(Request $request)
  {
    $todos = Todo::where('user_id', Auth::user()->id)->get();
    Log::info('User is accessing all his todos', ['user' => Auth::user()->id]);
    return view('dashboard')->with(['todos' => $todos]);
  }
  public function show(Request $request, $id)
  {
    $todo = Todo::find($id);
    Log::info('User is accessing a single todo', ['user' => Auth::user()->id, 'todo' => $todo->id]);
    return view('show')->with(['todo' => $todo]);
  }
  public function update(Request $request, $id)
  {
    # Validations before updating
    $todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first();
    Log::warning('Todo found for updating by user', ['user' => Auth::user()->id, 'todo' => $todo]);
    if ($todo) {
      $todo->title = $request->title;
      $todo->desc = $request->desc;
      $todo->status = $request->status == 'on' ? 1 : 0;
      if ($todo->save()) {
        Log::info('Todo updated by user successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]);
        return view('show', ['todo' => $todo]);
      }
      Log::warning('Todo could not be updated caused by invalid todo data', ['user' => Auth::user()->id, 'todo' => $todo->id, 'data' => $request->except('password')]);
      return; // 422
    }
    Log::error('Todo not found by user', ['user' => Auth::user()->id, 'todo' => $id]);
    return; // 401
  }
  public function store(Request $request)
  {
    Log::warning('User is trying to create a single todo', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
    # Validations before updating
    $todo = new Todo;
    $todo->title = $request->title;
    $todo->desc = $request->desc;
    $todo->user_id = Auth::user()->id;
    if ($todo->save()) {
      Log::info('User create a single todo successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]);
      return view('show', ['todo' => $todo]);
    }
    Log::warning('Todo could not be created caused by invalid todo data', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
    return; // 422
  }
  public function delete(Request $request, $id)
  {
    Log::warning('User is trying to delete a single todo', ['user' => Auth::user()->id, 'todo' => $id]);
    $todo = Todo::where('user_id', Auth::user()->id)->where('id', $id)->first();
    if ($todo) {
      Log::info('User deleted a single todo successfully', ['user' => Auth::user()->id, 'todo' => $id]);
      $todo->delete();
      return view('index');
    }
    Log::error('Todo not found by user for deleting', ['user' => Auth::user()->id, 'todo' => $id]);
    return; // 404
  }
}

Innerhalb jeder der Methoden in TodoController haben wir die Log Fassade mit einem bestimmten Log-Level hinzugefügt, um die Art des Fehlers zu definieren, den wir senden wollen. Im Folgenden findest du ein Beispiel für die Verwendung der

Log-Fassade in der Methode store.

public function store(Request $request)
{
  Log::warning('User is trying to create a single todo', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
  # Validations before updating
  $todo = new Todo;
  $todo->title = $request->title;
  $todo->desc = $request->desc;
  $todo->user_id = Auth::user()->id;
  if ($todo->save()) {
    Log::info('User create a single todo successfully', ['user' => Auth::user()->id, 'todo' => $todo->id]);
    return view('show', ['todo' => $todo]);
  }
  Log::warning('Todo could not be created caused by invalid todo data', ['user' => Auth::user()->id, 'data' => $request->except('password')]);
  return; // 422
}

Formatierung von Log-Meldungen

Angenommen, du bist mit der von Laravel standardmäßig verwendeten LineFormatter nicht zufrieden, die sehr gut lesbare und hilfreiche Meldungen liefert.

In diesem Fall kannst du ganz einfach ein benutzerdefiniertes Formatierungsobjekt erstellen, das auf deinen Anwendungsfall zugeschnitten ist, und es in der gesamten Anwendung verwenden.

In der offiziellen Monolog-Dokumentation findest du eine vollständige Liste der verfügbaren Formatierer und kannst ganz einfach einen benutzerdefinierten Formatierer erstellen.

In Laravel kannst du jeden Treiber so einstellen, dass er deinen benutzerdefinierten Formatter verwendet, indem du ihn in der Konfigurationsdatei config/logging.php in die Liste einträgst (siehe unten):

'daily' => [
  'driver' => 'daily',
  'path' => storage_path('logs/laravel.log'),
  'level' => env('LOG_LEVEL', 'debug'),
  'days' => 14,
  'formatter' => MonologFormatterHtmlFormatter::class,
  'formatter_with' => [
    'dateFormat' => 'Y-m-d',
  ]
],

Das obige Beispiel fügt dem Treiber daily ein benutzerdefiniertes MonologFormatterHtmlFormatter hinzu und verwendet die Schlüssel formatter und formatter_with in der Kanalkonfiguration daily, um das Datumsformat zu ändern.

Senden von Logs an verschiedene Kanäle

Mit Hilfe von Monolog kann Laravel Logs an verschiedene Kanäle und mehrere Kanäle gleichzeitig senden.

Wir zeigen dir, wie du mit diesen einfachen Schritten Logs an unseren Slack-Kanal senden kannst. Ändere den Standard-Log-Kanal in Slack und füge die Slack Webhook URL in deine .env-Datei ein.

LOG_CHANNEL=slack
LOG_SLACK_WEBBHOOK_URL= Slack_webhook_url_here

Als Nächstes testest du deine Konfiguration, indem du eine Nachricht in deiner Anwendung mit der Log Fassade wie unten gezeigt protokollierst:

Log::debug("The API instance is on fire caused by:", ['user' => 1])

Du kannst deinen Slack-Kanal öffnen, um zu prüfen, ob der Fehler in dem gewünschten Kanal, den du bei der Erstellung der Webhook-URL angegeben hast, ausgegeben wird.

Zusammenfassung

Die Protokollierung ist genauso wichtig wie jeder andere Faktor deiner Anwendung, wenn nicht sogar noch wichtiger. Deshalb wird sie im Twelve-Factor App Manifesto als einer der wichtigsten Punkte für jede moderne Anwendung genannt.

Mit einer effektiven Protokollierung kannst du Fehler und Defekte, die in deiner produktionsreifen Anwendung auftreten, leicht lesen, anzeigen und visualisieren. Deshalb ist es wichtig, dass du schon zu Beginn des Projekts eine strukturierte Protokollierung in deine Anwendung einbaust.

In diesem Artikel haben wir uns mit der Laravel-Protokollierung beschäftigt und erklärt, warum du sie in deinem nächsten Projekt einsetzen solltest. Wir haben sowohl das strukturierte Logging als auch das zentralisierte Logging im Detail besprochen. Außerdem haben wir gelernt, wie man die Laravel-Protokollierung durch den Aufbau einer Todo-Anwendung implementiert.

Wie willst du Logging in deine nächste Anwendung integrieren? Lass es uns im Kommentarbereich wissen.

Solomon Eseme

I am a Software Engineer and Content Creator who is geared toward building high-performing and innovative products following best practices and industry standards. I also love writing about it at Masteringbackend.com. Follow me on Twitter, LinkedIn, and About Me