Überwachen von Anwendungen mit Logger.Backends

Elixir nutzt die Erlang- Protokollierungsinfrastruktur voll aus, um Protokolle zu erstellen. Ab Version 1.10 , die in naher Zukunft veröffentlicht werden soll, stehen uns neue Benutzerprotokollierungsfunktionen zur Verfügung, die in Erlang / OTP 21+ erschienen sind.


Während OTP die gesamte Infrastruktur für die Übermittlung von Journalereignissen (Ereignissen) an Abonnenten bereitstellt, sollte die Protokollierung selbst von der Anwendung implementiert werden, sofern dies als Speichern und / oder Anzeigen von Journalereignissen verstanden wird. Zu diesem Zweck wird die entsprechende Abstraktion von Logger.Backend .


Hier ist ein Auszug aus der offiziellen Dokumentation:


Logger unterstützt verschiedene Backends, in denen Logmeldungen geschrieben werden.

Standardmäßig sind nur folgende Backends verfügbar:
  • :console - protokolliert Nachrichten an die Konsole (standardmäßig aktiviert)


Jeder Entwickler kann seine eigenen Ernten wie ein Backend für Logger erstellen. Da Logger ein Ereignismanager ist, der das Verhalten von Erlang :gen_event implementiert, müssen Sie lediglich einen eigenen Ereignishandler erstellen, wie in der Dokumentation für :gen_event .

Verwendete Backends werden über den Abschnitt :backends in der Konfigurationsdatei geladen, der vor dem Starten von application :logger verarbeitet werden muss.


Die gängigste hex.pm , die zur Entstehung vieler hex.pm Bibliotheken desselben Typs hex.pm besteht darin, einen Logger.Backend zu erstellen, der die JSON-Konsole versteht und ausspuckt und eine Art Protokolllieferung an den Ort Logger.Backend , an dem Sie sie benötigen (normalerweise handelt es sich um eine Art LaaS ). . Daher werden alle Protokolle normalerweise in einer NoSQL-Datenbank wie Elastic oder ähnlichem gespeichert .


Wir sind nicht original geworden, und wir speichern unsere Protokolle auch in Elastic , aber jetzt reichen Protokolle nicht mehr aus: Moderne modische Jungs halten sich an alle Nachrichten in den Protokollen - Metriken für alles über alles. Der De-facto-Standard für die Arbeit mit Metriken in OTP- Anwendungen war kürzlich die Telemetry- Bibliothek, ein relativ junges Open-Source-Projekt zur Vereinheitlichung und Standardisierung der Instrumentierung und Steuerung von BEAM-Bibliotheken und -Anwendungen.


Der Ansatz von Telemetry ist einfach bis zum Entsetzen: Wir nennen :telemetry.execute/2 wenn in der Anwendung etwas gemessen werden muss, und die Bibliothek antwortet mit dem Rückruf, der beim Start der Anwendung registriert wurde. Darüber hinaus ist es möglich, Telemetry.Poller anzuhängen und Metrikanforderungen in regelmäßigen Abständen durchzuführen. Das Beispiel in dem Artikel, zu dem ich den obigen Link gegeben habe, schlägt vor, Logger.log/3 von der internen Telemetrie- Ereignisbehandlungsroutine Logger.log/3 .


Gelato


Ich hasse Boilerplate-Code, den Sie kopieren und einfügen müssen, von Projekt zu Projekt, von Datei zu Datei. Ich möchte, dass alles, was der Compiler, der Scheduler und die Worker können, erledigt wird, damit ich nicht einmal darüber nachdenke. Zu diesem Zweck packe ich den Code des Boilerplates häufig in winzige Bibliotheken, die alle erforderlichen Boilerplates unter der Haube verbergen und saubere Schnittstellen für die Ausführung der von unserer Anwendung benötigten Aktionen bereitstellen. Ich möchte nur, dass etwas, das als report("message", payload) , einen Datensatz erstellt, Telemetriedaten hinzufügt und diesen Datensatz an unseren elastischen Speicher sendet.


Es stellt sich heraus, dass dies nicht so schwierig ist.


Wir haben uns entschlossen, die Standard- Logger Aufrufe als Schnittstelle zu verwenden, damit wir durch einfaches Ändern der Konfigurationen die gewünschte Funktionalität in bestehende Projekte einfügen können. Logger.Backend einfach einen neuen Logger.Backend zu einem vorhandenen Projekt hinzu:


 config :logger, backends: [Our.Fancy.Logger.Backend] 

- und voilà - logs mit telemetrie werden nun in einen elastischen bunker geschickt.


Und so entstand die Gelato Bibliothek. Ich weiß, dass echte, nachdenkliche Entwickler Bibliotheken gerne ein bisschen weniger esoterisch nennen, aber ich bin kein echter Entwickler. Was ist, müssen Sie sich abfinden. Gelato (übrigens in Spanisch - Eiscreme) passt sogar ein wenig zur Elastizität.


Die Bibliothek konzentriert sich sehr darauf, wie ich die richtige Welt sehe, und verwendet in Schwanz und Mähne den Ansatz der „Konvention über Konfiguration“. Es packt alles, was Sie benötigen, in einen JSON und sendet es mit einer einfachen HTTP-Anfrage an einen vorkonfigurierten elastischen Server. Es werden auch alle Metadaten Process.info/1 , auf die es Process.info/1 kann, z. B. Metriken, die mit Process.info/1 abgerufen wurden.


Um diese Bibliothek in einem Projekt zu verwenden, müssen Sie Ihrer Datei config/releases.exs Folgendes hinzufügen:


 config :gelato, uri: "http://127.0.0.1:9200", # Elastic API endoint events: [:foo, :bar], # attached telemetry events handler: :elastic # or :console for tests config :logger, backends: [Gelato.Logger.Backend], level: :info 

Danach wird jeder Logger.log/3 Aufruf wie der folgende telemetry und an den konfigurierten elastischen Server gesendet.


 Logger.info "foo", question: "why?", answer: 42, now: System.monotonic_time(:microsecond) 

Die Bibliothek präsentiert auch das Gelato.bench/4 Makro, das einen Block benötigt und zwei Aufrufe an Logger.log/3 : einen vor der Ausführung des Blocks und den anderen unmittelbar danach nach Art der Aspekte in Java.


Gelato besteht unauffällig auf einer besseren Organisation der Schnittstellen innerhalb von Projekten mit dem Makro Gelato.defdelegatelog/2 , der einfachen Komposition Gelato.bench/4 und Kernel.defdelegate/2 . Mit diesem Makro können Sie alle Projektschnittstellen in einen begrenzten Satz von Modulen der obersten Ebene extrahieren und diese Anrufe sofort mit Telemetrie protokollieren.


Envío.Log


Eine Logger.Backend Implementierung von Logger.Backend , die aus unserer technologischen Leidenschaft hervorgegangen ist, ist Envío.Log . Es verwendet die Envío Bibliothek, um Nachrichten an einen dedizierten Slack- Kanal zu senden. Dieser Logger verfügt über eine eigene log_level Einstellung, deren Wert normalerweise auf " :warn oder " :error , um zu verhindern, dass der Slack- Kanal spammt, und alle Anrufe mit einer niedrigeren als der konfigurierten Stufe werden beim Kompilieren aus BEAM gelöscht.


Eine typische Konfiguration würde so aussehen:


 config :envio, :log, level: :warn, # do not send :info to Slack process_info: false # do not attach process info config :logger, backends: [Envio.Log.Backend], level: :debug config :envio, :backends, %{ Envio.Slack => %{ {Envio.Log.Publisher, :info} => [ hook_url: {:system, "YOUR_SLACK_CHANNEL_API_ENDPOINT"} ] } } 

Nach der Konfiguration werden alle Aufrufe von Logger.{warn,error}/2 an den entsprechenden Slack- Kanal gesendet. Es ist sehr praktisch, um Arbeitsabläufe in der Produktion in Echtzeit zu überwachen.


Viel Spaß beim Loggen!

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


All Articles