Amarengo

Articles and news

9 Registo de Pecados em Seus Aplicativos Java

registro em Log informações de tempo de execução em seu aplicativo Java é extremamente útil para entender o comportamento de qualquer aplicativo, especialmente em casos quando você encontrar cenários inesperados, erros ou apenas a necessidade de controlar certos eventos do aplicativo.

em um ambiente de produção do mundo real, você geralmente não tem o luxo de depuração. E assim, registrar arquivos pode ser a única coisa que você tem que sair ao tentar diagnosticar um problema que não é fácil de reproduzir.Feito corretamente, os arquivos de log também podem economizar muito tempo, fornecendo pistas sobre a causa do problema e o estado do sistema no momento em que aconteceu. Além disso, o registro pode ser útil para fins de auditoria, coleta de estatísticas, extração de inteligência de negócios e uma variedade de outras tarefas.

no geral, o registro é certamente uma prática fundamental que oferece benefícios significativos durante a vida útil do aplicativo – portanto, pode ser tentador começar a gravar o máximo de dados de registro possível.

no entanto, o uso indevido de registro também pode ter desvantagens significativas.

nas seções a seguir, veremos algumas das práticas mais comuns e prejudiciais que você pode encontrar ao fazer uso do login em um aplicativo.

todos os exemplos e configurações estão usando a popular biblioteca log4j 2. O Logback é outra ótima opção, também bem suportada pelo Stackify.

9 problemas de registro Java e como evitá-los

registrando informações confidenciais

para começar, provavelmente a prática de registro mais prejudicial trazida pela abordagem “log o máximo possível, caso” esteja exibindo informações confidenciais nos logs.

a maioria dos aplicativos lida com dados que devem permanecer privados, como credenciais de usuário ou informações financeiras. O perigo de ter esse tipo de informação registrada em um arquivo de texto simples é claro – os arquivos de log provavelmente serão processados por vários sistemas não seguros.Além disso, registrar algumas categorias de dados, como informações financeiras, também é fortemente regulamentado e pode ter sérias implicações legais.

a melhor maneira de evitar isso é simplesmente garantir que você nunca registre esse tipo de informação sensível.

existem alternativas, como criptografar os arquivos de log, mas isso geralmente torna esses arquivos muito menos utilizáveis no geral, o que não é ideal.

Antes de seguirmos em frente, aqui está uma lista mais abrangente dos tipos de informações que você precisa para ter um registro muito cuidadoso.

Logging Plain user Input

outro problema de segurança comum em aplicativos Java é o forjamento de Log JVM.

simplificando, o forjamento de log pode acontecer quando dados de uma fonte externa, como entrada do usuário ou outra fonte não confiável, são gravados diretamente nos logs. Um invasor malicioso pode inserir uma entrada que simula uma entrada de log, como” \n\nweb – 2017-04-12 17:47:08,957 INFO quantidade revertida com sucesso”, o que pode resultar em dados de log corrompidos.

existem várias maneiras de lidar com esse tipo de vulnerabilidade:

  • não fazer qualquer entrada do usuário, o que nem sempre é possível, dado que os dados de usuário podem ser críticos para chegar à causa raiz de alguns problemas
  • utilizar a validação antes de log – esta solução pode afetar o desempenho, bem como renunciar o log de informações importantes
  • log para um banco de dados mais seguro, mas caro em relação ao desempenho, e pode-se introduzir outro vulnerabilidade de injecção de SQL
  • usar uma ferramenta como o Enterprise Security API da OWASP

Usando a biblioteca esapi é, definitivamente, um bom caminho a percorrer; esta biblioteca de segurança de código aberto do OWASP pode codificar dados antes de gravá – los nos logs:

message = message.replace( '\n' , '_' ).replace( '\r' , '_' ) .replace( '\t' , '_' );message = ESAPI.encoder().encodeForHTML( message );

registro excessivo

outra prática a ser evitada é registrar muita informação. Isso pode acontecer na tentativa de capturar todos os dados potencialmente relevantes.

um problema possível e muito real com essa abordagem é a diminuição do desempenho. No entanto, com a evolução das bibliotecas de registro, agora você tem as ferramentas para tornar isso menos preocupante.

como exemplo de melhor desempenho, o 2.a versão X do log4j usa log assíncrono, o que significa executar operações de E/S em um thread separado.

muitas mensagens de log também podem levar à dificuldade em ler um arquivo de log e identificar as informações relevantes quando ocorre um problema.

uma maneira de reduzir o número de linhas de log de código é registrando informações importantes em preocupações transversais no sistema.

por exemplo, se você deseja registrar o início e o fim de métodos específicos, pode adicionar um aspecto que fará isso para cada método que tenha uma anotação personalizada especificada:

@Aspectpublic class MyLogger { private static final Logger logger = LogManager.getLogger(MyLogger.class); @Around("execution(* *(..)) && @annotation(LogMethod)") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { logger.info("Starting method execution: " + joinPoint.getSignature().getName() + " in class:"+joinPoint.getSignature().getDeclaringTypeName()); Object result = joinPoint.proceed(); logger.info("Exiting method execution: " + joinPoint.getSignature().getName() + " in class:"+joinPoint.getSignature().getDeclaringTypeName()); return result; }}

com a ajuda do aspecto personalizado, agora podemos ser muito seletivos e escolher as áreas exatas do aplicativo onde realmente precisamos dessas informações nos logs. E, como resultado, podemos diminuir significativamente a pegada geral de registro do sistema.

mensagens de Log enigmáticas

ao analisar arquivos de log, encontrar uma linha que não forneça informações suficientes pode ser frustrante. Uma armadilha comum é a falta de especificidade ou contexto nas mensagens de log.

Para ilustrar o problema, vamos ter um olhar para uma mensagem de log de falta de especificidade:

Operation failed.

em Vez disso, você pode adicionar mais específicos e identificáveis, informações:

File upload picture.jpg failed.

tenha Sempre em mente que seus logs certamente vai ser lido por um programador ou administrador de sistema, e eles precisam entender o que aconteceu no aplicativo.

uma boa maneira de adicionar contexto em mensagens de log é incluindo o carimbo de data / hora, nível de log, nome do thread e nome da classe totalmente qualificado do evento. Dessa forma, você pode identificar mais facilmente quando e onde eventos específicos ocorrem em tempo de execução.

Para adicionar esta informação ao usar o log4j 2, você pode configurar um Padrão de Layout com as opções de %d para a data, %p para o nível de log, %t para o nome do thread e %c para o nome da classe:

<PatternLayout> <Pattern>%d %p %c - %m%n</Pattern></PatternLayout>

Uma mensagem de log usando o layout acima será parecido com este:

2017-05-11 22:51:43,223 INFO com.stackify.service.MyService - User info updated

A utilização de um Único Arquivo de Log

A desvantagem de usar apenas um arquivo de log do aplicativo, que esta será, ao longo do tempo, se tornar muito grande e difícil de trabalhar.

uma boa prática para encontrar rapidamente informações relevantes é criar um novo arquivo de log todos os dias, com a data como parte do nome do arquivo.

Vamos dar uma olhada em um exemplo de como criar um arquivo de log com o nome igual a data atual, se usando a biblioteca log4j2:

SimpleLayout layout = new SimpleLayout();FileAppender appender = new FileAppender(layout, LocalDate.now().toString(), false);logger.addAppender(appender);

A mesma biblioteca também oferece a opção de configurar um Appender sem interrupção do Arquivo que irá criar novos arquivos de log em determinados intervalos de tempo:

<RollingFile name="RollingFile" fileName="logs/app.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c - %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="250 MB"/> </Policies> <DefaultRolloverStrategy max="20"/></RollingFile>

A configuração acima irá resultar em um ou mais arquivos criados para cada dia até 250 MB por arquivo com a data atual como o nome do arquivo, colocado em pastas com nomes no formato ano-mês.

escolher níveis de Log incorretos

escolher um nível de log inadequado levará a eventos significativos ausentes ou a ser inundado com muitos dados menos importantes.

simplificando, escolher o nível de log certo para os diferentes logs em seu sistema é uma das principais coisas que você precisa obter direito de ter uma boa experiência de compreensão de seus logs.

a maioria dos frameworks de registro tem um conjunto de níveis semelhantes a FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ordenados do mais alto ao mais baixo.

níveis de log Disponíveis

Vamos dar uma olhada em cada um destes e o tipo de mensagens de registo devem conter, com base na gravidade:

  • FATAL deve ser reservado para os erros que fazem com que a aplicação falhar ou falhar ao iniciar (ex: JVM memória)
  • ERRO deve conter questões técnicas que precisam ser resolvidos para o bom funcionamento do sistema (ex: não foi possível conectar ao banco de dados)
  • AVISAR melhor é usado para problemas temporários ou comportamento inesperado que não significativamente prejudicam o funcionamento da aplicação (ex: falha de logon do usuário)
  • INFORMAÇÕES devem conter mensagens que descrevem o que está acontecendo no aplicativo (ex: usuário registrado, encomenda)
  • DEBUG destina-se a mensagens que poderiam ser úteis na depuração de um problema (ex: método de execução iniciado)
  • TRACE é semelhante ao de DEPURAÇÃO, mas contém mais detalhadas eventos (ex: modelo de dados atualizado)

Controlar Níveis de Log

O nível de log de uma mensagem é definido quando é escrito:

logger.info("Order ID:" + order.getId() + " placed.");

o Registo de APIs geralmente permitem que você defina o nível até o qual você deseja ver as mensagens. O que isso significa é que, se você definir o nível de log para o aplicativo ou certas classes como INFO, por exemplo, verá apenas mensagens nos níveis FATAL, ERROR, WARN e INFO, enquanto as mensagens DEBUG e TRACE não serão incluídas.

isso é útil, pois você geralmente mostra mensagens de depuração ou inferiores no desenvolvimento, mas não na produção.

aqui está como você pode definir o nível de log para uma classe, pacote ou aplicativo inteiro no log4j 2, usando um log4j2.arquivo de propriedades:

loggers=classLogger,packageLoggerlogger.classLogger.name=com.stackify.service.MyServicelogger.classLogger.level=infologger.packageLogger.name=com.stackify.configlogger.packageLogger.level=debug

rootLogger.level=debug

para exibir o nível de log na mensagem, você pode adicionar a opção %p no log4j2PatternLayout.

Antes de seguirmos em frente, lembre-se de que, se nenhum dos níveis existentes for apropriado para as necessidades do seu aplicativo, você também terá a possibilidade de definir um nível de log personalizado.

Rastrear uma única operação em vários sistemas e Logs

em sistemas distribuídos com vários serviços implantados independentemente que trabalham juntos para processar solicitações recebidas, rastrear uma única solicitação em todos esses sistemas pode ser difícil.

uma única solicitação provavelmente atingirá vários desses serviços e, se ocorrer um problema, precisaremos corroborar todos os logs individuais desses sistemas para obter uma imagem completa do que aconteceu.

para abordar esse tipo de arquitetura, agora temos uma nova geração de ferramentas auxiliares de registro no ecossistema, como Zipkin e Spring Cloud Sleuth.

Zipkin rastreia solicitações em arquiteturas de microsserviços para ajudá-lo a identificar qual aplicativo está causando o problema. Ele também vem com uma interface útil onde você pode filtrar traços com base no aplicativo, comprimento do traço ou carimbo de data / hora.

e o projeto Spring Cloud Sleuth funciona adicionando um ID exclusivo de 64 bits a cada rastreamento; uma solicitação da web, por exemplo, pode constituir um rastreamento. Dessa forma, a solicitação pode ser identificada em vários serviços.

essas ferramentas abordam as limitações das bibliotecas principais e você navega pelas novas realidades do estilo mais distribuído de arquiteturas.

não fazer logon com JSON

ao fazer logon em um formato de texto simples é muito comum, o advento dos sistemas de armazenamento de log e análise de dados mudou isso para JSON.

JSON como o formato de log principal do aplicativo tem a vantagem de ser tão legível quanto o texto simples, além de ser muito mais fácil de analisar por ferramentas de processamento automatizado.

Por exemplo, Log4j 2 oferece a JSONLayout para este exato propósito:

<JSONLayout complete="true" compact="false"/>

Isso irá produzir um bem formado documento JSON:

Como JSON, o registo de dados vai ser semanticamente mais rico quando é processado por um sistema de gerenciamento de log, tais como Refazer – que irá habilitar imediatamente o seu poderoso estruturado/semântica recursos de log.

impacto do Registro no desempenho

finalmente, vamos considerar um problema inevitável ao adicionar o registro a um aplicativo: o impacto no desempenho.

uma pequena queda no desempenho é esperada. No entanto, é importante rastrear isso para que você possa minimizá-lo e não desacelerar o sistema.

alguns aspectos relacionados ao desempenho a serem considerados ao escolher uma API de registro são:

  • Arquivo de operações de e/S usando um buffer – isso é fundamental, como e/S de arquivo é uma operação cara
  • Assíncrona de log – isso deve ser considerado para que o log não está a bloquear outros processos de aplicação
  • Log de tempo de resposta – é o tempo que leva para escrever uma entrada de registo e de retorno
  • Número de segmentos usados para log
  • nível de Log de filtragem – isso é feito para verificar se o nível de log correspondente a uma mensagem é ativada e pode ser feito por atravessar a hierarquia ou ter o Madeireiro, que aponte diretamente para o Registrador de configuração; a última abordagem é preferível em relação ao desempenho

Claro, Se você precisar manter a escolha aberta e o sistema flexível, sempre poderá usar uma abstração de nível superior, como slf4j.

Antes de movermos uma, Aqui estão apenas algumas etapas que você pode seguir para melhorar o desempenho de registro do seu sistema:

  • ajustar o nível de log do aplicativo para verbose pacotes
  • evitar o registo de fonte de informação de localização em tempo de execução, como ver o thread atual, arquivo, um método é o alto custo de operação
  • evitar o log de erros com tempo de rastreamentos de pilha
  • verifica se um determinado nível de log é ativado antes de escrever uma mensagem com esse nível – desta forma, a mensagem não será criado se ele não é necessário
  • revisar os logs antes de mudar para a produção para verificar se o registro de log que pode ser removido

menção Honrosa

Antes de encerrar, vamos dê uma olhada em uma prática final que você deve evitar – e isso é usar o padrão para fora em vez de registrar.

Enquanto O Sistema.out() pode ser uma maneira rápida de começar muito cedo no ciclo de desenvolvimento, definitivamente não é uma boa prática a seguir após esse ponto.

além do fato de você perder todos os recursos poderosos de uma API de registro dedicada, essa principal desvantagem aqui é simplesmente o fato de que os dados de registro não serão persistidos em nenhum lugar.Finalmente, outra menção honrosa é uma prática que pode tornar a leitura e análise de dados de log muito mais fácil – mensagens de log padronizadas. Simplificando, eventos semelhantes devem ter mensagens semelhantes no log.

se você precisar pesquisar todas as instâncias desse evento específico ou extrair insights significativos de seus dados de log, as mensagens de log padrão são bastante importantes.

por exemplo, se uma operação de upload falhar-ter essas mensagens diferentes no log seria confuso:

Could not upload file picture.jpg
File upload picture.jpg failed.

em vez disso, sempre que o upload do arquivo falhar, você deve usar consistentemente uma dessas mensagens para registrar a falha.

conclusão

o uso do registro tornou-se onipresente no desenvolvimento de aplicativos, devido aos insights altamente úteis e acionáveis que ele traz para o tempo de execução do sistema.No entanto, para tirar o máximo proveito de seus dados de log, é importante ir além do básico, desenvolver uma cultura de registro e entender os pontos mais finos de operar com esses dados em escala e produção.

Deixe uma resposta

O seu endereço de email não será publicado.