I want to log to different files in my code.
How can i do that in Log4cxx with xml configuration or programatically in code...
Update:
Logger.addAppender() approach:
log4cxx::helpers::Pool p;
std::string paramAppender = "appxNormalAppender";
std::string paramFileName = "\\Logs\\MyLog.txt";
LOG4CXX_DECODE_CHAR(logAppender, paramAppender );
LOG4CXX_DECODE_CHAR(logFileName, paramFileName );
FileAppenderPtr fileAppender =
logger->getLoggerRepository()->getRootLogger()->getAppender(logAppender);
if(fileAppender!= NULL)
{
fileAppender->setFile(logFileName);
fileAppender->activateOptions(p);
}
This does not work because
Suppose that i set FileName to Logger-k for k component, it logs to Logger-k, then i set file name to Logger-k+1 for compoent k+1, then both component k, and k+1 log the same loggerk+1 file. It seems last file name overrides or effects all others...
And
All compoenent compenent 1, ...compoeent k, componentk+1,.... component n are in the same application...
Create Each of the Loggers as normal, and then for each logger add a FileAppender set to the desired file via the Logger.addAppender() method.
You do need to create separate appenders for you loggers. In my example i've created afile1 and afile2 appenders. I have also created two loggers : my.logger1 and my.logger2. When you use my.logger1 it logs to mylog1 file, When you use my.logger2 it logs to mylog2 file.
Here is my log.properties file:
log4cplus.appender.afile1.layout=log4cplus::PatternLayout
log4cplus.appender.afile1.layout.ConversionPattern=%d [ %c{1} ] [ %-5p ] %m%n
log4cplus.appender.afile1=log4cplus::RollingFileAppender
log4cplus.appender.afile1.File=mylog1.log
log4cplus.appender.afile1.MaxFileSize=5MB
log4cplus.appender.afile1.MaxBackupIndex=2
log4cplus.appender.afile2.layout=log4cplus::PatternLayout
log4cplus.appender.afile2.layout.ConversionPattern=%d [ %c{1} ] [ %-5p ] %m%n
log4cplus.appender.afile2=log4cplus::RollingFileAppender
log4cplus.appender.afile2.File=mylog2.log
log4cplus.appender.afile2.MaxFileSize=5MB
log4cplus.appender.afile2.MaxBackupIndex=2
log4cplus.logger.my.logger1=INHERIT, afile1
log4cplus.additivity.my.logger1=false
log4cplus.logger.my.logger2=INHERIT, afile2
log4cplus.additivity.my.logger2=false
Here is an example programm:
example.cpp:
#include <iostream>
#include <log4cplus/logger.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/configurator.h>
#include <log4cplus/fileappender.h>
#define MYLOG1_INFO(logEvent) LOG4CPLUS_INFO (log4cplus::Logger::getInstance("my.logger1"), logEvent)
#define MYLOG2_INFO(logEvent) LOG4CPLUS_INFO (log4cplus::Logger::getInstance("my.logger2"), logEvent)
int main(int argc, char**argv)
{
try
{
log4cplus::PropertyConfigurator::doConfigure("log.properties");
}
catch( ... )
{
std::cerr<<"Exception occured while opening log.properties\n";
return -1;
}
MYLOG1_INFO("hello world!");
MYLOG2_INFO("hello world!");
return 0;
}
Here is Makefile( i suppose my log4cplus is built in parent dirrectory):
CXXFLAGS+=-I$(abspath ../log4cplus-1.0.4/include)
all: example.o
$(CXX) $^ $(abspath ../log4cplus-1.0.4/src/.libs/liblog4cplus.a) -lpthread -o test
Try this example and you should understand how appenders works
Log4cplus is mostly like log4j. so you can read basic principles log4j. And To get classes names you got to visit log4cplus.sourceforge.net
About log format. Documentation for log4cplus is available only in doxygen . so here you can read about formating in pattern layout
And if you want to log process id , than you should use %i in your layout conversion pattern
example:
...
log4cplus.appender.afile2.layout.ConversionPattern=[%i] %m%n
...
It will log process id and message
For dynamic components try this:
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <log4cxx/Logger.h>
#include <log4cxx/LogManager.h>
#include <log4cxx/xml/domconfigurator.h>
#include <log4cxx/FileAppender.h>
#include <log4cxx/SimpleLayout.h>
#include <log4cxx/helpers/transcoder.h>
void func(int k) {
std::string strName = "Log." + boost::lexical_cast<std::string>(k);
log4cxx::LoggerPtr log = log4cxx::Logger::getLogger(strName);
LOG4CXX_DECODE_CHAR(fileName, strName + ".log");
log4cxx::FileAppenderPtr appender(new log4cxx::FileAppender(new log4cxx::SimpleLayout, fileName, false));
log->addAppender(appender);
LOG4CXX_INFO(log, strName);
log->removeAppender(appender);
}
int main(int argc, char * argv[]) {
log4cxx::xml::DOMConfigurator::configure("trace.xml");
if(log4cxx::Logger::getLogger("Log")->getAllAppenders().empty()) {
std::cout << "failed to config log4cxx" << std::endl;
return 1;
}
log4cxx::LoggerPtr log = log4cxx::Logger::getLogger("Log");
boost::thread_group threadGroup;
for(int k = 0; k != 3; ++k) {
threadGroup.create_thread(boost::bind(func, k));
}
threadGroup.join_all();
return 0;
}
with simple trace.xml
<?xml version="1.0" encoding="UTF-8" ?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.SimpleLayout"/>
</appender>
<root>
<level value="all"/>
</root>
<category name="Log">
<level value="INFO"/>
<appender-ref ref="ConsoleAppender"/>
</category>
</log4j:configuration>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With