General Description
In XEO a logging system was created, to create a level of abstraction from other loggers currently used. In this version the log4j was updated to version 1.2.15 wich is used internally by the XEO.
This implementation pretends to normalize the XEO logging as also from the applications developed in this platform.
If no configuration is specified in the boconfig.xml, the system will use log4j general parameterization, namely log4j.properties.
Logger Architecture
The logger system consits of two levels. The Logger and the Appender
The loggers are the elements that define wich packages schould be logged, as also the writting format in the log. For each logger there are appenders, wich can be the following:
*console - This appender writes the log messages of the standart java output
*file - This appender creates log files with a defined file size
*email - This appender sends error by email to the configured recipients. This logger does not work in every leves, just superiors to WARNING.
There can be several loggers with different appenders, if you pretend that different packages are logged in different ways.
How to use
Obtain a logger for a class
import netgest.bo.system.Logger;
(...)
private static final Logger logger = Logger.getLogger(MyClass.class);
Write on the log
logger.warn("Something went wrong. Message");
Performance
When using logging, you should pay some attention to perfiormance questions. For example, avoid messages to be created if the logger is not active for the current level.
When doing logging, You should put the code in a if wich will check if the logger is active for the current level.
Wrong
logger.finest("Entering class " + this.getClass().getName );
Right
if( logger.isFinestEnabled() )
logger.finest("Entering class %s", this.getClass().getName );
By the second way, we avoid the string to be concatenated with the cass name when the FINEST level is not active.
XEO Logging configuration ( boconfig.xml )
Logging levels and respective using cases:
# |
Level |
Log Text |
Description |
1 |
FINEST |
FINST |
This level should be used to behavior debug. This level should never be active in production |
2 |
FINER |
FINER |
This level should give relevant information to trace errors, how external API's are called, runtime configuration reading results. |
3 |
FINE |
FINE |
Extended log level, gives information about backgroud tasks execution, external API calls result like sending emails, web srvice calls, etc. |
4 |
CONFIG |
CONF |
Information about System configurations, Atention, do not log passwords |
5 |
WARNING |
WARN |
Information of critical warning, unusual errors, but of wich ones the user is notified if they occurred. |
6 |
SEVERE |
SEVER |
Errors that prevent a good system functioning, so as poorly written queries, viewers/objects with definition syntax error, etc. |
Configuration in boconfig.xml
General configuration
logger:
Attribute |
Possible Values |
Description |
active |
true/false |
If the logger is active or not |
for |
String separated by commas |
Packages for wich this configuration should be used |
level |
FINEST / FINER / FINE / CONFIG / WARNING / SERVERE |
Log level that will be done by this configuration |
pattern |
Writting format for the log of type log4j |
Log writting format |
Appender Configuration
console:
Appender Configuration
file:
Attribute |
Possible Values |
Description |
active |
true/false |
Activate or disable this appender |
logFile |
Name of the log file |
xeoHome relative path or absolute localization and log file name |
maxSize |
nn / nnKB / nnMB |
Maximum log file size. |
backupFiles |
n |
Number of files that should be kept in the history after log limit exeded |
Appender Configuration (This Appender only works for logs superior to WARNING)
email:
Attribute |
Possible Values |
Description |
active |
true/false |
Activate or disable this appender |
buffer |
n |
Number of earlier messages in the log that should be send in the email body |
smtpHost |
hostname |
SMTP Server to use for sending error logs |
from |
email address |
Sender email address |
to |
email address |
Receiver email address |
cc |
email address |
Email CC address |
bcc |
email address |
Email BCC address |
subject |
String |
Email subject text |
Configuration Examples
This logger is configured to do logging in all classes that are in the pt and netgest package hierarchy. The log level is FINEST so, the log will be long. Once the appender email is deactivated, the WARNING and SEVERE messages are not send by 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 with examples of different leves and appenders by package. This configuration makes the log in FINEST mode to the console, file and email of all classes that are in the package pt. For the classes in the netgest package, writes on the console only config messages or higher.
<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>
Example of a class using logging
Example of use in a deveoped class:
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" );
}
}