I've got quite a number of request in email requesting me for a simple log4cxx sample program that illustrate the usage of log4cxx ever since I've wrote
this article. I've sent my sample program in emails to those request, but I guess it will be more productive if I would just put up a sample usage here.
This will be a to-the-point log4cxx tutorial, you will probably need the
binary here before you proceed:
The log4cxx XML Configuration file ( MyLogConfig.xml ) will shows you the usage of following appender:
- org.apache.log4j.ConsoleAppender
- org.apache.log4j.FileAppender
- org.apache.log4j.rolling.RollingFileAppender
- org.apache.log4j.RollingFileAppender
- org.apache.log4j.net.SMTPAppender
- org.apache.log4j.jdbc.JDBCAppender
- org.apache.log4j.net.XMLSocketAppender
The MyLogConfig.xml is properly commented, so it should be self explanatory. ( and no, there is no typo, the configuration file actually refer it as log4j )
Writing The Code
Create a C++ Console project in VC++, and put in the following code:
#include <log4cxx\logger.h>
#include <log4cxx\xml\domconfigurator.h>
#include <windows.h>
using namespace log4cxx;
using namespace log4cxx::xml;
using namespace log4cxx::helpers;
// Define static logger variable
LoggerPtr loggerToFile(Logger::getLogger( _T("MyLogger") ) );
LoggerPtr loggerMyFunctionA(Logger::getLogger( _T("MyFunctionA") ));
void MyFunctionA()
{
LOG4CXX_INFO(loggerMyFunctionA, _T("Executing MyFunctionA."));
}
int _tmain(int argc, _TCHAR* argv[])
{
// Load configuration file
DOMConfigurator::configure("MyLogConfig.xml");
// Loop something
for(int i=0; i<10; ++i)
{
LOG4CXX_DEBUG(loggerToFile, _T("this is a debug message."));
LOG4CXX_INFO (loggerToFile, _T("this is a info message, just ignore."));
LOG4CXX_WARN (loggerToFile, _T("this is a warn message, dont worry too much."));
LOG4CXX_ERROR(loggerToFile, _T("this is a error message, something serious is happening."));
LOG4CXX_FATAL(loggerToFile, _T("this is a fatal message, crash and burn!!!"));
MyFunctionA();
Sleep(1000);
printf("i = %d\n", i);
}
getchar();
return 0;
}
Writing the log4cxx Configuration File
The log4cxx configuration file as follows ( MyLogConfig.xml ):
<?xml version="1.0" encoding="UTF-8" ?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Output the log message to system console.
-->
<appender name="MyConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<!-- Output the log message to a log file named "NormalLogFile.log"
-->
<appender name="MyNormalAppender" class="org.apache.log4j.FileAppender">
<param name="file" value="NormalLogFile.log" />
<param name="append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %5p %c{1} - %m%n" />
</layout>
</appender>
<!-- the following appender with the name "TimeBasedLog.log", every night a few seconds after
12::00PM the old log will be renamed with append the date in filename, and a new log file
with the name "TimeBasedLog.log" will be create.
notice the RollingFileAppender is under "org.apache.log4j.rolling" namespace
-->
<appender name="MyRollingAppenderDaily" class="org.apache.log4j.rolling.RollingFileAppender">
<rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
<param name="FileNamePattern" value="TimeBasedLog.%d{yyyy-MM-dd}.log"/>
<param name="activeFileName" value="TimeBasedLog.log"/>
</rollingPolicy>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} %x [%p] (%F:%L) %m%n"/>
</layout>
<param name="file" value="TimeBasedLog.log"/>
<param name="append" value="true"/>
</appender>
<!-- On application startup, a log file named "SizeBasedLog.log" will be create if not exist.
When the log file reach beyond 5KB, it will be renamed "SizeBasedLog.log.1", when the log
index reach "SizeBasedLog.log.5", the next rename will be back to "SizeBasedLog.log.1" and
overite the old log.
-->
<appender name="MyRollingAppenderSize" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="SizeBasedLog.log"/>
<param name="append" value="true"/>
<param name="MaxFileSize" value="5KB"/>
<param name="MaxBackupIndex" value="5"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
</layout>
</appender>
<!-- the following appender creates a logfile in log4j XML format, suitable to viewing with
XML log viewer such as Chainsaw (http://logging.apache.org/log4j/docs/chainsaw.html)
-->
<appender name="MyLogFileAppenderXml" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="XmlLog.txt" />
<param name="append" value="true" />
<param name="ImmediateFlush" value="true" />
<layout class="org.apache.log4j.xml.XMLLayout" />
</appender>
<!-- This appender will send email through SMTP server.
-->
<appender name="MySMTPAppenderEmail" class="org.apache.log4j.net.SMTPAppender">
<param name="BufferSize" value="512" />
<param name="SMTPHost" value="smtp.youremailserver.com" />
<param name="SMTPPort" value="25" />
<param name="From" value="yourname@youremailserver.com (mailto:yourname@youremailserver.com)" />
<param name="To" value="yourname@youremailserver.com (mailto:yourname@youremailserver.com)" />
<param name="CC" value="someoneelse@youremailserver.com (mailto:someoneelse@youremailserver.com)" />
<param name="SMTPUsername" value="yourusername" />
<param name="SMTPPassword" value="yourpassword" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ABSOLUTE},%c{1}] %m%n"/>
</layout>
</appender>
<!-- This appender will write the log message to a database through JDBC connection
to Sybase Database.
-->
<appender name="MyJdbcAppender" class="org.apache.log4j.jdbc.JDBCAppender">
<param name="driver" value="com.sybase.jdbc2.jdbc.SybDriver"/>
<param name="URL" value="jdbc:sybase:Tds:127.0.0.1:2638/Summit"/>
<param name="user" value="DBA"/>
<param name="password" value="SQL"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="INSERT INTO ErrorLog (ErrorMessage) VALUES ('%d - %c - %p - %m')"/>
</layout>
</appender>
<!-- This appender will write log message and send it through XMLSocketAppender, a receiver
with XMLSocketReceiver such as Chainsaw (http://logging.apache.org/log4j/docs/chainsaw.html)
will be able to receive and interpret it.
-->
<appender name="MyXmlAppender" class="org.apache.log4j.net.XMLSocketAppender">
<param name="Port" value="1234"/>
<param name="RemoteHost" value="10.7.5.15"/>
<param name="ReconnectionDelay" value="60000"/>
<param name="LocationInfo" value="true" />
</appender>
<!-- Using XMLSocketAppender couple with pattern layout to send text lines to
a ordinary TCP listener, any application that implements TCP socuket listening
will be able to receive the log message.
-->
<appender name="MyXmlAppenderFormated" class="org.apache.log4j.net.XMLSocketAppender">
<param name="Port" value="1235"/>
<param name="RemoteHost" value="localhost"/>
<param name="ReconnectionDelay" value="60000"/>
<param name="LocationInfo" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
</layout>
</appender>
<!-- Setup the root category, add the appenders and set the default level
5 level of logging, ALL < DEBUG < INFO < WARN < ERROR < FATAL
The root level is set with INFO, which mean any message greater or same
as INFO will be log down, in this case, DEBUG is not logged.
To log all regardless of logging level, set <priority value="ALL">
-->
<root>
<priority value="all" />
<appender-ref ref="MyRollingAppenderDaily"/>
<appender-ref ref="MyRollingAppenderSize"/>
<appender-ref ref="MyConsoleAppender"/>
<appender-ref ref="MyLogFileAppenderXml"/>
<appender-ref ref="MyXmlAppenderFormated"/>
<appender-ref ref="MyXmlAppender"/>
<appender-ref ref="MyJdbcAppender"/>
</root>
<!-- Specify the level for some specific categories -->
<category name="MyFunctionA" >
<priority value ="info" />
<appender-ref ref="MyNormalAppender" />
</category>
</log4j:configuration>
You may notice that the tag has log4j in it, that's fine, it'll work :)
I can't remember where did I gather all the pieces up there, but I kind of remember that it was pieces from different sources before I have put in together. Let me know if you need additional instructions. Is this helpful? Happy Logging ; )