conf: Add log4cxx path to conf file
refs: #1950
Change-Id: I51f9217c6ee40fd49a53d5f8294b60fb306e82ee
diff --git a/log4cxx.properties.sample.in b/log4cxx.properties.sample.in
new file mode 100644
index 0000000..14e83a8
--- /dev/null
+++ b/log4cxx.properties.sample.in
@@ -0,0 +1,11 @@
+log4j.rootLogger=DEBUG, Rolling
+
+log4j.appender.Rolling=org.apache.log4j.rolling.RollingFileAppender
+log4j.appender.Rolling.File=/tmp/testnlsrproperties.log
+log4j.appender.Rolling.MaxSize=1MB
+log4j.appender.Rolling.MaxBackupIndex=10
+
+log4j.appender.Rolling.layout=PatternLayout
+log4j.appender.Rolling.layout.ContextPrinting=enabled
+log4j.appender.Rolling.layout.DateFormat=ISO8601
+log4j.appender.Rolling.layout.ConversionPattern=%date{yyyyMMddHHmmssSSS} %p: [%c] %m%n
\ No newline at end of file
diff --git a/nlsr.conf b/nlsr.conf
index 52ce870..31d9633 100644
--- a/nlsr.conf
+++ b/nlsr.conf
@@ -29,8 +29,9 @@
log-level INFO
- log-dir /var/log/nlsr/ ; path for log directory (Absolute path)
- seq-dir /var/lib/nlsr/ ; path for sequence directory (Absolute path)
+ log-dir /var/log/nlsr/ ; path for log directory (Absolute path)
+ seq-dir /var/lib/nlsr/ ; path for sequence directory (Absolute path)
+ ;log4cxx-conf /path/to/log4cxx-conf ; path for log4cxx configuration file (Absolute path)
}
; the neighbors section contains the configuration for router's neighbors and hello's behavior
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index de36941..b3067a3 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -348,7 +348,7 @@
}
}
else {
- std::cerr << "Log directory provided does not exists" << std::endl;
+ std::cerr << "Provided log directory <" << logDir << "> does not exist" << std::endl;
return false;
}
}
@@ -357,6 +357,7 @@
std::cerr << ex.what() << std::endl;
return false;
}
+
try {
std::string seqDir = section.get<string>("seq-dir");
if (boost::filesystem::exists(seqDir)) {
@@ -381,7 +382,7 @@
}
}
else {
- std::cerr << "Seq directory provided does not exists" << std::endl;
+ std::cerr << "Provided sequence directory <" << seqDir << "> does not exist" << std::endl;
return false;
}
}
@@ -391,6 +392,28 @@
return false;
}
+ try {
+ std::string log4cxxPath = section.get<string>("log4cxx-conf");
+
+ if (log4cxxPath == "") {
+ std::cerr << "No value provided for log4cxx-conf" << std::endl;
+ return false;
+ }
+
+ if (boost::filesystem::exists(log4cxxPath)) {
+ m_nlsr.getConfParameter().setLog4CxxConfPath(log4cxxPath);
+ }
+ else {
+ std::cerr << "Provided path for log4cxx-conf <" << log4cxxPath
+ << "> does not exist" << std::endl;
+
+ return false;
+ }
+ }
+ catch (const std::exception& ex) {
+ // Variable is optional so default configuration will be used; continue processing file
+ }
+
return true;
}
@@ -648,4 +671,4 @@
return true;
}
-} // namespace nlsr
+} // namespace nlsr
\ No newline at end of file
diff --git a/src/conf-parameter.cpp b/src/conf-parameter.cpp
index 763d771..30f0cf4 100644
--- a/src/conf-parameter.cpp
+++ b/src/conf-parameter.cpp
@@ -20,6 +20,7 @@
* \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
*
**/
+
#include "conf-parameter.hpp"
#include "logger.hpp"
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index 02eee7b..e25c4d3 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -111,6 +111,7 @@
, m_corR(0)
, m_corTheta(0)
, m_maxFacesPerPrefix(MAX_FACES_PER_PREFIX_MIN)
+ , m_isLog4cxxConfAvailable(false)
{
}
@@ -381,6 +382,25 @@
return m_seqFileDir;
}
+ bool
+ isLog4CxxConfAvailable() const
+ {
+ return m_isLog4cxxConfAvailable;
+ }
+
+ void
+ setLog4CxxConfPath(const std::string& path)
+ {
+ m_log4CxxConfPath = path;
+ m_isLog4cxxConfAvailable = true;
+ }
+
+ const std::string&
+ getLog4CxxConfPath() const
+ {
+ return m_log4CxxConfPath;
+ }
+
void
writeLog();
@@ -420,6 +440,8 @@
std::string m_logDir;
std::string m_seqFileDir;
+ bool m_isLog4cxxConfAvailable;
+ std::string m_log4CxxConfPath;
};
} // namespace nlsr
diff --git a/src/logger.cpp b/src/logger.cpp
index a82f5a9..6451a32 100644
--- a/src/logger.cpp
+++ b/src/logger.cpp
@@ -22,16 +22,30 @@
**/
#include <log4cxx/logger.h>
#include <log4cxx/basicconfigurator.h>
+#include <log4cxx/xml/domconfigurator.h>
+#include <log4cxx/propertyconfigurator.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/exception.h>
#include <log4cxx/rollingfileappender.h>
#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
#include "logger.hpp"
void
+INIT_LOG4CXX(const std::string& log4cxxConfPath)
+{
+ if (boost::filesystem::path(log4cxxConfPath).extension().string() == ".xml") {
+ log4cxx::xml::DOMConfigurator::configure(log4cxxConfPath);
+ }
+ else {
+ log4cxx::PropertyConfigurator::configure(log4cxxConfPath);
+ }
+}
+
+void
INIT_LOGGERS(const std::string& logDir, const std::string& logLevel)
{
static bool configured = false;
@@ -71,4 +85,4 @@
boost::iequals(logLevel, "debug") || boost::iequals(logLevel, "info") ||
boost::iequals(logLevel, "warn") || boost::iequals(logLevel, "error") ||
boost::iequals(logLevel, "none");
-}
+}
\ No newline at end of file
diff --git a/src/logger.hpp b/src/logger.hpp
index 267f30f..2a8e907 100644
--- a/src/logger.hpp
+++ b/src/logger.hpp
@@ -20,6 +20,7 @@
* \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
*
**/
+
#ifndef NLSR_LOGGER_HPP
#define NLSR_LOGGER_HPP
@@ -49,6 +50,9 @@
void
INIT_LOGGERS(const std::string& logDir, const std::string& logLevel);
+void
+INIT_LOG4CXX(const std::string& log4cxxConfPath);
+
bool
isValidLogLevel(const std::string& logLevel);
diff --git a/src/main.cpp b/src/main.cpp
index a21b0fd..45772aa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -66,13 +66,20 @@
return EXIT_FAILURE;
}
}
+
ConfFileProcessor cfp(nlsr, nlsr.getConfFileName());
if (!cfp.processConfFile()) {
std::cerr << "Error in configuration file processing! Exiting from NLSR" << std::endl;
return EXIT_FAILURE;
}
- INIT_LOGGERS(nlsr.getConfParameter().getLogDir(), nlsr.getConfParameter().getLogLevel());
+ if (nlsr.getConfParameter().isLog4CxxConfAvailable()) {
+ INIT_LOG4CXX(nlsr.getConfParameter().getLog4CxxConfPath());
+ }
+ else {
+ INIT_LOGGERS(nlsr.getConfParameter().getLogDir(), nlsr.getConfParameter().getLogLevel());
+ }
+
INIT_LOGGER("Main");
nlsr.initialize();
@@ -96,4 +103,4 @@
main(int32_t argc, char** argv)
{
return nlsr::main(argc, argv);
-}
+}
\ No newline at end of file
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index a66e6aa..19bb3cf 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -20,6 +20,7 @@
* \author A K M Mahmudul Hoque <ahoque1@memphis.edu>
*
**/
+
#include <cstdlib>
#include <string>
#include <sstream>
diff --git a/tests/test-conf-file-processor.cpp b/tests/test-conf-file-processor.cpp
index 5b70a65..25d1433 100644
--- a/tests/test-conf-file-processor.cpp
+++ b/tests/test-conf-file-processor.cpp
@@ -23,11 +23,15 @@
#include "test-common.hpp"
#include "dummy-face.hpp"
+#include "logger.hpp"
#include <fstream>
#include "conf-file-processor.hpp"
#include "nlsr.hpp"
+
#include <boost/test/unit_test.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
namespace nlsr {
namespace test {
@@ -49,6 +53,23 @@
" seq-dir /tmp\n"
"}\n\n";
+const std::string LOG4CXX_PLACEHOLDER = "$LOG4CXX$";
+
+const std::string SECTION_GENERAL_WITH_LOG4CXX =
+ "general\n"
+ "{\n"
+ " network /ndn/\n"
+ " site /memphis.edu/\n"
+ " router /cs/pollux/\n"
+ " lsa-refresh-time 1800\n"
+ " lsa-interest-lifetime 3\n"
+ " router-dead-interval 86400\n"
+ " log-level INFO\n"
+ " log-dir /tmp\n"
+ " seq-dir /tmp\n"
+ " log4cxx-conf " + LOG4CXX_PLACEHOLDER + "\n"
+ "}\n\n";
+
const std::string SECTION_NEIGHBORS =
"neighbors\n"
"{\n"
@@ -104,6 +125,8 @@
const std::string CONFIG_LINK_STATE = SECTION_GENERAL + SECTION_NEIGHBORS +
SECTION_HYPERBOLIC_OFF + SECTION_FIB + SECTION_ADVERTISING;
+const std::string CONFIG_LOG4CXX = SECTION_GENERAL_WITH_LOG4CXX;
+
const std::string CONFIG_HYPERBOLIC = SECTION_GENERAL + SECTION_NEIGHBORS +
SECTION_HYPERBOLIC_ON + SECTION_FIB + SECTION_ADVERTISING;
@@ -114,12 +137,18 @@
: face(ndn::makeDummyFace())
, nlsr(g_ioService, g_scheduler, ndn::ref(*face))
, CONFIG_FILE("unit-test-nlsr.conf")
+ , m_logConfigFileName(boost::filesystem::unique_path().native())
+ , m_logFileName(boost::filesystem::unique_path().native())
{
}
~ConfFileProcessorFixture()
{
remove("unit-test-nlsr.conf");
+ remove("/tmp/unit-test-log4cxx.xml");
+
+ boost::filesystem::remove(boost::filesystem::path(getLogConfigFileName()));
+ boost::filesystem::remove(boost::filesystem::path(getLogFileName()));
}
bool processConfigurationString(std::string confString)
@@ -133,12 +162,47 @@
return processor.processConfFile();
}
+ void
+ verifyOutputLog4cxx(const std::string expected[], size_t nExpected)
+ {
+ std::ifstream is(getLogFileName().c_str());
+ std::string buffer((std::istreambuf_iterator<char>(is)),
+ (std::istreambuf_iterator<char>()));
+
+ std::vector<std::string> components;
+ boost::split(components, buffer, boost::is_any_of(" ,\n"));
+
+ // expected + number of timestamps (one per log statement) + trailing newline of last statement
+ BOOST_REQUIRE_EQUAL(components.size(), nExpected);
+
+ for (size_t i = 0; i < nExpected; ++i) {
+ if (expected[i] == "")
+ continue;
+
+ BOOST_CHECK_EQUAL(components[i], expected[i]);
+ }
+ }
+
+ const std::string&
+ getLogConfigFileName()
+ {
+ return m_logConfigFileName;
+ }
+
+ const std::string&
+ getLogFileName()
+ {
+ return m_logFileName;
+ }
+
public:
shared_ptr<ndn::DummyFace> face;
Nlsr nlsr;
private:
const std::string CONFIG_FILE;
+ std::string m_logConfigFileName;
+ std::string m_logFileName;
};
BOOST_FIXTURE_TEST_SUITE(TestConfFileProcessor, ConfFileProcessorFixture)
@@ -146,7 +210,6 @@
BOOST_AUTO_TEST_CASE(LinkState)
{
processConfigurationString(CONFIG_LINK_STATE);
-
ConfParameter& conf = nlsr.getConfParameter();
conf.buildRouterPrefix();
@@ -195,6 +258,81 @@
BOOST_CHECK_EQUAL(nlsr.getNamePrefixList().getSize(), 2);
}
+BOOST_AUTO_TEST_CASE(Log4cxxFileExists)
+{
+ std::string configPath = boost::filesystem::unique_path().native();
+
+ std::ofstream log4cxxConfFile;
+ log4cxxConfFile.open(configPath);
+ log4cxxConfFile.close();
+
+ std::string config = CONFIG_LOG4CXX;
+ boost::replace_all(config, LOG4CXX_PLACEHOLDER, configPath);
+
+ BOOST_CHECK_EQUAL(processConfigurationString(config), true);
+
+ ConfParameter& conf = nlsr.getConfParameter();
+ BOOST_CHECK_EQUAL(conf.getLog4CxxConfPath(), configPath);
+ BOOST_CHECK_EQUAL(conf.isLog4CxxConfAvailable(), true);
+
+ boost::filesystem::remove(boost::filesystem::path(configPath));
+}
+
+BOOST_AUTO_TEST_CASE(Log4cxxFileDoesNotExist)
+{
+ std::string configPath = boost::filesystem::unique_path().native();
+
+ std::string config = CONFIG_LOG4CXX;
+ boost::replace_all(config, LOG4CXX_PLACEHOLDER, configPath);
+
+ BOOST_CHECK_EQUAL(processConfigurationString(config), false);
+}
+
+BOOST_AUTO_TEST_CASE(Log4cxxNoValue)
+{
+ std::string config = CONFIG_LOG4CXX;
+ boost::replace_all(config, LOG4CXX_PLACEHOLDER, "");
+
+ BOOST_CHECK_EQUAL(processConfigurationString(config), false);
+}
+
+BOOST_AUTO_TEST_CASE(Log4cxxTestCase)
+{
+ {
+ std::ofstream of(getLogConfigFileName().c_str());
+ of << "log4j.rootLogger=TRACE, FILE\n"
+ << "log4j.appender.FILE=org.apache.log4j.FileAppender\n"
+ << "log4j.appender.FILE.layout=org.apache.log4j.PatternLayout\n"
+ << "log4j.appender.FILE.File=" << getLogFileName() << "\n"
+ << "log4j.appender.FILE.ImmediateFlush=true\n"
+ << "log4j.appender.FILE.layout.ConversionPattern=%d{HH:mm:ss} %p %c{1} - %m%n\n";
+ }
+
+ INIT_LOG4CXX(getLogConfigFileName());
+
+ INIT_LOGGER("DefaultConfig");
+
+ _LOG_TRACE("trace-message-JHGFDSR^1");
+ _LOG_DEBUG("debug-message-IGg2474fdksd-fo-" << 15 << 16 << 17);
+ _LOG_INFO("info-message-Jjxjshj13");
+ _LOG_WARN("warning-message-XXXhdhd11" << 1 <<"x");
+ _LOG_ERROR("error-message-!#$&^%$#@");
+ _LOG_FATAL("fatal-message-JJSjaamcng");
+
+ const std::string EXPECTED[] =
+ {
+ "", "TRACE", "DefaultConfig", "-", "trace-message-JHGFDSR^1",
+ "", "DEBUG", "DefaultConfig", "-", "debug-message-IGg2474fdksd-fo-151617",
+ "", "INFO", "DefaultConfig", "-", "info-message-Jjxjshj13",
+ "", "WARN", "DefaultConfig", "-", "warning-message-XXXhdhd111x",
+ "", "ERROR", "DefaultConfig", "-", "error-message-!#$&^%$#@",
+ "", "FATAL", "DefaultConfig", "-", "fatal-message-JJSjaamcng",
+ "",
+ };
+
+ verifyOutputLog4cxx(EXPECTED, sizeof(EXPECTED) / sizeof(std::string));
+}
+
BOOST_AUTO_TEST_CASE(Hyperbolic)
{
processConfigurationString(CONFIG_HYPERBOLIC);
@@ -255,4 +393,4 @@
BOOST_AUTO_TEST_SUITE_END()
} //namespace test
-} //namespace nlsr
+} //namespace nlsr
\ No newline at end of file