À medida que meus projetos Java atuais crescem cada vez mais, sinto uma necessidade crescente de inserir saída de depuração em vários pontos do meu código.
Para habilitar ou desabilitar esse recurso de maneira apropriada, dependendo da abertura ou do fechamento das sessões de teste, eu geralmente coloco um private static final boolean DEBUG = false
no início das aulas que meus testes estão inspecionando e o uso trivialmente desta maneira (por exemplo):
public MyClass {
private static final boolean DEBUG = false;
... some code ...
public void myMethod(String s) {
if (DEBUG) {
System.out.println(s);
}
}
}
e similar.
Mas isso não me deixa muito feliz, porque é claro que funciona, mas pode haver muitas classes para definir DEBUG como verdadeiro, se você não estiver olhando apenas algumas delas.
Por outro lado, eu (como - acho - muitos outros) não gostaria de colocar o aplicativo inteiro no modo de depuração, pois a quantidade de texto que está sendo produzida pode ser esmagadora.
Portanto, existe uma maneira correta de lidar com essa situação arquitetonicamente ou a maneira mais correta é usar o membro da classe DEBUG?
Respostas:
Você deseja examinar uma estrutura de log e, talvez, uma estrutura de fachada de log.
Existem várias estruturas de registro por aí, geralmente com funcionalidades sobrepostas, tanto que, com o tempo, muitas evoluíram para depender de uma API comum ou passaram a ser usadas através de uma estrutura de fachada para abstrair seu uso e permitir que elas fossem trocadas no local se necessário.
Frameworks
Algumas estruturas de log
Algumas fachadas de log
Uso
Exemplo básico
A maioria dessas estruturas permitiria escrever algo do formulário (aqui usando
slf4j-api
elogback-core
):Observe o uso de uma classe atual para criar um criador de logs dedicado, o que permitiria ao SLF4J / LogBack formatar a saída e indicar de onde veio a mensagem de registro.
Conforme observado no manual do SLF4J , um padrão de uso típico em uma classe é geralmente:
Mas, na verdade, é ainda mais comum declarar o criador de logs com o seguinte formato:
Isso permite que o criador de logs seja usado também dentro de métodos estáticos e é compartilhado entre todas as instâncias da classe. É bem provável que seja sua forma preferida. No entanto, como observado por Brendan Long nos comentários, você deve entender as implicações e decidir adequadamente (isso se aplica a todas as estruturas de registro que seguem essas expressões idiomáticas).
Existem outras maneiras de instanciar os criadores de logs, por exemplo, usando um parâmetro string para criar um criador de logs nomeado:
Níveis de depuração
Os níveis de depuração variam de uma estrutura para outra, mas os comuns são (em ordem de criticidade, de benignos a ruins) e provavelmente muito comuns a esperançosamente muito raros:
TRACE
Informações muito detalhadas. Deve ser gravado apenas nos logs. Usado apenas para rastrear o fluxo do programa nos pontos de verificação.DEBUG
Informação detalhada. Deve ser gravado apenas nos logs.INFO
Eventos de tempo de execução notáveis. Deve estar imediatamente visível em um console, portanto, use com moderação.WARNING
Esquisitices de tempo de execução e erros recuperáveis.ERROR
Outros erros de tempo de execução ou condições inesperadas.FATAL
Erros graves que causam rescisão prematura.Blocos e guardas
Agora, digamos que você tenha uma seção de código na qual está prestes a escrever várias instruções de depuração. Isso pode afetar rapidamente seu desempenho, devido ao impacto do próprio log e da geração de quaisquer parâmetros que você possa estar passando para o método de log.
Para evitar esse tipo de problema, muitas vezes você deseja escrever algo no formato:
Se você não tivesse usado esse protetor antes de seu bloco de instruções de depuração, mesmo que as mensagens não sejam exibidas (se, por exemplo, seu criador de logs estiver configurado para imprimir apenas itens acima do
INFO
nível), oheavyComputation()
método ainda teria sido executado .Configuração
A configuração é bastante dependente da sua estrutura de log, mas eles oferecem basicamente as mesmas técnicas para isso:
Eles também oferecem principalmente os mesmos recursos:
Aqui está um exemplo comum de uma configuração declarativa, usando um
logback.xml
arquivo.Como mencionado, isso depende da sua estrutura e pode haver outras alternativas (por exemplo, o LogBack também permite que um script Groovy seja usado). O formato de configuração XML também pode variar de uma implementação para outra.
Para mais exemplos de configuração, consulte (entre outros):
Um pouco de diversão histórica
Por favor note que Log4J está vendo uma grande atualização no momento, a transição da versão 1.x para 2.x . Você pode querer dar uma olhada em ambos para obter mais diversão ou confusão histórica, e se você escolher o Log4J, provavelmente preferirá usar a versão 2.x.
Vale ressaltar, como Mike Partridge mencionou nos comentários, que o LogBack foi criado por um ex-membro da equipe do Log4J. Que foi criado para solucionar as deficiências da estrutura Java Logging. E que a próxima versão principal do Log4J 2.x está agora integrando alguns recursos retirados do LogBack.
Recomendação
Resumindo, mantenha-se o mais dissociado possível, brinque com alguns e veja o que funciona melhor para você. No final , é apenas uma estrutura de registro . Exceto se você tiver um motivo muito específico, além da facilidade de uso e da preferência pessoal, qualquer um deles funcionaria bem, então não faz sentido ficar de olho nele. A maioria deles também pode ser estendida às suas necessidades.
Ainda assim, se eu tivesse que escolher uma combinação hoje, iria com o LogBack + SLF4J. Mas se você me perguntasse alguns anos depois, eu recomendaria o Log4J com o Apache Commons Logging, portanto, fique de olho nas suas dependências e evolua com elas.
fonte
static
, pois economiza uma pequena quantidade de memória, mas causa problemas em certos casos: slf4j.org/faq.html#declared_staticusar uma estrutura de log
na maioria das vezes há um método estático de fábrica
então você pode gerar seu código de log com diferentes níveis:
haverá um único arquivo onde você poderá definir quais mensagens para cada classe devem ser gravadas na saída do log (arquivo ou stderr)
fonte
É exatamente para isso que servem as estruturas de log como log4j ou o slf4j mais recente. Eles permitem controlar o registro em detalhes e configurá-lo mesmo enquanto o aplicativo está em execução.
fonte
Uma estrutura de log é definitivamente o caminho a percorrer. No entanto, você também deve ter um bom conjunto de testes. Uma boa cobertura de teste geralmente pode eliminar a necessidade de saída de depuração todos juntos.
fonte