LOGGING DE EVENTOS COM LOG4J - PDF
Download "LOGGING DE EVENTOS COM LOG4J"
Ester Morais Paixão
1 LOGGING DE EVENTOS COM LOG4J por Luiz Gustavo Stábile de Souza O que é logging? Fazer o logging de uma aplicação é uma das possíveis maneiras de debugá-la, registrando em algum meio (arquivo, enviando s, gravando em bancos de dados, etc..) eventos ocorridos na aplicação, sejam eles apenas informações, ou indicações de erros no processamento. O framework de logging Log4J O Log4j é uma ferramenta open-source de logging, desenvolvida sob o projeto Apache Jakarta. É um conjunto de APIs que permite aos desenvolvedores escreverem declarações de log em seus códigos e configurá-los externamente, através de arquivos de propriedades. Para usarmos o Log4J, precisamos entender três aspectos deste framework: logger, appender, e layout. Entenda a relação dos três como a seguinte: Um logger envia os logs para um appender, que os armazena em um determinado layout (estilo). Logger Pense em um logger como um componente silencioso em sua aplicação, responsável por receber requisições de log e efetuá-las. Cada classe de uma aplicação pode ter um logger individual, mas o framework Log4J oferece um logger padrão. Caso você não crie um logger específico, pode usar o logger padrão oferecido pelo framework, chamando o método estático getrootlogger() da classe Logger. Appender Loggers precisam saber para onde enviar as informações de log. É aqui que os appenders entram em cena. O framework Log4J suporta o envio de informações de log para arquivos (FileAppender), para o console (ConsoleAppender), para bancos de dados (JDBCAppender), para eventos de log de sistemas NT (NTEventLogAppender), para servidores SMTP (SMTPAppender), para servidores remotos (SocketAppender), e outros. Um appender define as propriedades do destino de log para o Log4J. Desta maneira, se nós associarmos um appender do tipo JDBCAppender a um logger, estamos dizendo ao Log4J que os logs passados a este logger devem ser armazenados em uma determinada base de dados. Todas essas informações, referentes a como acessar o meio de armazenamento são propriedades do appender, e são usadas pelo Log4J para saber onde armazenar as informações. Página 1
2 Layout Loggers e appenders estão relacionados a criação e redirecionamento de nossas solicitações de log. E quanto ao formato em que serão armazenadas essas informações de log? Isso é o papel do layout, que define o estilo e o conteúdo da informação de log. Um layout define, por exemplo quando incluir informações de data e hora nos logs, linha onde o log se originou, etc. Relação de herança entre loggers Existe no Log4J uma relação de pai e filho entre os loggers que criamos. Essa relação é definida através de um padrão de nome, com a utilização do operador ponto.. Como citado anteriormente, pelo menos um logger existe para uma aplicação, o logger padrão oferecido pelo framework, e em último caso todos os loggers que criamos são filhos deste logger padrão. Para ilustrar essa relação de pai e filho entre os loggers, imagine que temos um logger cujo nome é br.com.meulogger.mylog, definido para uma classe de mesmo nome e mesmo pacote. Este logger será automaticamente "filho" de um logger que tenha o nome br.com.meulogger, caso ele exista, pelo simples fato de o nome do último fazer parte do nome do primeiro. Níveis de logging no Log4J Todo logger que usamos possui um, de cinco possíveis níveis definidos pelo Log4J: DEBUG, INFO, WARN, ERROR e FATAL. Se esse nível não for configurado explicitamente para um logger, será herdado de um logger "pai", que em último caso pode ser o logger padrão, definido pelo framework, e que possui um nível DEBUG. Portanto, todos os loggers em uma aplicação terão, no mínimo, o nível DEBUG. Mas para que servem estes níveis, e como eles podem afetar o mecanismo de logging? Assim como os loggers, todas as requisições de logging feitas a eles também possuem um nível. As requisições de logging somente serão atendidas se o seu nível for maior ou no mínimo igual ao nível do logger. Por exemplo, suponha que tenho um logger com o nível definido para WARN. Se uma solicitação de logging, de nível INFO chegar a ele, ela não será atendida, e portanto não será registrada no appender relacionado ao logger. Se enviarmos, para este mesmo logger, uma solicitação de logging de nível ERROR, ou WARN, ela será atendida e registrada, pois possui um nível maior ou pelo menos igual ao nível do logger. Essa característica é muito importante, pois podemos modificar externamente (através de arquivos de configuração) o nível dos loggers de nossa aplicação, sem ter que alterar o código. Isso permite habilitar um nível DEBUG durante o desenvolvimento, mas deixar somente o nível ERROR habilitado em produção. Uma aplicação de exemplo Para este exemplo vou utilizar o Eclipse IDE, mas se você preferir, pode executá-lo em outro IDE de sua preferência. Crie um pojeto Java simples, conforme mostra a figura 1: Página 2
3 figura 1: criação de um projeto Java simples Crie para o seu projeto um pacote com o nome de sua preferência, e nele crie uma classe chamada ExemploLog4J: figura 2: criação da classe ExemploLog4J.java Página 3
4 Em seguida, digite o seguinte código para a classe ExemploLog4J (se for necessário, faça as adaptações pra o nome do seu pacote, se ele for diferente): package blogspot.luizgustavoss.log4j; import javax.swing.joptionpane; public class ExemploLog4J { public static void main(string[] a){ ExemploLog4J exemplo = new ExemploLog4J(); exemplo.run(); public void run(){ int quantidade = solicitarquantidade(); int[] valores = new int[quantidade]; lervaloresinteiros(valores); double resultado = calcularmedia(valores); exibirvalorreal(resultado); public void exibirvalorreal(double valor){ JOptionPane.showMessageDialog(null, "o valor é: " + valor); public double calcularmedia(int[] v1){ double soma = 0; int total = 0; double resultado = 0; try{ for(int i : v1){ total++; soma += i; resultado = (soma/total); catch(exception e){ System.out.println("Erro!"); return resultado; public int solicitarquantidade(){ int valor = 0; try{ valor = Integer.parseInt( JOptionPane.showInputDialog("Quantos valores?:")); Página 4
5 catch(exception e){ System.out.println("Erro!"); return valor; public void lervaloresinteiros(int[] valores){ try{ for(int i = 0; i< valores.length ; i++){ valores[i] = Integer.parseInt( JOptionPane.showInputDialog("valor:")); catch(exception e){ System.out.println("Erro!"); Repare que para os possíveis casos de exceção estamos apenas enviando a mensagem "Erro!" para o console, como forma de registrar o erro. Logo modificaremos este comportamento. Agora vamos configurar o framework Log4J para nossa aplicação. Configurando o Log4J O primeiro passo para a configuração do Log4J é adicionar o seu arquivo.jar em nosso projeto. Para isso clique com o botão direito do mouse sobre o projeto e escolha a opção Properties. Em seguida escolha a aba Libraries, conforme mostra a figura 3: Página 5
6 figura 3: tela para adição de bibliotecas ao projeto Nesta tela, clique no botão Add External jars, e informe o arquivo.jar do Log4J, que pode ser encontrado no site oficial do projeto ( na seção de downloads. Depois de adicionado o arquivo.jar, a tela deverá estar como apresentado na figura 4: Página 6
7 figura 4: tela para adição de bibliotecas ao projeto depois de adicionar o jar do Log4J Como foi dito anteriormente, a configuração do Log4J pode ser feita externamente, através de arquivos de configuração, e pode ser feita também programaticamente, através de código. Para este estudo, vamos focar na configuração do Log4J através de arquivos de configuração, por ser uma abordagem mais flexível do que a configuração programática. O arquivo de configuração do Log4J é um arquivo de texto simples, do tipo properties, cujo conteúdo é um conjunto de chaves-valores associados. O nome do arquivo é, por padrão, log4j.properties. Crie um arquivo com este nome na raiz do projeto. Para isso, no Eclipse, clique sobre o nome do projeto e escolha no menu a opção New>Other>General>File: Página 7
8 figura 5: criação do arquivo log4j.properties Logo após a criação do arquivo, a estrutura do projeto deve estar parecida com a apresentada na figura 6: Página 8
9 figura 6: projeto já com o arquivo log4j.properties A seguir está o conteúdo para o arquivo log4j.properties. Os comentários explicam a função de cada linha: # Configura dois appenders (stdout para o console, fileout para um arquivo) # para o logger padrão, e configura um nível (INFO). Como todos os # loggers que criamos herdam do logger padrãoo, quaisquer loggers que criarmos # terão esta configuração log4j.rootcategory=info, stdout, fileout # O primeiro appender escreve para o console log4j.appender.stdout=org.apache.log4j.consoleappender # O padrão para apresentação do conteúdo (layout) log4j.appender.stdout.layout=org.apache.log4j.patternlayout log4j.appender.stdout.layout.conversionpattern=%5p [%t] (%F:%L) - %m%n # O segundo appender escreve para um arquivo log4j.appender.fileout=org.apache.log4j.rollingfileappender log4j.appender.fileout.file=exemplo.log # Controla o tamanho máximo do arquivo de log log4j.appender.fileout.maxfilesize=500kb # Arquiva arquivos de log (somente um arquivo de backup) log4j.appender.fileout.maxbackupindex=1 # O padrãoo para apresentação do conteúdo (layout) log4j.appender.fileout.layout=org.apache.log4j.patternlayout log4j.appender.fileout.layout.conversionpattern=(%f:%l) %p %t %c - %m%n Página 9
10 Agora que temos o framework devidamente configurado, vamos alterar nossa classe para que sejam efetuados os logs. Adicione a seguinte declaração à classe ExemploLog4J: private org.apache.log4j.logger logger = Logger.getLogger(ExemploLog4J.class.getName()); O que esta declaração faz é criar um logger, com o mesmo nome da nossa classe. Agora, outras solicitações de logging são adicionadas ao código, inclusive substituindo o que foi colocado nos blocos catch. Eis o código final: package blogspot.luizgustavoss.log4j; import javax.swing.joptionpane; import org.apache.log4j.logger; public class ExemploLog4J { private org.apache.log4j.logger logger = Logger.getLogger(ExemploLog4J.class.getName()); public static void main(string[] a){ ExemploLog4J exemplo = new ExemploLog4J(); exemplo.run(); public void run(){ logger.info("iniciando o método run..."); int quantidade = solicitarquantidade(); int[] valores = new int[quantidade]; lervaloresinteiros(valores); double resultado = calcularmedia(valores); exibirvalorreal(resultado); logger.info("método o run finalizado!"); public void exibirvalorreal(double valor){ JOptionPane.showMessageDialog(null, "o valor é: " + valor); logger.info("operaçãoo exibirvalorreal realizada!"); public double calcularmedia(int[] v1){ double soma = 0; int total = 0; double resultado = 0; try{ for(int i : v1){ total++; Página 10
11 soma += i; resultado = (soma/total); logger.info("operação calcularmedia realizada!"); catch(exception e){ logger.error("erro na operação calcularmedia!"); return resultado; public int solicitarquantidade(){ int valor = 0; try{ valor = Integer.parseInt( JOptionPane.showInputDialog("Quantos valores?:")); logger.info("operação solicitarquantidade realizada!"); catch(exception e){ logger.error("erro na operação solicitarquantidade!"); return valor; public void lervaloresinteiros(int[] valores){ try{ for(int i = 0; i< valores.length ; i++){ valores[i] = Integer.parseInt( JOptionPane.showInputDialog("valor:")); logger.info("operação lervaloresinteiros realizada!"); catch(exception e){ logger.error("erro na operação lervaloresinteiros!"); Repare nas chamadas a info e error no logger criado. Estas são solicitações de logging nos níveis INFO e ERROR respectivamente, ou seja, para cada nível de logging há um método correspondente que pode ser chamado em um logger. Agora vamos executar o projeto e ver qual o resultado para as configurações feitas até o momento. Clique no botão Run e escolha a opção de executar como uma aplicação Java comum: Página 11
12 figura 7: execução do programa Repare que todas as solicitações de logging foram atendidas por nosso logger, conforme mostra a figura 8, pois ele está configurado, de acordo com o arquivo de configuração, para atender a solicitações a partir do nível INFO. Página 12
13 figura 8: execução das solicitações de logging Sem modificar nosso código, vamos alterar o nível de INFO para WARN, no arquivo log4j.properties: Página 13
14 figura 9: configuração do nível de logging para WARN Repare também, na imagem acima, que foi criado um arquivo chamado exemplo.log, conforme indicado no arquivo de configurações. Agora execute a aplicação e informe uma letra, ao invés de um número, para o primeiro painel que surge. Você verá que as solicitações de logging com nível INFO feitas através do método info não são atendidas, somente a solicitação de nível ERROR, conforme mostra a figura 10. Página 14
15 figura 10: é efetuado somente o logging de nível ERROR Esta facilidade de configuração nos permite adicionar solicitações de logging em tempo de projeto, que podem, em tempo de produção, ser desabilitadas. Para evitar um processamento desnecessário, podemos ainda realizar um teste antes da solicitação de um logging, checando o nível de logging habilitado para o logger: if (logger.isinfoenabled()) { logger.info("informação!"); Conclusão A utilização de logging em aplicações é de extrema importância, uma vez que durante o desenvolvimento ajuda no debbug, e em produção permite registrar eventos importantes ao longo da execução e rastrear problemas ocorridos. Este tutorial teve o objetivo de apresentar o framework Log4J, que é uma das principais alternativas dentre os frameworks de logging disponíveis. Foram apresentadas suas principais características, uma das formas de configuração, e sua utilização em uma aplicação prática. Página 15