Magento 2. Monolog oder wie man Protokolle schreibt

Wenn Sie die verschiedenen Module für Magento 2 studieren, werden Sie feststellen, dass die Protokollierung viel seltener verwendet wird als Magento 1. Dies liegt hauptsächlich an der Tatsache, dass die Protokollierung schwieriger geworden ist. Hier möchte ich mich auf die technische Seite des Problems konzentrieren, nämlich wie Daten protokolliert werden, wie Protokolle in Ihre eigene Datei geschrieben werden und was Monolog ist.

Inhaltsverzeichnis


Monolog
Anwendungsfunktionen in Magento 2
Implementierung
Protokollierung mit dem Standardlogger
Protokollierung mit einem Standardlogger mit einem benutzerdefinierten Kanal
Schreiben in eine benutzerdefinierte Datei mit Ihrem eigenen Handler
Schreiben in eine benutzerdefinierte Datei mit virtualType
Schnelle Datenerfassung
Fazit

Monolog


Beginnen wir mit der wichtigsten Frage: Was ist Monolog und woher kommt es?

Monolog - Dies ist eine Bibliothek, die den PSR-3-Standard für die Datenprotokollierung implementiert. Es ist Monolog, das in Magento 2 zum Aufzeichnen von Protokollen verwendet wird.

PSR-3 ist wiederum ein Standard, der einen gemeinsamen Ansatz für die Datenprotokollierung und Empfehlungen für die Implementierung von Protokollierern beschreibt, die eine gemeinsame Schnittstelle bieten.

PSR-3-Highlights
1. Der Logger (Objekt) muss die Schnittstelle \ Psr \ Log \ LoggerInterface implementieren.
2. Wir haben die folgenden Fehlerstufen (angegeben in der Reihenfolge der Priorität von größer nach kleiner):
NOTFALL - System ist unbrauchbar.
ALERT - Maßnahmen müssen sofort ergriffen werden. Beispiel: Ganze Website ausgefallen, Datenbank nicht verfügbar usw.
KRITISCH - Kritische Bedingungen. Beispiel: Anwendungskomponente nicht verfügbar, unerwartete Ausnahme.
FEHLER - Laufzeitfehler, die keine sofortige Aktion erfordern, aber normalerweise überwacht werden sollten.
WARNUNG - Außergewöhnliche Vorkommen, bei denen es sich nicht um Fehler handelt. Beispiel: Verwendung veralteter APIs.
HINWEIS - Normale, aber wichtige Ereignisse.
INFO - Interessante Ereignisse. Beispiel: Benutzer meldet sich an, SQL-Protokolle.
DEBUG - Detaillierte Debug-Informationen.

3. Jede Ebene hat ihre eigene Methode (Debug, Info, Benachrichtigung, Warnung, Fehler, Kritisch, Alarm, Notfall / Notfall) und es sollte auch eine Protokollmethode geben, die die Fehlerstufe als ersten Parameter verwendet.
4. Die Methoden akzeptieren eine Zeichenfolge oder etwas, das __toString () implementiert (dh Sie müssen print_r ($ message, true) manuell für Arrays verwenden oder sie im nächsten Parameter übergeben).
5. Alle Methoden akzeptieren ein $ context-Array, das das Protokoll ergänzt.
6. Kann, aber nicht unbedingt, das Ersetzen von Daten aus dem $ context-Array in die Nachricht implementiert werden. In diesem Fall wird das Format {name} empfohlen, wobei name -> der Schlüssel des Arrays im $ -Kontext ist.


Monolog ist ziemlich einfach zu bedienen. Schauen wir uns das folgende Beispiel an.

use Monolog\Logger; use Monolog\Handler\StreamHandler; use Monolog\Formatter\HtmlFormatter; //     "name" $log = new Logger('name'); //  ,      "path/to/your1.log"       "WARNING"   (notice, info  debug   ). $log->pushHandler(new StreamHandler('path/to/your1.log', Logger::WARNING)); //  ,      "path/to/your2.log"       "ALERT"   (..        alert  emergency).    ,    .         html   HtmlFormatter. $log->pushHandler(new StreamHandler('path/to/your2.log', Logger::ALERT,false) ->setFormatter(new HtmlFormatter)); //  ,       . $log->pushProcessor(function ($record) { $record['extra']['dummy'] = 'Hello world!'; return $record; }); //   $log->warning('Foo'); $log->error('Bar',['test']); $log->info('Test'); //   ,    1     INFO //your1.log // [2019-08-12 02:57:52] name.WARNING: Foo [] ['extra'=>['dummy'=>'Hello world!']] // [2019-08-12 02:57:53] name.ERROR: BAR ['test'] ['extra'=>['dummy'=>'Hello world!']] //your2.log // , .    ALERT  EMERGENCY 

Höhepunkte der Arbeit von Monolog zu beachten:

  • Logger ist ein Objekt, mit dem wir Protokolle aufzeichnen. Der Logger selbst zeichnet nicht auf, sondern verwaltet Handler. Es kann eine beliebige Nummer erstellt werden.
  • Handler - ein Objekt, das Daten direkt verarbeitet. Sie können dem Logger so viele Handler hinzufügen, wie Sie möchten. Alle werden nacheinander aufgerufen, unabhängig davon, ob der angegebene Handler den Fehler verarbeiten konnte oder nicht. Die isHandling-Methode bestimmt, ob dieser Handler den empfangenen Fehler verarbeiten kann.

     public function isHandling(array $record) { return $record['level'] >= $this->level; } 

    Die größte Ähnlichkeit mit dem Handler ist meiner Meinung nach der Event Observer.
  • Prozessor - jede aufgerufene Entität (aufrufbar). Vielleicht ein paar. Sie können sowohl global zugewiesen als auch für den Handler installiert werden. Zunächst werden globale Prozessoren gestartet. Die Hauptaufgabe des Prozessors besteht darin, dem Protokoll zusätzliche Daten hinzuzufügen (z. B. die IP, von der aus die Verbindung hergestellt wurde, den Wert globaler Variablen, Informationen darüber, auf welchem ​​Git-Zweig sich der Code befindet usw.).
  • Formatierer - Konvertiert die Nachrichtenausgabe vor dem Schreiben. Es kann nur 1 pro Handler geben. Es ist notwendig, die Formatierung des Nachrichtentexts zu ändern, um beispielsweise Text in HTML oder JSON zu konvertieren.
  • Kanal - der Name des Loggers. Es wird beim Aufzeichnen des Protokolls geschrieben. Da 1 Handler in 2 verschiedenen Loggern verwendet werden kann (er schreibt Protokolle in 1 dieselbe Datei), wird dadurch bestimmt, woher der Fehler stammt.
  • Level - Fehlerlevel. Dieser Parameter für den Handler gibt die minimale Fehlerstufe an, die er behandeln wird.
  • Bubble - Nachrichten-Popup. Nachdem der Handler die Nachricht verarbeitet hat, leitet der Logger die Nachricht an den nächsten Handler weiter. Dieser Prozess kann mithilfe der Eigenschaft bubble gestoppt werden. Wenn der Handler den Wert dieser Eigenschaft false hat (der Standardwert ist immer true), werden andere Handler nicht gestartet, nachdem dieser Handler seine Arbeit erledigt hat (dieser Fehler konnte verarbeitet werden).
  • Sortierreihenfolge - Ausführungsreihenfolge. Der zuletzt hinzugefügte Handler wird immer als allererster gestartet. Mit dieser Funktion können Sie einen Mechanismus implementieren, um den Logger vollständig zu deaktivieren (über Bubbling False). Über den Konstruktor hinzugefügte Handler werden in der im Konstruktor angegebenen Reihenfolge ausgeführt.

Da PSR-3 Entwickler nicht verpflichtet, AutoCorrect-Werte im Text zu implementieren, führt Monolog dies standardmäßig nicht aus. Wenn Sie schreiben -> emerg ('test 1111 {placeholder}', ['placeholder' => 'foo']), erhalten Sie Folgendes
[2019-08-12 02:57:52] main.EMERGENCY: test 1111 {placeholder} {"placeholder": "foo"} []

Damit der Austausch funktioniert, müssen Sie einen zusätzlichen Prozessor anschließen - \ Monolog \ Processor \ PsrLogMessageProcessor.
Es ist erwähnenswert, dass Monolog eine große Anzahl von Formatierern, Prozessoren und Handlern im Auslieferungszustand hat. Sie können sie entweder verwenden oder Ihre eigenen schreiben.

Anwendungsfunktionen in Magento 2


Auf der offiziellen Magento-Website finden Sie ein allgemeines Beispiel für die Verwendung des Loggers. Leider enthüllt das vorgestellte Beispiel nicht alle Details und beantwortet leider nicht die Frage "Wie schreibe ich Protokolle in Ihre eigene Datei?". Lassen Sie uns deshalb alles genauer verstehen.

In den Tagen von Magento 1 verwendeten wahrscheinlich früher oder später alle die Mage :: log-Methode, die überall im Code verfügbar war, und der einfachste Protokolleintrag sah aus wie Mage :: log ('ALARM!', Null, 'api.log'). Als Ergebnis hatten wir einen Datensatz des folgenden Formulars in der Datei var / log / api.log

 2019-08-12T01:00:27+00:00 DEBUG (7): ALARM! 

Standardformat:% Zeitstempel %% Prioritätsname% (% Priorität%):% Nachricht%.

Mal sehen, wie man Daten im einfachsten Fall in Magento 2 protokolliert. Meistens verwenden Sie $ this -> _ logger-> info ('ALARM!'); (Wenn ein Objekt beispielsweise eine solche Eigenschaft geerbt hat).

Als Ergebnis eines solchen Aufrufs erhalten wir den folgenden Eintrag in der Datei var / log / system.log

 [2019-08-12 02:56:43] main.INFO: ALARM! [] [] 

Das Standardformat ist [% datetime%]% channel%.% Level_name%:% message %% context %% extra%
Wenn das Objekt keine solche Eigenschaft hat (_logger oder logger), müssen wir zuerst die Abhängigkeit \ Psr \ Log \ LoggerInterface zu Ihrer Klasse hinzufügen und das resultierende Objekt in die Eigenschaft $ logger schreiben (gemäß PSR-2 Punkt 4.2 und dem auf der Magento-Website dargestellten Beispiel ). .
Im Gegensatz zu Magento 1 gibt es hier viel mehr Nuancen.

1. Parameter für die Protokollierung.

Betrachten Sie einen generischen Aufruf der Schreibmethode

 $this->_logger->{level}($message, $context = []); //$this->_logger->log('{level}', $message, $context = []); 

1) Wobei {level} gemäß PSR-3 eine der Methoden ist, die für die Protokollierung einer bestimmten Fehlerstufe reserviert sind (Debug, Info, Benachrichtigung, Warnung, Fehler, kritisch, Alarm, Notfall / Notfall).
2) $ message - im Gegensatz zu Magento 1 sollte es eine Zeichenfolge sein. Das heißt, $ object-> getData () funktioniert hier nicht. Das Datenarray muss an den nächsten Parameter übergeben werden. \ Exception-Objekte sind eine Ausnahme, da die Implementierung von \ Magento \ Framework \ Logger \ Monolog sie separat verarbeitet und automatisch -> getMessage () als $ message weiterführt, wenn das \ Exception-Objekt als Nachricht übergeben wurde.
3) $ context ist ein optionaler Parameter, ein Array.

2. Die Eigenschaft $ this -> _ logger ist nicht in allen Klassen verfügbar.

Präsentiert in: Block, Helfer, Modell, Sammlung usw.
Nicht verfügbar in: ResourceModel, Controller, Comand, Setup usw.

Erfahren Sie mehr über ResourceModel und Collection.
ResourceModel verfügt über die Eigenschaft _logger, wird jedoch nicht im Konstruktor ausgefüllt. Es wird nur mit der privaten Methode getLogger in \ Magento \ Framework \ Model \ ResourceModel \ AbstractResource gefüllt. Die Methode wird nur im Fehlerfall beim Schreiben in die Datenbank (im catch-Block) innerhalb der commit () -Methode aufgerufen. Bis dahin verfügt das Ressourcenmodell nicht über einen Logger.

 public function commit() { $this->getConnection()->commit(); if ($this->getConnection()->getTransactionLevel() === 0) { $callbacks = CallbackPool::get(spl_object_hash($this->getConnection())); try { foreach ($callbacks as $callback) { call_user_func($callback); } } catch (\Exception $e) { $this->getLogger()->critical($e); } } return $this; } … private function getLogger() { if (null === $this->_logger) { $this->_logger = ObjectManager::getInstance()->get(\Psr\Log\LoggerInterface::class); } return $this->_logger; } 

Collection hat von Anfang an einen Logger. Es wird im Konstruktor \ Magento \ Framework \ Data \ Collection \ AbstractDb zugewiesen und später vererbt.

Es ist unmöglich, dies nicht zu sagen, aber in den Controllern gibt es eine Möglichkeit, den Logger mithilfe des ObjectManager abzurufen (über die Eigenschaft $ this -> _ objectManager). Dies ist natürlich nicht der richtigste Weg.

3. Der Standardlogger und die Liste der Handler.

In der globalen Datei di.xml (app / etc / di.xml) finden Sie, dass \ Psr \ Log \ LoggerInterface von der Klasse \ Magento \ Framework \ Logger \ Monolog implementiert wird, die wiederum von \ Monolog \ Logger erbt. Der Loggername ist main. Dort sind auch mehrere Handler definiert.

 <preference for="Psr\Log\LoggerInterface" type="Magento\Framework\Logger\Monolog" /> ... <type name="Magento\Framework\Logger\Monolog"> <arguments> <argument name="name" xsi:type="string">main</argument> <argument name="handlers" xsi:type="array"> <item name="system" xsi:type="object">Magento\Framework\Logger\Handler\System</item> <item name="debug" xsi:type="object">Magento\Framework\Logger\Handler\Debug</item> <item name="syslog" xsi:type="object">Magento\Framework\Logger\Handler\Syslog</item> </argument> </arguments> </type> ... 

Einige Klassen unterscheiden sich von den oben aufgeführten (da sie im Magento \ Developer-Modul neu definiert wurden):

1) Magento \ Framework \ Logger \ Handler \ System ( hört auf INFO)
2) Magento \ Developer \ Model \ Logger \ Handler \ Debug ( hört DEBUG ab )
3) Magento \ Developer \ Model \ Logger \ Handler \ Syslog ( hört auf DEBUG )

In den angegebenen Klassen (Debug und Syslog) wird die Möglichkeit zum Deaktivieren der Protokollierung (dev / debug / debug_logging bzw. dev / syslog / syslog_logging) hinzugefügt.

Beachten Sie, dass die Liste der Handler, die in exception.log schreiben, keinen Ausnahmebehandler enthält. Es wird im Systemhandler aufgerufen.

Magento \ Framework \ Logger \ Handler \ System
 ... public function write(array $record) { if (isset($record['context']['exception'])) { $this->exceptionHandler->handle($record); return; } $record['formatted'] = $this->getFormatter()->format($record); parent::write($record); } ... 


Magento 2 bis 2.2 hatten ein Problem damit, dass der Logger nach dem ersten gefundenen nicht mehr zu einem anderen Handler springen konnte. Dieses Problem wurde durch die Tatsache verursacht, dass Monolog berechnete, dass alle Handler in einem Array mit digitalen Schlüsseln und mit alphabetischen Schlüsseln (['system' =>, 'debug' =>, ...]) darauf kamen. Magento-Entwickler haben die Situation später korrigiert - sie konvertieren den Hash in ein reguläres Array mit digitalen Schlüsseln, bevor sie ihn an Monolog übergeben. Monolog hat jetzt auch den Handler-Aufzählungsalgorithmus geändert und verwendet die next () -Methode.
4. Einführung Ihres Handlers in die Liste der vorhandenen.

Wir kommen zu der interessantesten Sache, die den Eindruck der Implementierung in Magento 2 ein wenig beeinträchtigt. Sie können der Liste der vorhandenen mit di.xml keinen benutzerdefinierten Handler hinzufügen, ohne ... "zusätzliche Gesten". Dies ist auf das Prinzip der Zusammenführungskonfiguration zurückzuführen.

Es gibt mehrere Konfigurationsbereiche :

1) Initial (app / etc / di.xml)
2) Global ({moduleDir} /etc/di.xml)
3) Bereichsspezifisch ({moduleDir} / etc / {area} /di.xml dh Frontend / adminhtml / crontab / webapi_soap / webapi_rest usw.)

Innerhalb von Level 1 werden Konfigurationen zusammengeführt, aber die nächste Ebene definiert sie beim Zusammenführen neu (wenn sie auch dort deklariert sind). Dies macht es unmöglich, Handler in ihren Modulen zur vorhandenen Liste hinzuzufügen, da diese im ursprünglichen Bereich deklariert ist.

Vielleicht sehen wir in Zukunft eine Implementierung, bei der das Hinzufügen von Handlern vom ursprünglichen Bereich in ein anderes Modul verschoben und dadurch in den globalen Bereich übertragen wird.

Implementierung


Schauen wir uns die wichtigsten Methoden zum Aufzeichnen von Protokollen an, die für uns bei der Implementierung von Aufgaben hilfreich sein können.

1. Protokollierung mit dem Standardlogger


Mit dieser Methode können wir problemlos Protokolle in eines der Standardprotokolle (debug.log, system.log oder exception.log) schreiben.

 class RandomClass { private $logger; public function __construct(\Psr\Log\LoggerInterface $logger) { $this->logger = $logger; } public function foo() { $this->logger->info('Something went wrong'); //[...some date...] main.INFO: Something went wrong [] [] } } 

Alles wird noch einfacher, wenn in unserer Klasse bereits eine vererbte Logger-Abhängigkeit besteht.

 $this->_logger->info('Something went wrong'); //    ->debug,   ,      debug.log ... 

2. Protokollierung mit einem Standardlogger mit einem benutzerdefinierten Kanal


Diese Methode unterscheidet sich von der vorherigen darin, dass ein Klon des Loggers erstellt und ihm ein anderer Kanal (Name) zugewiesen wird. Dies vereinfacht die Suche in der Protokolldatei.

 class RandomClass { private $logger; public function __construct(\Psr\Log\LoggerInterface $logger) { $this->logger = $logger->withName('api'); //    } public function foo() { $this->logger->info('Something went wrong'); //[...some date...] api.INFO: Something went wrong [] [] } } 


Um nach den erforderlichen Protokollen zu suchen, reicht es jetzt aus, die Suche nach "api" (der Standardprotokollierer in Magento 2 heißt main) in den vorhandenen Dateien system.log, debug.log, exception.log zu verwenden. Kann verwenden
 grep -rn 'api' var/log/system.log 


3. Schreiben Sie mit Ihrem eigenen Handler in eine benutzerdefinierte Datei


Erstellen wir einen einfachen Handler, der alle Fehler der kritischen Ebene und höher in einer separaten Datei var / log / Critical.log protokolliert. Fügen Sie die Möglichkeit hinzu, alle anderen Handler für eine bestimmte Fehlerstufe und höher zu blockieren. Dadurch wird vermieden, dass Daten in den Dateien debug.log und system.log dupliziert werden.

 <?php namespace Oxis\Log\Logger\Handler; use Magento\Framework\Filesystem\DriverInterface; use Magento\Framework\Logger\Handler\Base; use Monolog\Logger; class Test extends Base { protected $fileName = 'var/log/critical.log'; protected $loggerType = Logger::CRITICAL; public function __construct(DriverInterface $filesystem) { parent::__construct($filesystem,null,null); $this->bubble = false; //      setBubble() } } 

In Magento 2 2.2+ im Konstruktor \ Magento \ Framework \ Logger \ Handler \ Base hat sich die Art und Weise der Verarbeitung des Pfads zur Protokolldatei geändert
 // BP . $this->fileName // BP. DIRECTORY_SEPARATOR . $this->fileName 

Daher finden Sie in älteren Handlern / am Anfang von $ fileName.


Zum Beispiel ist eine kleine Erklärung wert. Da Base es Ihnen nicht erlaubt, die Bubble-Eigenschaft über Konstruktorparameter festzulegen, müssten wir entweder einen Teil des Codes aus dem Base-Konstruktor wiederholen, um den Eingabeparameter korrekt an das übergeordnete Element der Base-Klasse zu übergeben (das übrigens einen Eingabeparameter zum Festlegen dieser Eigenschaft hat) oder verwenden ein solcher Ansatz. Ich habe die zweite Option gewählt.

 use Oxis\Log\Logger\Handler\Test; use Psr\Log\LoggerInterface; class RandomClass { private $logger; public function __construct( LoggerInterface $logger, Test $handler ) { $logger->pushHandler($handler); //  setHandlers([$handler]),        . $this->logger = $logger; } public function foo() { $this->logger->critical('Something went wrong'); //      critical.log //[...some date...] main.CRITICAL: Something went wrong [] [] } } 

Diese Methode zum Hinzufügen eines Handlers ist nicht ideal, ermöglicht es Ihnen jedoch, den Konfigurationsbereich des Problems zu verlassen, sodass wir alle Logger in unserer di.xml duplizieren müssen. Wenn das Ziel darin besteht, alle Logger durch Ihre eigenen zu ersetzen, ist es viel besser, den virtualType-Ansatz zu verwenden, den wir weiter betrachten werden.

4. Schreiben in eine benutzerdefinierte Datei mit virtualType


Dieser Ansatz ermöglicht es uns, die Klasse, die wir zum Schreiben von Protokollen benötigen, mit di.xml in die angegebene Protokolldatei zu zwingen. Einen ähnlichen Ansatz finden Sie in den Modulen Magento \ Payment und Magento \ Shipping. Ich mache Sie darauf aufmerksam, dass dieser Ansatz ab Magento 2 2.2 und höher funktioniert.
In Magento 2 2.2+ wurde dem Konstruktor \ Magento \ Framework \ Logger \ Handler \ Base ein neuer Parameter hinzugefügt, mit dem Sie einen virtuellen Handler erstellen und über di.xml den relativen Pfad zur Datei zum Schreiben des Protokolls angeben können. Bisher war es erforderlich, entweder den vollständigen Pfad durch $ filePath anzugeben oder einen neuen Handler zu erstellen und den relativen Pfad in die geschützte Datei $ fileName-Eigenschaft zu schreiben.

Fügen Sie in der Datei di.xml unseres Moduls Folgendes hinzu
  <!--      ,     --> <virtualType name="ApiHandler" type="Magento\Framework\Logger\Handler\Base"> <arguments> <argument name="fileName" xsi:type="string">var/log/api.log</argument> </arguments> </virtualType> <!--  ,     --> <virtualType name="ApiLogger" type="Magento\Framework\Logger\Monolog"> <arguments> <argument name="name" xsi:type="string">api</argument> <argument name="handlers" xsi:type="array"> <item name="default" xsi:type="object">ApiHandler</item> </argument> </arguments> </virtualType> <!--       --> <type name="Oxis\Log\Model\A"> <arguments> <argument name="logger" xsi:type="object">ApiLogger</argument> </arguments> </type> 

Fügen Sie Oxis \ Log \ Model \ A eine Logger-Klasse hinzu.
 namespace Oxis\Log\Model; class A { private $logger; public function __construct(\Psr\Log\LoggerInterface $logger) { $this->logger = $logger; } public function foo() { $this->logger->info('Something went wrong'); } } 

Jetzt werden absolut alle Protokolle, die in unserer Klasse geschrieben werden, von unserer Version des Loggers verarbeitet, der mit unserem Handler Protokolle in die Datei var / log / api.log schreibt.

4.1. Wenn die Klasse den Logger über das $ context-Objekt und nicht über ihren Konstruktor empfängt.
Dazu gehört \ Magento \ Catalog \ Model \ Product, dessen Abhängigkeiten nicht \ Psr \ Log \ LoggerInterface haben, aber es gibt \ Magento \ Framework \ Model \ Context, über das der Logger auf die Klasseneigenschaft festgelegt wird. In diesem Fall müssen wir die obige Option etwas komplizieren und den im $ context-Objekt befindlichen Logger ersetzen. Damit dies nicht das gesamte Magento betrifft, ersetzen wir $ context nur für unsere Klasse durch virtualType.
 <virtualType name="ApiHandler" type="Magento\Framework\Logger\Handler\Base"> <arguments> <argument name="fileName" xsi:type="string">var/log/api.log</argument> </arguments> </virtualType> <virtualType name="ApiLogger" type="Magento\Framework\Logger\Monolog"> <arguments> <argument name="name" xsi:type="string">api</argument> <argument name="handlers" xsi:type="array"> <item name="default" xsi:type="object">ApiHandler</item> </argument> </arguments> </virtualType> <!--       logger--> <virtualType name="ApiLogContainingContext" type="Magento\Framework\Model\Context"> <arguments> <argument name="logger" xsi:type="object">ApiLogger</argument> </arguments> </virtualType> <!--    --> <type name="Oxis\Log\Model\A"> <arguments> <argument name="context" xsi:type="object">ApiLogContainingContext</argument> </arguments> </type> 


5. Schnelle Datenprotokollierung


Es gibt Zeiten, in denen wir die Protokollierung schnell hinzufügen müssen. In den meisten Fällen kann dies entweder auf dem Produktionsserver oder für schnelle Tests erforderlich sein.
 ... $log = new \Monolog\Logger('custom', [new \Monolog\Handler\StreamHandler(BP.'/var/log/custom.log')]); $log->error('test'); ... 

Vorteile dieses Ansatzes: Schreibt ein Datum, es gibt einen Kontext (Array), fügt am Ende automatisch \ n hinzu

Im obigen Beispiel wird \ Monolog \ Logger speziell angewendet und nicht \ Magento \ Framework \ Logger \ Monolog, wodurch es erweitert wird. Tatsache ist, dass es bei dieser Verwendung keinen Unterschied gibt, sondern weniger zu schreiben (und sich leichter daran zu erinnern).

\ Monolog \ Handler \ StreamHandler wird wiederum anstelle von \ Magento \ Framework \ Logger \ Handler \ Base verwendet, da die Verwendung von Base als Snippet aufgrund zusätzlicher Abhängigkeiten von Klassen von Drittanbietern nicht sehr praktisch ist.

Ein anderer Ansatz, über den nicht gesprochen werden kann, sind die guten alten file_put_contents.

 ... file_put_contents(BP.'/var/log/custom.log', 'test',FILE_APPEND); ... 

Vorteile dieses Ansatzes: Schreiben Sie relativ schnell und müssen Sie sich nicht an Klassen erinnern.

In beiden Fällen spielt der konstante BP die Hauptrolle. Sie zeigt immer auf den Ordner mit Magenta (1 Stufe höher als die Kneipe), was praktisch ist und uns immer hilft, Protokolle an die richtige Stelle zu schreiben.

Fazit


Ich hoffe, die obigen Informationen waren oder werden für Sie nützlich sein.

Source: https://habr.com/ru/post/de450636/


All Articles