Monitorando aplicativos com o Logger.

O Elixir faz uso total da infraestrutura de log Erlang para criar logs. A partir da versão 1.10 , que será lançada em breve, novas funções de registro de usuários que apareceram no Erlang / OTP 21+ estão disponíveis para nós.


Embora o OTP forneça toda a infraestrutura para a entrega de eventos do diário (eventos) aos assinantes, o próprio registro, se entendido como armazenamento e / ou exibição de eventos do diário, deve ser implementado pelo aplicativo. Para esse propósito, a abstração correspondente do Logger.Backend .


Aqui está um trecho da documentação oficial:


Logger criador de logs suporta vários back-end onde as mensagens de log são gravadas.

Os back-end disponíveis, por padrão, são limitados a um:
  • :console - registra mensagens no console (ativado por padrão)


Qualquer desenvolvedor pode criar sua própria colheita como um back-end para o Logger . Como o Logger é um gerenciador de eventos que implementa o comportamento Erlang :gen_event , escrever um novo back-end é apenas uma questão de criar seu próprio manipulador de eventos, conforme descrito na documentação para :gen_event .

Os back-ends usados ​​são carregados na seção :backends no arquivo de configuração, que deve ser processada antes de iniciar o aplicativo :logger .


A abordagem mais comum que deu origem a muitas do mesmo tipo de bibliotecas hex.pm é criar um Logger.Backend que entende e cospe o console JSON e Logger.Backend algum tipo de entrega de log para onde você precisa (geralmente é algum tipo de LaaS ) . Assim, todos os logs geralmente terminam em um banco de dados NoSQL , como o Elastic , ou algo semelhante.


Não nos tornamos originais, e também armazenamos nossos registros no Elastic , mas agora os registros por si só não são suficientes: os meninos da moda moderna se apegam a todas as mensagens nos registros - métricas para tudo sobre tudo. O padrão de fato para trabalhar com métricas em aplicativos OTP foi recentemente a biblioteca de Telemetria , um projeto de código aberto relativamente recente que visa unificar e padronizar como as bibliotecas e aplicativos BEAM são instrumentados e controlados .


A abordagem adotada pela Telemetria é simples ao :telemetry.execute/2 horror: chamamos :telemetry.execute/2 sempre que houver necessidade de medir algo no aplicativo, e a biblioteca responde com o retorno de chamada registrado no início do aplicativo. Além disso, é possível anexar o Telemetry.Poller e executar solicitações de métricas periodicamente. O exemplo no artigo ao qual Logger.log/3 o link acima sugere chamar o Logger.log/3 do manipulador de eventos interno de Telemetria .


Gelato


Eu odeio o código padrão que você tem que arrastar copiar e colar de projeto para projeto, de arquivo para arquivo. Quero que tudo que possa ser feito pelo compilador, agendador e trabalhadores seja feito para que eu nem pense nisso. Para fazer isso, costumo incluir o código padrão em pequenas bibliotecas que ocultam todo o padrão necessário sob o capô e fornecem interfaces limpas para a execução das ações necessárias ao nosso aplicativo. Gostaria apenas que algo que pudesse ser chamado de report("message", payload) crie um registro, adicione dados de telemetria e envie esse registro para nosso armazenamento elástico.


Acontece que isso não é tão difícil de fazer.


Decidimos usar as chamadas padrão do Logger como uma interface, para que, simplesmente alterando as configurações, pudéssemos introduzir a funcionalidade desejada nos projetos existentes. Basta adicionar um novo Logger.Backend a um projeto existente:


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

- e voilà - logs com telemetria agora são enviados para um bunker elástico.


E assim surgiu a biblioteca Gelato . Eu sei que desenvolvedores realmente severos e pensativos, como bibliotecas, são chamados um pouco menos esotericamente, mas não sou um desenvolvedor de verdade. O que é, você tem que chegar a um acordo. Embora, o gelato (em espanhol - sorvete, por sinal) esteja um pouco sintonizado com a elasticidade.


A biblioteca está muito focada em como eu vejo o mundo certo, e na cauda e na crina usa a abordagem de "convenção acima da configuração". Ele reúne tudo o que você precisa em um JSON e o envia para um servidor elástico pré-configurado com uma simples solicitação HTTP. Também anexa todos os metadados que pode alcançar, como métricas obtidas usando Process.info/1 , etc.


Para começar a usar esta biblioteca em um projeto, você precisa adicionar o seguinte ao seu 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 

Depois disso, qualquer chamada do Logger.log/3 como a abaixo será transmitida por telemetry e enviada ao servidor elástico configurado.


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

A biblioteca também apresenta a macro Gelato.bench/4 , que pega um bloco e faz duas chamadas para o Logger.log/3 : uma antes do bloco ser executado e a outra imediatamente depois, por tipo de aspectos em Java.


Gelato insiste discretamente em uma melhor organização das interfaces nos projetos usando a macro Gelato.defdelegatelog/2 , a composição simples Gelato.bench/4 e Kernel.defdelegate/2 . Usando essa macro, você pode extrair todas as interfaces do projeto em um conjunto limitado de módulos de nível superior e fazer essas chamadas registradas com telemetria imediatamente.


Envío.Log


Outra implementação do Logger.Backend que nasceu no nosso canto da paixão tecnológica é o Envío.Log . Ele usa a biblioteca Envío para enviar mensagens para um canal Slack dedicado. Esse criador de logs possui sua própria configuração log_level , cujo valor geralmente é definido como :warn ou :error , para impedir que o canal Slack seja spam e todas as chamadas em níveis inferiores ao configurado serão excluídas do BEAM durante a compilação.


Uma configuração típica ficaria assim:


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

Após a configuração, todas as chamadas para o Logger.{warn,error}/2 serão enviadas para o canal Slack correspondente. É muito conveniente para monitorar os processos de trabalho na produção em tempo real.


Tenha um bom registro!

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


All Articles