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
e logback-core
):
package chapters.introduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// copied from: http://www.slf4j.org/manual.html
public class HelloWorld {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.debug("Hello world, I'm a DEBUG level message");
logger.info("Hello world, I'm an INFO level message");
logger.warn("Hello world, I'm a WARNING level message");
logger.error("Hello world, I'm an ERROR level message");
}
}
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:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
final Logger logger = LoggerFactory.getLogger(MyCLASS.class);
public void doSomething() {
// some code here
logger.debug("this is useful");
if (isSomeConditionTrue()) {
logger.info("I entered by conditional block!");
}
}
}
Mas, na verdade, é ainda mais comum declarar o criador de logs com o seguinte formato:
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
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:
Logger logger = LoggerFactory.getLogger("MyModuleName");
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:
if (LOGGER.isDebugEnabled()) {
// lots of debug logging here, or even code that
// is only used in a debugging context.
LOGGER.debug(" result: " + heavyComputation());
}
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), o heavyComputation()
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:
- configuração programática (em tempo de execução, via API - permite alterações no tempo de execução ),
- configuração declarativa estática (na hora de início, geralmente por meio de um arquivo XML ou de propriedades - provavelmente o que você precisa primeiro ).
Eles também oferecem principalmente os mesmos recursos:
- configuração do formato da mensagem de saída (timestamps, marcadores, etc ...),
- configuração dos níveis de saída,
- configuração de filtros refinados (por exemplo, para incluir / excluir pacotes ou classes),
- configuração de anexadores para determinar onde fazer logon (para console, arquivar, para um serviço da Web ...) e possivelmente o que fazer com logs mais antigos (por exemplo, com arquivos de rolagem automática).
Aqui está um exemplo comum de uma configuração declarativa, usando um logback.xml
arquivo.
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
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.