|
Related YoLinux Tutorials:
°C++ Info, links
°C++ String Class
°C++ STL vector, list
°Fork and exec
°BSD Sockets
°Emacs and C/C++
°Advanced VI
°CGI in C++
°MS/Visual C++ Practices
°C++ Memory corruption and leaks
°YoLinux Tutorials Index
Free Information Technology Magazines and Document Downloads
Free Information Technology Software and Development Magazine Subscriptions and Document Downloads
|
Apache Log4cxx is a framework which provides the capability to log messages in a variety of formats to the local console, local files, streamed over a socket or even launch an email based on a hierarchy of notification levels.
-
| Log Level | Description |
| FATAL | Severe errors that cause premature termination. |
| ERROR | Other runtime errors or unexpected conditions. |
| WARN | Runtime situations that are undesirable or unexpected, but not necessarily "wrong". |
| INFO | Interesting runtime events (startup/shutdown). |
| DEBUG | Detailed information on the flow through the system. |
| TRACE | More detailed information. |
Prerequisites:
Red Hat Enterprise Linux 5 (RHEL5) and Ubuntu 8.10:
- autoconf and automake
- RHEL5: yum install autoconf automake
- Ubuntu: apt-get install autoconf automake
- libxml2 and libxml2-devel (http://xmlsoft.org/)
- RHEL5 (2.6.26): yum install libxml2 libxml2-devel
- Ubuntu 8.10 (2.6.32): sudo apt-get install libxml2 libxml2-dev
- gmp (http://swox.com/gmp/)
- RHEL5 (gmp 4.1.4): yum install gmp
- Ubuntu 8.10 (4.2.2): sudo apt-get install libgmpxx4 libgmp3-dev
- boost and boost-devel
- RHEL5 (boost: 1.33.1): yum install boost boost-devel
- Ubuntu 8.10 (libboost-dev: 1.34.1): sudo apt-get install libboost-dev
- cppunit
- RHEL5 (1.12.0): Download RPMs from RepoForge
Download packages cppunit and cppunit-devel
- Ubuntu 8.10 (1.12.1): sudo apt-get install libcppunit-dev
- apr, apr-devel and apr-util, apr-util-devel
- RHEL5 (1.2.7): yum install apr apr-devel apr-util apr-util-devel
- Ubuntu 8.10 (1.2.12): sudo apt-get install libapr1 libaprutil1
Requires Maven for the build (and thus requires Java):
- Install Java: (Maven is a Java program) See the YoLinux Java installation tutorial
- Install Maven (untar Java jar files. Java program and thus platform independent)
(Called by XmlBeans configure script and Makefile)
- Download compiled Java program: http://maven.apache.org/download.html
- cd /opt
- wget http://apache.opensourceresources.org/maven/binaries/apache-maven-2.2.1-bin.tar.gz
- tar xzf apache-maven-2.2.1-bin.tar.gz
This creates /opt/apache-maven-2.2.1
- Configuration:
- Add path to shell environment: export PATH=$PATH:/opt/apache-maven-2.2.1/bin
This allows execution of the Maven build command mvn
- If using a proxy, edit /opt/apache-maven-2.2.1/conf/settings.xml
Set proxy: <proxies> <proxy> ...
Ubuntu/Debian Note: Maven can also be installed using apt-get: sudo apt-get install maven2
Build and install:
- Apache Log4cxx home page
- download
- tar xzf apache-log4cxx-0.10.0.tar.gz
- cd apache-log4cxx-0.10.0/
- ./configure --prefix=/usr
Typically I would specify /opt or /usr/local but xmlbeansxx (an XML parser I like) which has a dependency on log4cxx and requires an installation in /usr.
- make
(will call Maven mvn)
- make install
This installs:
-
/usr/include/log4cxx/...
/usr/lib/liblog4cxx.so.10.0.0
/usr/lib/liblog4cxx.la
/usr/lib/liblog4cxx.a
/usr/lib/pkgconfig/liblog4cxx.pc
[Potential Pitfall]:
If you get the following error when atempting to use log4cxx:
-
error while loading shared libraries: liblog4cxx.so.10: cannot open shared object file: No such file or directory
Register the libraries with the system. Run the following command as root:
ldconfig -n /usr/lib
[Potential Pitfall]:
RHEL 6.3 gave me the following build error:
-
[prompt]$ ./configure --prefix=/usr LDFLAGS="-L/lib64 -L/usr/lib64"
[prompt]$ make
inputstreamreader.cpp:66: error: 'memmove' was not declared in this scope
make[3]: *** [inputstreamreader.lo] Error 1
Edit the following three files to fix this error:
- File: apache-log4cxx-0.10.0/src/main/cpp/inputstreamreader.cpp
Add the include file: #include <string.h>
Change from:
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/inputstreamreader.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/bytebuffer.h>
to:
#include <string.h>
#include <log4cxx/logstring.h>
#include <log4cxx/helpers/inputstreamreader.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/bytebuffer.h>
- File: apache-log4cxx-0.10.0/src/main/cpp/socketoutputstream.cpp
Add the include file: #include <string.h>
- File: apache-log4cxx-0.10.0/src/examples/cpp/console.cpp
Add the include file: #include <stdio.h>
Add the include file: #include <string.h>
[Potential Pitfall]:
If you get the following error during the configure process:
-
checking for APR... configure: error: --with-apr requires a directory or file to be provided
you may have neglected to install the packages apr-devel and apr-util-devel.
Install (RHEL5 example): rpm -ivh apr-devel-1.2.7-11.el5_3.1.i386.rpm apr-util-devel-1.2.7-7.el5_3.2.i386.rpm
[Potential Pitfall]:
Building on a 64 bit x86_64 Linux system - You may get the following link error:
-
/usr/lib/libaprutil-1.so: could not read symbols: File in wrong format
This is because the linker is trying to link with /usr/lib/libaprutil-1.so.0 instead of /usr/lib64/libaprutil-1.so.0
One can force a link with 64 bit libraries by using one of the following techniques:
- Add the following directives to the configure script: ./configure --prefix=/usr LDFLAGS="-L/lib64 -L/usr/lib64"
- Set the following environment variable: export LDFLAGS="-L/lib64 -L/usr/lib64"
- Edit the gcc/g++ compile/link statement and add the following directives: -L/lib64 -L/usr/lib64
or go all 32 bit (cross compile from 64 bit system). Build 32 bit code on the 64 bit system: ./configure CXXFLAGS="-m32" LDFLAGS="-m32"
| Example of C++ logging using Log4cxx: |
File: testLog4cxx.cpp
-
#include <log4cxx/logger.h>
#include <log4cxx/xml/domconfigurator.h>
using namespace log4cxx;
using namespace log4cxx::xml;
using namespace log4cxx::helpers;
// Define static logger variable
LoggerPtr loggerMyMain(Logger::getLogger( "main"));
LoggerPtr loggerFunctionA(Logger::getLogger( "functionA"));
void functionA()
{
LOG4CXX_INFO(loggerFunctionA, "Executing functionA.");
}
int main()
{
// Load configuration file
DOMConfigurator::configure("Log4cxxConfig.xml");
LOG4CXX_TRACE(loggerMyMain, "this is a debug message for detailed code discovery.");
LOG4CXX_DEBUG(loggerMyMain, "this is a debug message.");
LOG4CXX_INFO (loggerMyMain, "this is a info message, ignore.");
LOG4CXX_WARN (loggerMyMain, "this is a warn message, not too bad.");
LOG4CXX_ERROR(loggerMyMain, "this is a error message, something serious is happening.");
LOG4CXX_FATAL(loggerMyMain, "this is a fatal message!!!");
functionA();
return 0;
}
Compile and static link: g++ testLog4cxx.cpp -I/opt/include /opt/lib/liblog4cxx.a -lapr-1 -laprutil-1
Log4cxx Configuration File: Log4cxxConfig.xml
(Specified in line 20 in the program above)
-
<?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="appxConsoleAppender" 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 log file
-->
<appender name="appxNormalAppender" class="org.apache.log4j.FileAppender">
<param name="file" value="appxLogFile.log" />
<param name="append" value="true" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%t:%x] %C{2} (%F:%L) - %m%n" />
</layout>
</appender>
<root>
<priority value="all" />
<appender-ref ref="appxNormalAppender"/>
<appender-ref ref="appxConsoleAppender"/>
</root>
<!-- Specify the level for some specific categories -->
<category name="functionA" >
<priority value ="info" />
<appender-ref ref="appxNormalAppender"/>
<appender-ref ref="appxConsoleAppender"/>
</category>
</log4j:configuration>
|
Note this configuration file logs all messages to the console and log file.
| Log4cxx configuration file options: |
Log4cxx can log to the console and log file as shown above. It can also log in XML format or a specified format, it can log time intervals with each interval logged to its' own log file (time based logs with TimeBasedRollingPolicy) or log to files of a specified size where upon reaching the size limit, it logs to a new file (size based logs set MaxFileSize).
Log4cxx can log to the Linux syslogd (local or remote) or to a socket stream.
Email allerts can be sent (e.g. send email upon total extreme failure).
Logs can be sent vis ODBC to MySQL or Postgres.
Add the "appender" definition and "root" "appender-ref" snipets below to the above configuration file.
Time based logs (daily) snipet:
-
<appender name="appxRollingAppenderDaily" 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="appxDailyLog.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="appxDailyLog.log"/>
<param name="append" value="true"/>
</appender>
...
...
<root>
<priority value="all" />
<appender-ref ref="appxRollingAppenderDaily"/>
</root>
|
Size based logs snippet:
-
<appender name="appxRollingAppenderSize" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="appxSizeBasedLog.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>
...
...
<root>
<priority value="all" />
<appender-ref ref="appxRollingAppenderSize"/>
</root>
|
Note:
- Set file size limit MaxFileSize to 5KB
- Keep five rolling log files with MaxBackupIndex: appxSizeBasedLog.log.1, ... appxSizeBasedLog.log.5
Log4cxx will operate "round robin" and overwrite the previous log file.
XML outputlogs: (used by Chainsaw)
-
<appender name="appxLogFileAppenderXml" class="org.apache.log4j.RollingFileAppender">
<param name="file" value="appxXmlLog.txt" />
<param name="append" value="true" />
<param name="ImmediateFlush" value="true" />
<layout class="org.apache.log4j.xml.XMLLayout" />
</appender>
...
...
<root>
<priority value="all" />
<appender-ref ref="appxLogFileAppenderXml"/>
</root>
|
Send an email via SMTP:
-
<appender name="appxSMTPAppenderEmail" class="org.apache.log4j.net.SMTPAppender">
<param name="BufferSize" value="512" />
<param name="SMTPHost" value="smtp.yourdomain.com" />
<param name="SMTPPort" value="25" />
<param name="From" value="sysadmin@yourdomain.com (mailto:sysadmin@yourdomain.com)" />
<param name="To" value="bigboss@yourdomain.com (mailto:bigboss@yourdomain.com)" />
<param name="CC" value="otheruser@yourdomain.com (mailto:otheruser@yourdomain.com)" />
<param name="SMTPUsername" value="adminaccount" />
<param name="SMTPPassword" value="supersecret" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ABSOLUTE},%c{1}] %m%n"/>
</layout>
</appender>
...
...
<root>
<priority value="all" />
<appender-ref ref="appxSMTPAppenderEmail"/>
</root>
|
| Using Log4cxx with the "Chainsaw" log file viewer |
Apache Chainsaw is a Java GUI application for viewing log files.
It can accept streaming logs or view a log file.
Start Chainsaw before running the application as this will be the socket server, then start the application. The Log4cxx configuration below will set-up the application to be the socket client which will attach to the Chainsaw socket server.
Configure Chainsaw:
- Right click on "Receivers"
- Select option "New Receivers"
- Select "New XMLSocketReceiver" (This will open up a new dialog window shown below)
- Populate the options:
- active: false (default)
- class: org.apache.log4j.net.XMLSocketReceiver (default)
- decoder: org.apache.log4j.xml.XMLDecoder
- name: name-of-application-you-are-logging
- paused: false (default)
- port: 4448 (default)
- threshold: TRACE (Select from TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF, ALL)
-
Application Log4cxx configuration to log to the console and to connect to and log to Chainsaw:
-
<?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="ConsoleAppender" 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>
<appender name="ChainsawAppenderXML" class="org.apache.log4j.XMLSocketAppender">
<param name="RemoteHost" value="192.168.1.101"/>
<param name="Port" value="4448" />
<layout class="org.apache.log4j.xml.XMLLayout">
<param name="properties" value="true" />
<param name="locationinfo" value="true" />
</layout>
</appender>
<root>
<priority value="error" />
<appender-ref ref="ConsoleAppender"/>
<appender-ref ref="ChainsawAppenderXML"/>
</root>
<category name="main" >
<priority value ="trace" />
</category>
<category name="MySAX2Handler" >
<priority value ="error" />
</category>
</log4j:configuration>
Books: |
-
 |
C++ How to Program
by Harvey M. Deitel, Paul J. Deitel
ISBN #0131857576, Prentice Hall
Fifth edition.
The first edition of this book (and Professor Sheely at UTA) taught me to
program C++. It is complete and covers all the nuances of the C++ language.
It also has good code examples. Good for both learning and reference.
|
|
|
|