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",
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,
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!