Escrevendo alguns logs realmente decentes

Melhores práticas e conselhos com registros

Chris Cooney em HackerNoon.com Segue em 2 de jul · 5 min ler

O registro geralmente não é visto como uma tarefa crucial e inicial. Um engenheiro me disse uma vez: "Bem, os logs são como comentários, certo?" . Não, engenheiro sem nome. Eles não são como comentários. Eles são muito mais do que comentários. Eles são uma das formas mais flexíveis de visualizar o desempenho do seu sistema. Eles são frequentemente negligenciados, não amados ou mal utilizados.

Eu vi alguns logs terríveis. Eu tenho SSH em um servidor às 3 da manhã, apenas para encontrar logs como processing... repetidamente em um arquivo. Sem utilidade. Então, à luz das minhas noites sem dormir e da solução de problemas frenéticos, pensei em lançar algumas das práticas que podem levar seus logs dos logs para o LOGS .

Não, não esses tipos de registros, oh apenas leia o maldito artigo.

Coloque todos os ovos na mesma cesta.

Também conhecido como Agregação de Log. A ideia aqui é ter um portal único para todos os seus logs de aplicativos. Você não quer entrar e sair de servidores para descobrir qual instância do seu aplicativo está falhando. A ferramenta mais comum que as pessoas usam é a pilha ELK . O Guru99 produziu um grande mergulho sobre o que é e como configurá-lo. Eu recomendaria enfaticamente colocar algum tipo de agregação de log como seu primeiro porto de escala.

E ocasionalmente comer alguns desses ovos

Algo que muitas vezes é esquecido é a remoção de logs. As instâncias do Elasticsearch ficam sobrecarregadas com grandes quantidades de logs irrelevantes. Ferramentas como o Curator são úteis para apagar registros antigos. Você precisa conversar sobre o período de retenção dos registros, levando em consideração os requisitos regulamentares e investigativos.

Escreva seus logs em um formato analisável

Isso está vinculado à recomendação acima. Quando você escreve seus logs em JSON (por exemplo), você tem algumas oportunidades interessantes abertas para você. O JSON limita a legibilidade, mas cria logs pesquisáveis e pesquisáveis. É aí que a agregação do Log dá um novo passo à frente. Por exemplo, usando o Slf4j em Java, pode-se escrever um log como este:

 log.info ("Um usuário foi criado", valor ("userId", user.getId ()); 

Agora, quando você está pesquisando através de seus logs, você pode executar uma consulta como a seguinte no Kibana (o K na pilha ELK):

 userId: 1234 E mensagem: "Um usuário foi criado" 

Não há mais peneirar um arquivo e escrever comandos grep aleatórios na hora. Basta consultar seu armazenamento elasticsearch. O mesmo vale para coisas como IDs de correlação, para que você possa rastrear o movimento de uma mensagem até o seu sistema.

Inclua uma mensagem legível por humanos

OK, seus logs estão em JSON e armazenados no Elasticsearch. Você está fazendo bom uso do Kibana para consultá-los e está se divertindo muito. Mas não esqueça o básico! Inclua uma mensagem simples, legível por humanos, que descreva o que está acontecendo. Mantenha isso em seu próprio campo, como parte do seu log. Isso não precisa ser uma frase longa, ou mesmo uma sentença. Até algo como:

 log.info ("UserCreated", ...); 

Precisa haver algum campo que especifique, sucintamente, o que está acontecendo. Isso parece óbvio, mas muitas vezes é ignorado e aparecem mensagens de log como o processing user . O que o processamento realmente significa? Você está excluindo-os? Quem sabe! Assim como suas variáveis, nomes de aplicativos e recursos REST, seja claro e direto com seus logs.

Registrar consistentemente

Muitas vezes, as mensagens de log podem diferir um pouco dentro do seu aplicativo. Para evitar isso, recomendo abstrair parte do seu registro de chaves em um serviço próprio. Isso evita a repetição, mas também cria um único local que você pode verificar para ver quais são as mensagens de log corretas.

 public class MyController { 
public void handleRequest (Request req) {
MyLogger.logIncomingRequest (req);
}
}
classe pública MyLogger {
public static void logIncomingRequest (Request req) {
log.info ("...");
}
}

Esse padrão tem alguns trade offs. Você está ocultando seus logs por trás de um serviço e perde o valor de anotação que os logs podem fornecer. A vantagem é que, quando seus logs centrais estão todos na mesma classe, é muito mais fácil mantê-los consistentes.

Registre em vários níveis

Depois de capturar seus principais eventos de negócios em seus registros, você poderá ficar tentado a parar. Não! Continue, você tem muito mais a fazer! Entre todas essas mensagens UserCreated usuário, você tem gravações de banco de dados, leituras de banco de dados e criação de objetos. É por isso que o bom Deus criou vários níveis de log. Um bom exemplo de uso efetivo desses registros é:

 log.debug ("UserCreationRequestReceived", ...); 
log.debug ("CheckingToSeeIfUserExists", ...);
log.trace ("Consulta DB Concluída", ...);
log.trace ("MappingToUserObject", ...);
log.debug ("UserDoesNotExist", ...);
log.debug ("Criando usuário", ...);
...
log.info ("UserCreated", ...);

Isso parece excessivo, mas quando você está em uma situação de crise, você quer ter esse tipo de visibilidade disponível para você. Então, como você controla o barulho?

Alterar o nível de log sem reiniciar

Quando você registra em múltiplos níveis, você precisa decidir quais logs serão silenciados. Por exemplo, se você definir seu nível de log como info , suprimirá seus logs de nível de debug e trace . Se você configurá-lo para trace , você vai conseguir tudo.

O que é essencial aqui é que você pode discar rapidamente seus detalhes de registro em uma crise. Se você já estiver usando o Spring Boot, você pode fazer isso de graça com o Actuator . Isso é muito específico da linguagem, mas muitas ferramentas já existem para as linguagens e estruturas conhecidas. Isso vale a pena implementar. Ele forma uma parte essencial de sua automação de recuperação de desastres.

Inclua valores significativos e pesquisáveis em seus registros

Se você tem uma API e deseja vincular todas as atividades associadas a uma determinada solicitação, anexar um valor de consulta a suas linhas de log é uma maneira muito poderosa de agrupar atividades comuns. Isso pode ser algo tão simples quanto um UUID gerado no ponto de solicitação. Imagine um código de registro semelhante a este:

 log.info ("UserArrived", 
value ("sessionId", "1234"),
valor ("userId", "5432")
);
// Algumas coisas
log.error ("UserError",
valor ("causa", "Conta de usuário desativada"),
value ("sessionId", "1234"),
valor ("userId", "5432")
);
// Mais algumas coisas
log.info ("UserAccountEnabled",
value ("sessionId", "1234"),
valor ("userId", "5432")
);

Agora, quando você está procurando no Kibana por uma determinada sessão, tudo o que você precisa fazer é consultar esse ID de sessão. Boom, você tem absolutamente tudo o que ocorreu no seu sistema. Se você quisesse saber sobre essa sessão em particular, você pode procurar por sessionId: 1234 e se você quiser tudo para esse usuário, userId: 5432 .

Isso também funcionará em microsserviços, criando um único thread que vincula todo o comportamento do usuário. O truque é escolher os valores corretos. IDs de sessão estão bem, mas eles podem ser um problema. Primeiro você precisa encontrar a sessão para encontrar o ID. Coisas como IDs de usuário são melhores, pois essas informações provavelmente estarão disponíveis quando você iniciar sua investigação. Isso cria uma propriedade conhecida como "rastreabilidade".

Texto original em inglês.