Podemos afirmar que instruções de log, isto é, mensagens indicando o comportamento de um programa, podem poluir o código e diminuir a legibilidade. Além disso, o log aumenta o tamanho do código e reduz sua velocidade.
Log4j é um projeto de código aberto (open Source) baseado no trabalho de diversos autores. Ele permite ao desenvolvedor controlar, de maneira flexível, cada saída de log. Com o ele, podemos ativar o log em tempo de execução sem modificar os binários da aplicação, esse comportamento pode ser controlado apenas editando um arquivo de configuração.
Uma das características do Log4j é a herança em loggers. Usando uma hierarquia de loggers é possível controlar quais instruções de log serão usadas. Isto ajuda a reduzir o volume de saídas e minimizar seu custo.
A saída poderá ser um arquivo, um OutputStream, um java.io.Writer, um servidor Log4j remoto, um daemon Unix, ou mesmo um evento de log do Windows.
A versão atual do Log4J é a 1.2.8, seu download pode ser feito em http://logging.apache.org/log4j/docs/download.html onde poderá ser obtido o código fonte e as bibliotecas para uso.
Para começar a usar o Log4J, basta descompactar o arquivo que foi baixado e colocar o log4j-xxx.jar (onde xxx é a versão).
Para se usar o Log4j deve-se ter um considerável planejamento e esforço, pois após colocarmos instruções de log dentro do código de um sistema, é importante que não seja preciso modificá-las manualmente.
Esse planejamento é feito na configuração, esta é, talvez, a parte mais importante ao utilizar o Log4j. A configuração pode ser feita por programação,entretanto, fica claro que é obtida uma flexibilidade muito maior ao usarmos outras duas formas possíveis de configuração: um arquivo xml ou um arquivo de propriedades (no formato chave=valor).
Basta chamar o método estático configure() da classe org.apache.log4j.BasicConfigurator.
private SessionFactory sessionFactory;
public static void main(String[] args) {
BasicConfigurator.configure();
logger.info("Iniciando a aplicacao");
}
Configurar o Log4j é de fato setar os loggers para mostrar as mensagens de log nos appenders escolhidos usando layouts determinados pelo desenvolvedor. Os loggers podem ser criados e configurados em qualquer ordem, em particular um logger irá encontrar e agrupar seus descendentes mesmo que ele seja instanciado depois deles.
Isto tudo pode ser feito em um arquivo que deve ser chamado de log4j.properties, desta forma a configuração é feita apenas uma vez e é carregada na inicialização da aplicação. Este arquivo deve ser colocado no classpath da aplicação.
Veja um exemplo:
#### Usando 2 appenders, 1 para logar no console, outro para um arquivo log4j.rootCategory=DEBUG, stdout, fileOut # Imprime somente mensagens com 'priority' WARN ou mais alto para o logger #lembrando a ordem: DEBUG - INFO - WARN - ERROR - FATAL log4j.category.SEU.LOGGER.NAME=WARN # Explicita a herança do nivel de prioridade #log4j.category.your.category.name=INHERITED #### O primeiro appender escreve no console log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout # Pattern que mostra o nome do arquivo e numero da linha. log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n #### O segundo appender escreve em um arquivo log4j.appender.fileOut =org.apache.log4j.RollingFileAppender log4j.appender.fileOut.File=example.log # Controla o tamanho maximo do arquivo log4j.appender.fileOut.MaxFileSize=100KB # Faz backup dos arquivos de log (apenas 1) log4j.appender.fileOut.MaxBackupIndex=1 log4j.appender.fileOut.layout=org.apache.log4j.PatternLayout log4j.appender.fileOut.layout.ConversionPattern=%p %t %c - %m%n
O Log4j possui três componentes principais: loggers, appenders e layouts. Eles trabalham juntos para que os desenvolvedores façam o log de suas mensagens de acordo com o tipo e o nível delas, e controle em tempo de execução como estas mensagens são formatadas e onde são reportadas.
A primeira e principal vantagem de qualquer API de log sobre o System.out.println está em sua habilidade de desabilitar certos níveis de log (quando estes não são necessários) enquanto os demais níveis continuam funcionando normalmente. O Log4j oferece cinco níveis de log em sua hierarquia: DEBUG, INFO, WARN, ERROR e FATAL. O nível da hierarquia de log será informado quando da chamada ao método de log.
O nome de um logger deve seguir o mesmo estilo já conhecido dos programadores Java, separando por pontos (.) desta forma:
"com.foo" é um parent de "com.foo.Bar" e este chamado de child. Similarmente, assim como "java" é um ancestor de "java.util.Vector", dizemos que "com" é um ancestor de "com.foo.Bar".
A classe org.apache.log4j.Logger é a classe central do Log4j, a maioria das operações de log, exceto configuração, são feitas através desta classe.
Um appender é uma saída onde são mostradas as mensagens, o console, algum arquivo, um servidor remoto de sockets, etc. Um logger pode ter mais de um appender. Por exemplo, podemos mandar as mensagens de log para o console e para um arquivo ao mesmo tempo. Além disso podemos mostrar níveis diferentes de mensagens nos appenders diferentes, ou seja, mandar para o console todas as mensagens enquanto que para o arquivo podemos salvar apenas as mensagens de nível WARN, por exemplo.
Appenders:
ConsoleAppender - envia as mensagens de log para o System.out (default) ou System.err (mudado com a propriedade Target)
Para filtrar os tipos de logs, basta setar a propriedade Threshold=<nivel minimo>, desta forma serão
mostradas todas as mensagens que tiverem prioridade igual ou maior do que o nível setado, seguindo a ordem:
DEBUG < INFO < WARN < ERROR < FATAL.
log4j.appender.meuLogger.Threshold=WARN
Isto significa dizer que somente as mensagens com nível WARN, ERROR e FATAL serão mostradas.
Com Log4j é possível enviar os logs facilmente para um destinatário de e-mail, usando o appender
org.apache.log4j.net.SMTPAppender
Como o SMTPAppender usa a JavaMail API da Sun (http://java.sun.com/products/javamail), é necessário utilizar o
JavaBeans Activation Framework (http://java.sun.com/beans/glasgow/jaf.html) através do arquivo activation.jar,
e o pacote javax.mail que pode ser encontrado no arquivo mail.jar da Sun. Estes dois arquivos devem ser colocados
no CLASSPATH da aplicação.
Daí então, só é preciso fazer a devida configuração assim como qualquer outro appender:
log4j.rootCategory=DEBUG, emailOut
!-------------------- Enviando por e-mail -------------------!
log4j.appender.emailOut=org.apache.log4j.net.SMTPAppender
log4j.appender.emailOut.Threshold=DEBUG
log4j.appender.emailOut.SMTPHost=<seu servidor smtp>
log4j.appender.emailOut.From=<seu e-mail>
log4j.appender.emailOut.BufferSize=2
log4j.appender.emailOut.Subject=<assunto>
log4j.appender.emailOut.To=<destinatario>
log4j.appender.emailOut.layout=org.apache.log4j.PatternLayout
log4j.appender.emailOut.layout.ConversionPattern=%d{ISO8601} %5p [%t](%F:%L)- %m%n
O e-mail enviado conterá exatamente as mensagens de log como aparecem no console por exemplo, seguindo o pattern escolhido pelo desenvolvedor.
Layout é o formato como a mensagem vai ser mostrada. Este formato pode incluir a data da mensagem, qual o método que contém o log, qual linha, classe, arquivo, etc.
Log4j fornece as seguintes classes de Layout:
org.apache.log4j.Layout (abstrata) -org.apache.log4j.SimpleLayout -org.apache.log4j.PatternLayout -org.apache.log4j.HTMLLayout -org.apache.log4j.XMLLayout -org.apache.log4j.DateLayout(abstrata): org.apache.log4j.TTCCLayout
Para usar um destes layouts é muito simples, veja este exemplo que irá criar um saída em uma tabela HTML:
log4j.rootCategory=DEBUG, htmlOut !-------------------------------HTMLLayout OPTIONS----------------------------! log4j.appender.htmlOut=org.apache.log4j.RollingFileAppender log4j.appender.htmlOut.File=logging/HTMLLayout.html log4j.appender.htmlOut.layout=org.apache.log4j.HTMLLayout log4j.appender.htmlOut.layout.LocationInfo=true log4j.appender.htmlOut.layout.Title=Log gerado pelo Log4j
Isto irá criar um arquivo com o nome HTMLLayout.html, e neste arquivo terá uma tabela com o tempo decorrido em milisegundos desde quando o programa foi iniciado, a thread que disparou o log, o nível de prioridade, a classe, o nome do arquivo *.java desta classe e o número da linha (se LocationInfo = true) e a mensagem de log.
Ao enviar o log para o console ou para um arquivo por exemplo, podemos mostrar tais informações na ordem em que escolhermos e com o formato que desejarmos, um ótimo exemplo é o formato da data, podemos mostrar "dd/mm/aaaa" ou "aaaa-mm-dd" com hora ou não. Isto depende do pattern usado. Veja este exemplo:
Pattern: "%r [%t] %-5p %c{2} - %m%n"
176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order
r - numero de milissegundos transcorridos desde o inicio do programa
t - nome da thread que gerou o evento de log
p - prioridade (o -5 indica que deve alinhar a direita se o número de caracteres for menor que cinco)
c - nome da classe (2 indica que se o nome completo da classe for "a.b.c" por exemplo, deverá ser mostrado apenas "b.c")
m - é a mensagem (não pode faltar !)
n - é o separador de linhas padrão do sistema operacional - "\n" ou "\r\n"
Para usar os patterns devemos dizer que o layout será da classe org.apache.log4j.PatternLayout. Ela serve justamente para formatar um evento de log e retornar uma string que será mostrada no appender escolhido, para fazer a formatação usamos uma propriedade de PatternLayout chamada ConversionPattern.
Veja como esta configuração é simples:
log4j.rootCategory=DEBUG, stdOut
# stdOut usa PatternLayout
log4j.appender.stdOut.layout=org.apache.log4j.PatternLayout
log4j.appender.stdOut.layout.ConversionPattern=%-2d{dd/MM/yy HH:mm} [%t] %5p %c:%L - %m%n
Isto irá mostrar
22/01/04 13:07 [main] INFO logging.UseLogger :12 - Iniciando a aplicacao 22/01/04 13:07 [main] INFO logging.UseLogger :14 - Fim da aplicacao
Para ver a lista dos patterns, consulte a classe org.apache.log4j.PatternLayout nos javadocs do Log4j, a versão on-line é http://logging.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html
Veja abaixo um arquivo com muitas opções de configuração do Log4j.
#log4j.debug=true
#log4j.disable=fatal
#log4j.additivity.TestLogging=false
log4j.rootCategory=, dest1
log4j.category.TestLogging=DEBUG, dest1
log4j.appender.dest1=org.apache.log4j.ConsoleAppender
#log4j.appender.dest1.layout=org.apache.log4j.SimpleLayout
log4j.appender.dest1.layout=org.apache.log4j.PatternLayout
#log4j.appender.dest1.layout.ConversionPattern=%-5p %l %x: %m%n
!----------------------####### END OF PROPERTIES #######----------------------!
###############################################################################
# Below I document in more detail how to write a log4j configuration file. #
# SELECTIVELY copy lines beginning with #, paste and uncomment them above. #
###############################################################################
!-----------------------------------------------------------------------------!
! PLACE THIS FILE ANYWHERE IN CLASSPATH !
! Appenders are additive by default. !
! Priorities are inherited until overridden in a category. !
! In ${property_key}, the value of the key can be defined as a system !
! property or in this file itself. System properties are searched first and !
! then this file. !
!-----------------------------------------------------------------------------!
!-----------------------------------------------------------------------------!
! Configure log4j's operation at the meta level !
!-----------------------------------------------------------------------------!
! Observe log4j parsing this file
#log4j.debug=true
! Set this to false for log4j to actually obey the log4j.disable property(next)
#log4j.disableOverride=false
! Disable all logging in all categories for messages with priority equal to
! or lower than the one given here
#log4j.disable=INFO
!-----------------------------------------------------------------------------!
! Configure categories (loggers) !
!-----------------------------------------------------------------------------!
! ROOT CATEGORY (Usually sufficient to set this one only)
! Here, logs messages with priority DEBUG (default) or higher
#log4j.rootCategory=, dest1
! Or,
#log4j.rootCategory=debug, dest1, dest2
! YOUR CATEGORIES (to customize logging per class/pkg/project/etc)
! Here, overrides ancestor's priority and makes it WARN or higher for this cat.
#log4j.category.TestLogging=WARN, dest3
! Or,
#log4j.category.TestLogging=DEBUG, dest3
!--------DON'T DO THIS!!! APPENDERS ARE ADDITIVE BY DEFAULT!!!---------------!
! It will write the same log message TWICE to dest1. Once for root, then for !
! this category. !
!#log4j.category.TestLogging=DEBUG, dest1, dest3 !
! If you DO NOT want additivity for this category, say so !
!#log4j.additivity.TestLogging=false !
!-----------------------------------------------------------------------------!
!-----------------------------------------------------------------------------!
! Configure appenders (log destinations/targets) and their options !
!-----------------------------------------------------------------------------!
! WRITE TO CONSOLE (stdout or stderr)
#log4j.appender.dest1=org.apache.log4j.ConsoleAppender
#log4j.appender.dest1.ImmediateFlush=true
! WRITE LOG TO A FILE, ROLL THE FILE AFTER SOME SIZE
#log4j.appender.dest2=org.apache.log4j.RollingFileAppender
! This appender will only log messages with priority equal to or higher than
! the one specified here
#log4j.appender.dest2.Threshold=ERROR
! Specify the file name (${property_key} gets substituted with its value)
#log4j.appender.dest2.File=${java.home}/log4j.log
! Don't append, overwrite
#log4j.appender.dest2.Append=false
! Control the maximum log file size
#log4j.appender.dest2.MaxFileSize=100KB
! Keep backup file(s) (backups will be in filename.1, .2 etc.)
#log4j.appender.dest2.MaxBackupIndex=2
! WRITE LOG TO A FILE, ROLL THE FILE EVERY WEEK
#log4j.appender.dest3=org.apache.log4j.DailyRollingFileAppender
! Specify the file name
#log4j.appender.dest3.File=log4TestLogging2.html
! Control the maximum log file size
#log4j.appender.dest3.MaxFileSize=300KB
! Rollover log file at the start of each week
#log4j.appender.dest3.DatePattern='.'yyyy-ww
!-----------------------------------------------------------------------------!
! Configure appender layouts (log formats) and their options !
!-----------------------------------------------------------------------------!
! USE SIMPLE LOG FORMAT (e.g. INFO - your log message)
#log4j.appender.dest1.layout=org.apache.log4j.SimpleLayout
! USE A C PRINTF STYLE PATTERN TO FORMAT LOG MESSAGE
#log4j.appender.dest1.layout=org.apache.log4j.PatternLayout
! For a pattern layout, specify the pattern (Default is %m%n which is fastest)
#log4j.appender.dest1.layout.ConversionPattern=%-5p: %m%n
! Or,
#log4j.appender.dest1.layout.ConversionPattern=%-5p %6.10r[%t]%x(%F:%L) - %m%n
#log4j.appender.dest2.layout=org.apache.log4j.PatternLayout
#log4j.appender.dest2.layout.ConversionPattern=[%d{ISO8601}]%5p%6.6r[%t]%x(%F:%L) - %m%n
! Or, (the pattern below will slow down your app)
#log4j.appender.dest2.layout.ConversionPattern=[%d{yyyy-mm-dd hh:mm},%6.6r]%-5p[%t]%x(%F:%L) - %m%n
! FORMAT LOG MESSAGES IN THE FORM OF AN HTML TABLE
#log4j.appender.dest3.layout=org.apache.log4j.HTMLLayout
! Include Java file name and line number (Default is false)
#log4j.appender.dest3.layout.LocationInfo=true
! Set <title> tag (Default: Log4J Log Messages)
#log4j.appender.dest3.layout.Title=My App Log
!-----------------------------------------------------------------------------!
! PATTERN FORMATS GLOSSARY !
!-----------------------------------------------------------------------------!
! %n - newline !
! %m - your log message !
! %p - message priority (FATAL, ERROR, WARN, INFO, DEBUG or custom) !
! %r - millisecs since program started running !
! %% - percent sign in output !
! !
!-----------------------SOME MORE CLUTTER IN YOUR LOG-------------------------!
! %c - name of your category (logger), %c{2} will outputs last two components !
! %t - name of current thread !
! %x - Nested Diagnostic Context (NDC) (you supply it!) !
! !
!-------------------------SLOW PERFORMANCE FORMATS----------------------------!
! %d - date and time, also %d{ISO8601}, %d{DATE}, %d{ABSOLUTE}, !
! %d{HH:mm:ss,SSS}, %d{dd MMM yyyy HH:mm:ss,SSS} and so on !
! %l - Shortcut for %F%L%C%M !
! %F - Java source file name !
! %L - Java source line number !
! %C - Java class name, %C{1} will output the last one component !
! %M - Java method name !
! !
!------------------------------FORMAT MODIFIERS-------------------------------!
! %-any_letter_above - Left-justify in min. width (default is right-justify) !
! %20any_letter_above - 20 char. min. width (pad with spaces if reqd.) !
! %.30any_letter_above - 30 char. max. width (truncate beginning if reqd.) !
! %-10.10r - Example. Left-justify time elapsed within 10-wide field. !
! Truncate from beginning if wider than 10 characters. !
!-----------------------------------------------------------------------------!
!-----------------------------------------------------------------------------!
! OPTIONS GLOSSARY !
!-----------------------------------------------------------------------------!
!-------------------------OVERALL OPTIONS FOR log4j---------------------------!
! Specify as command line option: -Dlog4j.defaultInitOverride=false
! Specify as command line option: -Dlog4j.configuration=app_config.properties
!#log4j.debug=true
!#log4j.disable=INFO
!#log4j.disableOverride=false
!#log4j.additivity.your.category.name=false
!
!----------------------------NullAppender OPTIONS-----------------------------!
!#log4j.appender.dest1.Threshold=INFO
!
!---------------------------ConsoleAppender OPTIONS---------------------------!
!#log4j.appender.dest1.Threshold=INFO
!#log4j.appender.dest1.ImmediateFlush=true
!#log4j.appender.dest1.Target=System.err
!
!-----------------------------FileAppender OPTIONS----------------------------!
!#log4j.appender.dest2.Threshold=INFO
!#log4j.appender.dest2.ImmediateFlush=true
!#log4j.appender.dest2.File=mylog.txt
!#log4j.appender.dest2.Append=false
!
!-------------------------RollingFileAppender OPTIONS-------------------------!
!#log4j.appender.dest2.Threshold=INFO
!#log4j.appender.dest2.ImmediateFlush=true
!#log4j.appender.dest2.File=mylog.txt
!#log4j.appender.dest2.Append=false
!#log4j.appender.dest2.MaxFileSize=100KB
!#log4j.appender.dest2.MaxBackupIndex=2
!
!-----------------------DailyRollingFileAppender OPTIONS----------------------!
!#log4j.appender.dest2.Threshold=INFO
!#log4j.appender.dest2.ImmediateFlush=true
!#log4j.appender.dest2.File=mylog.txt
!#log4j.appender.dest2.Append=false
!#log4j.appender.dest2.DatePattern='.'yyyy-ww
!
!-----------------------------SimpleLayout OPTIONS----------------------------!
!**None**
!
!-------------TTCCLayout OPTIONS (PatternLayout is more flexible)-------------!
!#log4j.appender.dest1.layout.DateFormat=ISO8601
!#log4j.appender.dest1.layout.TimeZoneID=GMT-8:00
!#log4j.appender.dest1.layout.CategoryPrefixing=false
!#log4j.appender.dest1.layout.ThreadPrinting=false
!#log4j.appender.dest1.layout.ContextPrinting=false
!
!-----------------------------PatternLayout OPTIONS---------------------------!
!#log4j.appender.dest1.layout.ConversionPattern=%m%n
!
!-------------------------------HTMLLayout OPTIONS----------------------------!
!#log4j.appender.dest3.layout.LocationInfo=true
!#log4j.appender.dest3.layout.Title=My app title
!
!--------------------------------XMLLayout OPTIONS----------------------------!
!#log4j.appender.dest3.layout.LocationInfo=true
!-----------------------------------------------------------------------------!

Por favor, dê a sua opinião a respeito do conteúdo apresentado. Correções, sugestões ou qualquer outra informação relevante é de suma importância para nós e será muito bem vinda.
Contato: owner@hotwork.dev.java.net