25 de jan. de 2011

Apache Log4j

Logging em aplicações é a forma ou técnica de se escrever o que acontece por dentro da aplicação fora dos olhos dos programadores/desenvolvedores. Em ambientes de produção por exemplo não é possível uma pessoa ficar plugada no console do servidor para ver o que acontece na aplicação, e é ai que os frameworks de logging entram em ação. Um deles é o Apache Log4j.

O Log4j é um framework do grupo Apache destinado a fazer log's da aplicação. Sendo log's de erros, informações, debuggers dentre outros. Que permite o direcionamento dos log's de forma transparente para diferentes destinos, como escritas no console, arquivos de textos, e-mails, banco de dados, filas JMS dentre outros. O framework também permite a criação de destinos customizados.

Este tutorial mostrará as configurações básicas do framework para direcionar os log's para o console, arquivo de texto e e-mail.

A configuração do log4j é bem simples, por padrão pode ser configurado atravéz de arquivos .properties (log4j.properties), arquivos .xml (log4j.xml) e também programaticamente. Neste tutorial utilizaremos a configuração através do arquivo log4j.properties. É necessário ter o .jar do framework nas lib's do seu projeto log4j-x.x.xx.jar

Será apresentado o arquivo de configuração e abaixo um explicação das partes que o compõe juntamente com um exemplo de sua utilização.

log4j.properties - Este arquivo deve ficar localizado no classpath da aplicação, se estiver utilizando o eclipse como IDE, o arquivo deverá ficar dentro da pasta src de seu projeto.

Configuração para o log4j.properties quando for utilizar o destino console
 log4j.rootLogger=INFO, CONSOLE  
 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender  
 log4j.appender.CONSOLE.encoding=UTF-8  
 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout  
 log4j.appender.CONSOLE.layout.ConversionPattern=[%d{dd/MM/yyyy HH:mm:ss S}] [%t] %p - %c - %m%n  

Configuração para o log4j.properties quando for utilizar o destino de arquivo .txt
 #FILE APPENDER  
 log4j.rootLogger=INFO, FILE 
 log4j.appender.FILE=org.apache.log4j.FileAppender  
 log4j.appender.FILE.ImmediateFlush=true  
 log4j.appender.FILE.Encoding=UTF-8  
 log4j.appender.FILE.threshold=ERROR  
 log4j.appender.FILE.File=C:\\blog-logger.txt  
 log4j.appender.FILE.layout=org.apache.log4j.PatternLayout  
 log4j.appender.FILE.layout.ConversionPattern=[%d{dd/MM/yyyy HH:mm:ss S}] [%t] %p - %c - %m%n  

Configuração para o log4j.properties quando for utilizar o destino e-mail
 #E-MAIL APPENDER
 log4j.rootLogger=INFO, EMAIL
 log4j.appender.EMAIL=org.apache.log4j.net.SMTPAppender  
 log4j.appender.EMAIL.threshold=ERROR  
 log4j.appender.EMAIL.SMTPHost=seu smtp host  
 log4j.appender.EMAIL.SMTPPassword=sua senha  
 log4j.appender.EMAIL.SMTPUsername=seu nome de usuario  
 log4j.appender.EMAIL.from=email que sera utilizado para enviar 
 log4j.appender.EMAIL.subject=ERRO NO SISTEMA   
 log4j.appender.EMAIL.to=email que recebera os logs
 log4j.appender.EMAIL.layout=org.apache.log4j.PatternLayout   
 log4j.appender.EMAIL.layout.ConversionPattern=[%d{dd/MM/yyyy HH:mm:ss S}] [%t] %p - %c - %m%n  
Obs.: as 3 configurações podem ser utilizadas ao mesmo tempo, gerando o log no console, escrevendo no arquivo .txt e enviando e-mail's. Para a utilização do destino de e-mail é necessário ter no classpath os jar's activation.jar e mail.jar

Para habilitar mais de um destino ao mesmo tempo, defina a propriedade log4j.rootLogger como abaixo, onde está configurado para escrever no CONSOLE e enviar EMAIL`s
 log4j.rootLogger=INFO, CONSOLE, EMAIL  

TesteLogging.java
 /**  
  * @author Calazans  
  * */  
 package com.calazans.logging;  
 import org.apache.log4j.Logger;  
 public class TesteLogging {  
      private static final Logger LOGGER = Logger.getLogger(TesteLogging.class);  
      public static void main(String[] args){  
           LOGGER.debug("DEBUG LOG");  
           LOGGER.info("INFO LOG");  
           LOGGER.warn("WARN LOG");  
           LOGGER.error("ERROR LOG");  
           LOGGER.fatal("FATAL LOG");  
      }  
 }  

Saída do log
 [25/01/2011 18:58:04 903] [main] INFO - com.calazans.logging.TesteLogging - INFO LOG  
 [25/01/2011 18:58:04 904] [main] WARN - com.calazans.logging.TesteLogging - WARN LOG  
 [25/01/2011 18:58:04 904] [main] ERROR - com.calazans.logging.TesteLogging - ERROR LOG  
 [25/01/2011 18:58:04 904] [main] FATAL - com.calazans.logging.TesteLogging - FATAL LOG  

Os níveis de log do framework são divididos em uma série de níveis sendo ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF. Esses níveis trabalham na forma de hierarquia e indicam as partes da aplicação configurada que será "logada".

- ALL: Indica que tudo vai ser mostrado no log
- DEBUG: Indica que tudo abaixo de debug irá aparecer no log
- INFO: Indica que tudo abaixo de info irá aparecer no log
- WARN: Indica que tudo abaixo de warn irá aparecer no log
- ERROR: Indica que tudo abaixo de error irá aparecer no log
- FATAL: Indica que somente os logs de nível fatal irá aparecer no log
- OFF: Desabilita todos os níveis e tipos de logs.

Esta configuração é feita no log4j.properties como

log4j.rootLogger=INFO, CONSOLE

É uma forma geral de informar o nível padrão para todos os destinos, onde todos os log's abaixo de INFO (inclusive) serão escritos no console, esta configuração pode ser sobrecrita em destinos específicos como em

log4j.appender.FILE.threshold=ERROR

no qual diz que só será escrito no arquivo .txt os níveis de ERRO (inclusive) para baixo.

log4j.appender.CONSOLE.layout
O layout é a forma de como será disposta a informação, determinados layouts mostram mais informações que outros e com formatações diferentes como em Html no layout HTMLLayout que irá gerar uma página html com as informações do log.
Os Layouts também podem ser customizados de maneira que lhe atenda melhor, bastando para isso escrever uma classe que implemente os métodos da classe abstrata org.apache.log4j.Layout.

log4j.appender.FILE.layout.ConversionPattern
O ConversionPattern é a forma de como será formatada a informação gerada nos log's.

Exemplo EscritaTxt.java
 /**  
  * @author Calazans  
  * */  
 package com.calazans.io;  
 import java.io.BufferedWriter;  
 import java.io.File;  
 import java.io.FileOutputStream;  
 import java.io.IOException;  
 import java.io.OutputStream;  
 import java.io.OutputStreamWriter;  
 import org.apache.log4j.Logger;  
 public class EscritaTxt {  
      private static final Logger LOGGER = Logger.getLogger(LeituraTxt.class);  
      public static void main(String[] args) {  
           try {                 
                OutputStream os = new FileOutputStream(new File("arquivo.txt"));  
                OutputStreamWriter osw = new OutputStreamWriter(os);  
                BufferedWriter bw = new BufferedWriter(osw);  
                LOGGER.debug("Inicio da escrita no arquivo .txt");  
                bw.write("Teste");  
                LOGGER.debug("Fim da escrita no arquivo .txt");  
                bw.close();  
                LOGGER.debug("Fechando arquivo .txt");  
                LOGGER.info("Arquivo escrito com sucesso...");                 
           } catch (IOException ioe) {  
                LOGGER.error("Erro ao escrever arquivo .txt", ioe);  
           }  
      }  
 }  
Saída do log
 [25/01/2011 19:04:36 258] [main] DEBUG - com.calazans.io.LeituraTxt - Inicio da escrita no arquivo .txt  
 [25/01/2011 19:04:36 258] [main] DEBUG - com.calazans.io.LeituraTxt - Fim da escrita no arquivo .txt  
 [25/01/2011 19:04:36 259] [main] DEBUG - com.calazans.io.LeituraTxt - Fechando arquivo .txt  
 [25/01/2011 19:04:36 259] [main] INFO - com.calazans.io.LeituraTxt - Arquivo escrito com sucesso...  

Você ainda pode definir quais partes de sua aplicação ou frameworks serão logados, através dos filtros nos pacotes:
 log4j.logger.org.springframework=ERROR  
 log4j.logger.org.hibernate=ALL  
No Spring framework só será mostrado os níveis de ERROR para baixo, já no Hibernate framework será mostrado todos os níveis de log's.

Mais informações sobre configurações específicas, layouts disponíveis, formas de formatações podem ser obtidas no próprio site do framework.

Um comentário:

Anônimo disse...

Muito bom o blog. Parabéns me foi muito útil.

Postar um comentário