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