Surveillance des applications avec Logger.Backends

Elixir utilise pleinement l'infrastructure de journalisation d' Erlang pour créer des journaux. À partir de la version 1.10 , qui doit être publiée prochainement, de nouvelles fonctions de journalisation des utilisateurs apparues dans Erlang / OTP 21+ sont à notre disposition.


Tandis qu'OTP fournit toute l'infrastructure pour fournir des événements de journal (événements) aux abonnés, la journalisation elle-même, si elle est comprise comme stockant et / ou affichant des événements de journal, doit être implémentée par l'application. À cet effet, l'abstraction correspondante de Logger.Backend .


Voici un extrait de la documentation officielle:


Logger prend en charge divers backends où les messages de journal sont écrits.

Les backends disponibles par défaut sont limités à un:
  • :console - enregistre les messages sur la console (activé par défaut)


Tout développeur peut créer sa propre moisson comme un backend pour Logger . Étant donné que Logger est un gestionnaire d'événements qui implémente le comportement Erlang :gen_event , l'écriture d'un nouveau backend consiste simplement à créer votre propre gestionnaire d'événements, comme décrit dans la documentation de :gen_event .

Les backends utilisés sont chargés via la section :backends du fichier de configuration, qui doit être traitée avant de lancer l'application :logger .


L'approche la plus courante qui a donné naissance à un grand nombre du même type de bibliothèques hex.pm consiste à créer Logger.Backend , qui comprend et crache la console JSON, et à visser une sorte de livraison de journal là où vous en avez besoin (généralement c'est une sorte de LaaS ) . Ainsi, tous les journaux se retrouvent généralement dans une base de données NoSQL , comme Elastic , ou quelque chose de similaire.


Nous ne sommes pas devenus originaux et nous stockons également nos journaux dans Elastic , mais maintenant les journaux seuls ne suffisent plus: les garçons à la mode modernes s'accrochent à tous les messages dans les journaux - des mesures pour tout sur tout. La norme de facto pour travailler avec des métriques dans les applications OTP a récemment été la bibliothèque de télémétrie , un projet open source relativement récent visant à unifier et à normaliser la façon dont les bibliothèques et les applications BEAM sont instrumentées et contrôlées .


L'approche adoptée par la télémétrie est simple au :telemetry.execute/2 horreur: nous appelons :telemetry.execute/2 chaque fois qu'il y a un besoin de mesurer quelque chose dans l'application, et la bibliothèque répond avec le rappel enregistré au début de l'application. De plus, il est possible d'attacher Telemetry.Poller et d'effectuer périodiquement des requêtes métriques. L'exemple dans l'article auquel j'ai donné le lien ci-dessus suggère d'appeler Logger.log/3 partir du gestionnaire d'événements de télémétrie interne.


Gelato


Je déteste le code passe-partout que vous devez faire glisser-copier de projet en projet, de fichier en fichier. Je veux que tout ce qui peut être fait par le compilateur, le planificateur et les travailleurs soit fait pour que je n'y pense même pas. Pour ce faire, j'emballe souvent le code passe-partout dans de minuscules bibliothèques qui cachent tous les passe-partout nécessaires sous le capot et fournissent des interfaces propres pour effectuer les actions nécessaires à notre application. Je voudrais juste quelque chose qui puisse être appelé comme report("message", payload) pour créer un enregistrement, ajouter des données de télémétrie et envoyer cet enregistrement à notre stockage élastique.


Il s'avère que ce n'est pas si difficile à faire.


Nous avons décidé d'utiliser les appels Logger standard comme interface, afin qu'en changeant simplement les configurations, nous puissions introduire la fonctionnalité souhaitée dans les projets existants. Ajoutez simplement un nouveau Logger.Backend à un projet existant:


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

- et voilà - les journaux avec télémétrie sont désormais envoyés dans un bunker élastique.


Et c'est ainsi que la bibliothèque Gelato a vu le jour. Je sais que les vrais développeurs sérieux et réfléchis, comme les bibliothèques, doivent être appelés un peu moins ésotériquement, mais je ne suis pas un vrai développeur. Ce qui est, vous devez vous réconcilier. Bien que le gelato (en espagnol - la crème glacée, soit dit en passant) soit même un peu en phase avec l'élasticité.


La bibliothèque est très concentrée sur la façon dont je vois le bon monde, et dans la queue et la crinière utilise l'approche de «convention au-dessus de la configuration». Il regroupe tout ce dont vous pourriez avoir besoin dans un seul JSON et l'envoie à un serveur élastique préconfiguré avec une simple requête HTTP. Il joint également toutes les métadonnées qu'il peut atteindre, telles que les mesures obtenues à l'aide de Process.info/1 , etc.


Pour commencer à utiliser cette bibliothèque dans un projet, vous devez ajouter ce qui suit à votre fichier config/releases.exs :


 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 

Après cela, tout appel Logger.log/3 comme celui ci-dessous sera transmis par telemetry et envoyé au serveur élastique configuré.


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

La bibliothèque présente également la macro Gelato.bench/4 , qui prend un bloc et effectue deux appels à Logger.log/3 : un avant l'exécution du bloc et l'autre immédiatement après, par type d'aspects en Java.


Gelato insiste discrètement sur une meilleure organisation des interfaces au sein des projets en utilisant la macro Gelato.defdelegatelog/2 , la composition simple Gelato.bench/4 et Kernel.defdelegate/2 . À l'aide de cette macro, vous pouvez extraire toutes les interfaces du projet dans un ensemble limité de modules de niveau supérieur et effectuer ces appels enregistrés avec la télémétrie hors de la boîte.


Envío.Log


Logger.Backend autre implémentation de Logger.Backend qui est née dans notre coin de passion technologique. Il utilise la bibliothèque Envío pour envoyer des messages à un canal Slack dédié. Cet enregistreur a son propre paramètre log_level , dont la valeur est généralement définie sur :warn ou :error , pour empêcher le canal Slack d'être spammé, et tous les appels à des niveaux inférieurs à ceux configurés seront supprimés de BEAM lors de la compilation.


Une configuration typique ressemblerait à ceci:


 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"} ] } } 

Après la configuration, tous les appels à l' Logger.{warn,error}/2 seront envoyés au canal Slack correspondant. Il est très pratique pour surveiller les processus de travail en production en temps réel.


Bonne journalisation!

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


All Articles