Descrição Geral
No xeo foi criado um sistema de logging de forma a criar um nível de abstração sobre os loggers actualmente utilizados. Nesta versão o log4j foi acualizado para a versão 1.2.15 que é utilizado internffamente pelo XEO.
Esta implementação pretende normalizar o logging no XEO assim como em aplicações desenvolvidas sobre a plataforma.
Se não for especificado qualquer configuração no boconfig.xml, o sistema utiliza a parameterização geral do log4j, ou seja o log4j.properties.
Arquitectura do Logger
O sistema de logger é constituido por dois níveis. O logger e ou Appender.
Os loggers são os elementos que definem quais os packages que devem ser logados assim como o formato de escrita no log. Por cada logger existem appenders, que podem ser os seguintes:
- console - Este appender escreve as mensagens de log na standard output do java
- file - Este appender cria ficheiros de log com um limite pre-definido de tamanho
- email - Este appender envia os erros por email para os destinatários configurados. Este logger não funciona em todos os níveis, só superiores a WARNING.
Podem existir varios loggers com diferentes appenders, caso se pretenda que determinados packages sejam logados de formas distinctas.
Como usar
Obter um logger para uma class import netgest.bo.system.Logger;
(...)
private static final Logger logger = Logger.getLogger(MyClass.class);
Escrever no log logger.warn("Something went wrong. Message");
Performance
Quando se está a fazer logging deve-se ter alguma atenção quanto às questões de performance. Por exemplo, evitar que mensagens sejam criadas se o logger não está activo para determinado nível.
Quando se está a fazer loging deverá sempre colocar-se o código dentro de um if que interrogará o logger se este está activo para determinado nível.
Errado logger.finest("Entrando na class " + this.getClass().getName )
Correcto if( logger.isFinestEnabled() )
logger.finest("Entrando na class " + this.getClass().getName )
Na segunda forma, evitamos que a string seja concatenada com o nome da class quando o nível FINEST não está activo.
Configuração do Logging no XEO (bo-config.xml)
Níveis de logging e respectivos casos de uso:
# |
Nivel |
Texto no Log |
Descrição |
1 |
FINEST |
FINST |
Este nível deve ser utilizado para fazer de debug de comportamentos. Este nivel nunca deve estar activo em produção |
2 |
FINER |
FINER |
Este nível deve dar informação relevante de trace de erros, como seja chamada a API's externas, resultados de leitura de configurações de runtime |
3 |
FINE |
FINE |
Nível de log alargado, ou seja dá informação sobre execução de tarefas de background, resultado de chamadas a API externas como envio de emails, chamadas a webservices, etc. |
4 |
CONFIG |
CONF |
Informação sobre configuração do Sistema, atenção, não fazer log the passwords |
5 |
WARNING |
WARN |
Informação de avisos não criticos, ou seja erros pouco comuns, mas que o utilizador é notificado que ocorreram |
6 |
SEVERE |
SEVER |
Erros que impedem o bom funcionamento do sistema, tais como queries mal escritas, viewers/objectos com erros de sintaxe na definição, etc... |
Configuração no bo-config.xml
Configuração geral do logger:
Atributo |
Valores Possiveis |
Descrição |
pattern |
Formato de escrita do log do tipo log4j |
Formato de escrita no Log |
level |
FINEST / FINER / FINE / CONFIG / WARNING / SERVERE |
Nivel de log que deve ser feito por esta configuração |
for |
String separada por virgulas |
Packages que esta configuração para os quais esta configuração deve ser usada |
active |
true/false |
Se este logger está activo ou não |
Configuração dos appender console:
Configuração do appender file:
Atributo |
Valores Possiveis |
Descrição |
active |
true/false |
Activar ou desactivar este appender |
logFile |
Nome do ficheiro de log |
Caminho relativo ao xeoHome ou absoluto da localização e nome do ficheiro de log |
maxSize |
nn / nnKB / nnMB |
Tamanho máximo do ficheiro de log. |
backupFiles |
n |
Número de ficheiros que devem ser guardados em histórico após o limite do log ser ultrapassado |
Configuração do appender (Este appender só funciona para log's superiores a WARNING) email:
Atributo |
Valores Possiveis |
Descrição |
active |
true/false |
Activar ou desactivar este appender |
buffer |
n |
Número de messagens anteriores no log que devem ser enviadas no corpo do email |
smtpHost |
hostname |
Servidor SMTP a usar para envio dos erros de log |
from |
email address |
Endereço de email do remetente |
to |
email address |
Endereço do destinatário do email |
cc |
email address |
Endereço CC do email |
bcc |
email address |
Endereço BCC do email |
subject |
String |
Texto do assunto do email |
Exemplos de configuração
Este logger está configurado para fazer logging em todas as classes que estejam na hierarquia do package pt e netgest. O nivel de log é o FINEST por isso, o log será extenso. Como o appender email está desactivado, as mensagens de WARNING e SEVERE não serão enviadas por email.
<logConfig>
<logger active='true' for='pt,netgest' level='FINEST' pattern='%d %5p [%t] (%F:%L) - %m%n' >
<console active='true' />
<file active='true' logFile='.\log\fileName.log' backupFiles='5' maxSize='50MB' />
<email active='false' buffer='50' smtpHost='mail.itds.pt' from='' to='jp[a]itds.pt' cc='' bcc='' subject='ola' />
</logger>
</logConfig>
Log com exemplo de niveis diferentes e appenders por package. Esta configuração faz o log em mode FINEST para a consola, ficheiro e email de todas as classes que estejam no package pt. Para as classes que estejam no package netgest, escreve na consola apenas as mensagens de CONFIG ou superiores.
<logConfig>
<logger active='true' for='pt' level='FINEST' pattern='%d %5p [%t] (%F:%L) - %m%n' >
<console active='true' />
<file active='true' logFile='.\log\fileName.log' backupFiles='5' maxSize='50MB' />
<email active='true' buffer='50' smtpHost='mail.itds.pt' from='' to='destemail' cc='' bcc='' subject='ola' />
</logger>
<logger active='true' for='netgest' level='CONFIG' pattern='%d %5p [%t] (%F:%L) - %m%n' >
<console active='true' />
</logger>
</logConfig>
Exemplo de uma class a utilizar o logging
Exemplo de utilização numa class desenvolvida:
package pt.logger;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import netgest.bo.system.Logger;
import netgest.bo.system.boApplication;
public class LoggerDemo {
// Initialize the logger for the class
private static final Logger logger = Logger.getLogger( LoggerDemo.class );
public static void main( String[] args ) {
// Call some sample methods
loggedMethod();
doSomeWork();
}
public static void doSomeWork() {
FileWriter fw;
PrintWriter pw;
File propsFile;
// Log configuration info to the logger
logger.config("xeoHome is [%s]",
boApplication.getApplicationFromStaticContext("XEO")
.getApplicationConfig().getNgtHome()
);
propsFile = new File("c:\\jvmprops.txt");
if( propsFile.exists() ) {
// Warning - the previous file was overwritten
logger.warn("Overwritting file %s ", propsFile.getName() );
}
else {
if( logger.isFineEnabled() )
// Fine - Creating a file
logger.fine("Creating file %s ", propsFile.getName() );
}
try {
fw = new FileWriter( propsFile );
pw = new PrintWriter( fw );
if( logger.isFinestEnabled() ) {
// Finest - Filling a file
logger.finest("Dumping properties to [%s]", propsFile.getAbsolutePath() );
}
for( Object propName : System.getProperties().keySet() ) {
pw.format( "%s : %s \n", propName, System.getProperty( propName.toString() ) );
}
pw.close();
if( logger.isFinestEnabled() ) {
// Finest - Closing the file
logger.finest("Closing file [%s]", propsFile.getAbsolutePath() );
}
fw.close();
} catch (IOException e) {
// Severe - Something goes wrong writing the file
logger.severe( "Error writing to file [%s]" , e, propsFile.getAbsolutePath() );
}
}
public static void loggedMethod() {
// Finest - tracing method call's
logger.finest( "Entering in method: %s", "loggedMethod" );
// Do Work
// (...)
logger.finest( "Exiting in method: %s", "loggedMethod" );
}
}