summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2017-06-12 20:44:02 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2017-06-12 20:44:17 +0100
commitd45efb9de474b625fddaab5914c5c5c6955e9c7a (patch)
tree30f1f5c15b5bb4e40c1236f77104506f0d99baae
parentAdd basic support for managed logging (diff)
downloadicetray-d45efb9de474b625fddaab5914c5c5c6955e9c7a.tar.bz2
icetray-d45efb9de474b625fddaab5914c5c5c6955e9c7a.tar.xz
icetray-d45efb9de474b625fddaab5914c5c5c6955e9c7a.zip
Add support for configured installed log writers on start-up from properties in the Communicator
-rw-r--r--icetray/icetray/Jamfile.jam1
-rw-r--r--icetray/icetray/icetrayService.cpp4
-rw-r--r--icetray/icetray/logger.cpp57
-rw-r--r--icetray/icetray/logger.h19
-rw-r--r--icetray/unittests/testIceTrayLogger.cpp127
5 files changed, 174 insertions, 34 deletions
diff --git a/icetray/icetray/Jamfile.jam b/icetray/icetray/Jamfile.jam
index 42f5389..7944202 100644
--- a/icetray/icetray/Jamfile.jam
+++ b/icetray/icetray/Jamfile.jam
@@ -15,6 +15,7 @@ lib icetray :
<library>..//boost_thread
<library>../..//glibmm
<allow-ice>yes
+ <slicer>yes
: :
<include>.
<library>..//dbppcore
diff --git a/icetray/icetray/icetrayService.cpp b/icetray/icetray/icetrayService.cpp
index 8353fd2..d540d7a 100644
--- a/icetray/icetray/icetrayService.cpp
+++ b/icetray/icetray/icetrayService.cpp
@@ -29,6 +29,10 @@ namespace IceTray {
void Service::start(const std::string & name, const Ice::CommunicatorPtr & ic, const Ice::StringSeq & args)
{
adp = ic->createObjectAdapter(name);
+ for (auto logWriterFactory : AdHoc::PluginManager::getDefault()->getAll<Logging::LogWriterFactory>()) {
+ auto logWriter = logWriterFactory->implementation()->create(ic->getProperties().get());
+ logManager.addWriter(Logging::LogWriterPrx::uncheckedCast(adp->addWithUUID(logWriter)));
+ }
addObjects(name, ic, args, adp);
adp->activate();
}
diff --git a/icetray/icetray/logger.cpp b/icetray/icetray/logger.cpp
index b4cf629..aac966a 100644
--- a/icetray/icetray/logger.cpp
+++ b/icetray/icetray/logger.cpp
@@ -2,8 +2,12 @@
#include <factory.impl.h>
#include <buffer.h>
#include <lockHelpers.h>
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <slicer/modelPartsTypes.h>
-INSTANTIATEFACTORY(IceTray::Logging::LogWriter, Ice::CommunicatorPtr);
+INSTANTIATEFACTORY(IceTray::Logging::LogWriter, Ice::Properties *);
namespace IceTray {
namespace Logging {
@@ -131,6 +135,57 @@ namespace IceTray {
logger->logs = getLogsForDomain(logger->domain);
}
}
+
+ AbstractLogWriter::AbstractLogWriter()
+ {
+ }
+
+ AbstractLogWriter::AbstractLogWriter(LogLevel level)
+ {
+ logDomains.insert({ { }, level });
+ }
+
+ AbstractLogWriter::AbstractLogWriter(const std::string & prefix, Ice::PropertiesPtr p)
+ {
+ if (!p || prefix.empty()) {
+ logDomains.insert({ { }, WARNING });
+ return;
+ }
+ auto domainsPrefix = prefix + ".domains.";
+ auto map = p->getPropertiesForPrefix(domainsPrefix);
+ for (const auto & d : map) {
+ auto level = Slicer::ModelPartForEnum<LogLevel>::lookup(d.second);
+ auto domain = d.first.substr(domainsPrefix.length());
+ logDomains.insert({ splitDomain(domain), level });
+ }
+ auto defaultLevel = p->getProperty(prefix + ".default");
+ if (!defaultLevel.empty()) {
+ auto level = Slicer::ModelPartForEnum<LogLevel>::lookup(defaultLevel);
+ logDomains.insert({ {}, level });
+ }
+ }
+
+ IceUtil::Optional<LogLevel>
+ AbstractLogWriter::level(const std::string & domain, const Ice::Current &)
+ {
+ auto domainTokens = splitDomain(domain);
+ for (auto d = logDomains.rbegin(); d != logDomains.rend(); d++) {
+ if (boost::algorithm::starts_with(domainTokens, d->first)) {
+ return d->second;
+ }
+ }
+ return IceUtil::None;
+ }
+
+ Ice::StringSeq
+ AbstractLogWriter::splitDomain(const std::string & domain)
+ {
+ if (domain.empty()) return Ice::StringSeq();
+
+ Ice::StringSeq domainTokens;
+ boost::algorithm::split(domainTokens, domain, boost::algorithm::is_any_of(".:"), boost::algorithm::token_compress_on);
+ return domainTokens;
+ }
}
}
diff --git a/icetray/icetray/logger.h b/icetray/icetray/logger.h
index cb16852..c435644 100644
--- a/icetray/icetray/logger.h
+++ b/icetray/icetray/logger.h
@@ -8,6 +8,7 @@
#include <map>
#include <buffer.h>
#include <boost/thread/shared_mutex.hpp>
+#include <Ice/Properties.h>
namespace IceTray {
namespace Logging {
@@ -79,7 +80,23 @@ namespace IceTray {
LogWriters logWriters;
};
- typedef AdHoc::Factory<LogWriter, Ice::CommunicatorPtr> LogWriterFactory;
+ class DLL_PUBLIC AbstractLogWriter : public LogWriter {
+ public:
+ IceUtil::Optional<LogLevel> level(const std::string &, const Ice::Current &) override;
+
+ protected:
+ AbstractLogWriter();
+ AbstractLogWriter(LogLevel level);
+ AbstractLogWriter(const std::string & prefix, Ice::PropertiesPtr p);
+
+ typedef std::map<Ice::StringSeq, LogLevel> LogDomains;
+ LogDomains logDomains;
+
+ private:
+ static Ice::StringSeq splitDomain(const std::string &);
+ };
+
+ typedef AdHoc::Factory<LogWriter, Ice::Properties *> LogWriterFactory;
}
}
diff --git a/icetray/unittests/testIceTrayLogger.cpp b/icetray/unittests/testIceTrayLogger.cpp
index 321a878..e1a62a5 100644
--- a/icetray/unittests/testIceTrayLogger.cpp
+++ b/icetray/unittests/testIceTrayLogger.cpp
@@ -8,40 +8,37 @@
#include <Ice/ObjectAdapter.h>
#include <compileTimeFormatter.h>
#include <boost/format.hpp>
+#include <slicer/common.h>
using namespace IceTray::Logging;
struct LogEntry {
+ LogLevel priority;
std::string domain;
std::string message;
};
-class TestLogWriter : public LogWriter {
+class TestLogWriter : public AbstractLogWriter {
public:
- TestLogWriter(LogLevel ll) :
- calls(0),
- l(ll)
+ template <typename ... T>
+ TestLogWriter(const T & ... t) :
+ AbstractLogWriter(t...)
{
}
- IceUtil::Optional<LogLevel> level(const std::string &, const Ice::Current &) override
+ TestLogWriter(Ice::Properties * p) :
+ AbstractLogWriter("TestLogWriter", p)
{
- return l;
}
void message(LogLevel priority, const std::string & domain, const std::string & message, const Ice::Current &) override
{
- calls += 1;
- BOOST_REQUIRE(l >= priority);
- msgs.push_back({domain, message});
+ msgs.push_back({priority, domain, message});
}
std::vector<LogEntry> msgs;
- unsigned int calls;
-
- private:
- const LogLevel l;
};
+FACTORY(TestLogWriter, LogWriterFactory);
class TestLogImpl {
public:
@@ -68,9 +65,9 @@ class TestLogImpl {
protected:
LoggerPtr log;
LogManager manager;
+ Ice::CommunicatorPtr ic;
private:
- Ice::CommunicatorPtr ic;
Ice::ObjectAdapterPtr adp;
};
@@ -94,57 +91,48 @@ BOOST_AUTO_TEST_CASE(priority_filtering) {
log->message(DEBUG, "debug");
BOOST_REQUIRE(w->msgs.empty());
BOOST_REQUIRE(e->msgs.empty());
- BOOST_REQUIRE_EQUAL(0, w->calls);
- BOOST_REQUIRE_EQUAL(0, e->calls);
log->message(INFO, "into");
BOOST_REQUIRE(w->msgs.empty());
BOOST_REQUIRE(e->msgs.empty());
- BOOST_REQUIRE_EQUAL(0, w->calls);
- BOOST_REQUIRE_EQUAL(0, e->calls);
log->message(NOTICE, "notice");
BOOST_REQUIRE(w->msgs.empty());
BOOST_REQUIRE(e->msgs.empty());
- BOOST_REQUIRE_EQUAL(0, w->calls);
- BOOST_REQUIRE_EQUAL(0, e->calls);
log->message(WARNING, "warning");
BOOST_REQUIRE_EQUAL(1, w->msgs.size());
BOOST_REQUIRE(e->msgs.empty());
- BOOST_REQUIRE_EQUAL(1, w->calls);
- BOOST_REQUIRE_EQUAL(0, e->calls);
log->message(ERR, "err");
BOOST_REQUIRE_EQUAL(2, w->msgs.size());
BOOST_REQUIRE_EQUAL(1, e->msgs.size());
- BOOST_REQUIRE_EQUAL(2, w->calls);
- BOOST_REQUIRE_EQUAL(1, e->calls);
log->message(CRIT, "crit");
BOOST_REQUIRE_EQUAL(3, w->msgs.size());
BOOST_REQUIRE_EQUAL(2, e->msgs.size());
- BOOST_REQUIRE_EQUAL(3, w->calls);
- BOOST_REQUIRE_EQUAL(2, e->calls);
log->message(ALERT, "alert");
BOOST_REQUIRE_EQUAL(4, w->msgs.size());
BOOST_REQUIRE_EQUAL(3, e->msgs.size());
- BOOST_REQUIRE_EQUAL(4, w->calls);
- BOOST_REQUIRE_EQUAL(3, e->calls);
log->message(EMERG, "emerg");
BOOST_REQUIRE_EQUAL(5, w->msgs.size());
BOOST_REQUIRE_EQUAL(4, e->msgs.size());
- BOOST_REQUIRE_EQUAL(5, w->calls);
- BOOST_REQUIRE_EQUAL(4, e->calls);
manager.removeWriter(wp);
log->message(ERR, "err2");
BOOST_REQUIRE_EQUAL(5, w->msgs.size());
BOOST_REQUIRE_EQUAL(5, e->msgs.size());
- BOOST_REQUIRE_EQUAL(5, w->calls);
- BOOST_REQUIRE_EQUAL(5, e->calls);
+}
+
+BOOST_AUTO_TEST_CASE( no_domains )
+{
+ auto d = new TestLogWriter();
+ manager.addWriter(add(d));
+ log->message(DEBUG, "debug message.");
+ log->message(EMERG, "emergency message.");
+ BOOST_REQUIRE(d->msgs.empty());
}
BOOST_AUTO_TEST_CASE(formatter_plain)
@@ -188,6 +176,77 @@ BOOST_AUTO_TEST_CASE(formatter_adhoc_compiletime)
BOOST_REQUIRE_EQUAL("test.domain", d->msgs.front().domain);
}
+BOOST_AUTO_TEST_CASE( domains_none )
+{
+ // No domains
+ auto l = add(new TestLogWriter());
+ BOOST_REQUIRE(!l->level("test"));
+ BOOST_REQUIRE(!l->level("test.domain"));
+}
+
+BOOST_AUTO_TEST_CASE( domains_single )
+{
+ // A single catch-all domain at the given level
+ auto l = add(new TestLogWriter(ERR));
+ BOOST_REQUIRE_EQUAL(ERR, *l->level("test"));
+ BOOST_REQUIRE_EQUAL(ERR, *l->level("test.domain"));
+}
+
+BOOST_AUTO_TEST_CASE( domains_fromNullProperties )
+{
+ // A single catch-all domain at the default level (WARNING)
+ auto l = add(new TestLogWriter("", Ice::PropertiesPtr()));
+ BOOST_REQUIRE_EQUAL(WARNING, *l->level("test"));
+ BOOST_REQUIRE_EQUAL(WARNING, *l->level("test.domain"));
+}
+
+BOOST_AUTO_TEST_CASE( domains_fromProperties )
+{
+ // Domains configured according to properties
+ Ice::PropertiesPtr p = ic->getProperties();
+ p->setProperty("TestLogWriter.domains.test.domain", "EMERG");
+ p->setProperty("TestLogWriter.domains.test.debug", "DEBUG");
+ p->setProperty("TestLogWriter.domains", "ignored");
+ p->setProperty("TestLogWriter.default", "WARNING");
+ auto l = add(new TestLogWriter("TestLogWriter", p));
+ BOOST_REQUIRE_EQUAL(WARNING, *l->level("test"));
+ BOOST_REQUIRE_EQUAL(WARNING, *l->level("other"));
+ BOOST_REQUIRE_EQUAL(EMERG, *l->level("test.domain"));
+ BOOST_REQUIRE_EQUAL(DEBUG, *l->level("test.debug"));
+}
+
+BOOST_AUTO_TEST_CASE( domains_fromProperties_noDefault )
+{
+ // Domains configured according to properties
+ Ice::PropertiesPtr p = ic->getProperties();
+ p->setProperty("TestLogWriter.domains.test.domain", "EMERG");
+ p->setProperty("TestLogWriter.domains.test.debug", "DEBUG");
+ auto l = add(new TestLogWriter("TestLogWriter", p));
+ BOOST_REQUIRE_EQUAL(EMERG, *l->level("test.domain"));
+ BOOST_REQUIRE_EQUAL(DEBUG, *l->level("test.debug"));
+}
+
+BOOST_AUTO_TEST_CASE( domains_fromProperties_onlyDefault )
+{
+ // Domains configured according to properties
+ Ice::PropertiesPtr p = ic->getProperties();
+ p->setProperty("TestLogWriter.default", "INFO");
+ auto l = add(new TestLogWriter("TestLogWriter", p));
+ BOOST_REQUIRE_EQUAL(INFO, *l->level("test"));
+ BOOST_REQUIRE_EQUAL(INFO, *l->level("other"));
+ BOOST_REQUIRE_EQUAL(INFO, *l->level("test.domain"));
+ BOOST_REQUIRE_EQUAL(INFO, *l->level("test.debug"));
+}
+
+BOOST_AUTO_TEST_CASE( domains_fromProperties_badLevel )
+{
+ Ice::PropertiesPtr p = ic->getProperties();
+ p->setProperty("TestLogWriter.domains.test.domain", "BAD");
+ BOOST_REQUIRE_THROW({
+ TestLogWriter tlw("TestLogWriter", p);
+ }, Slicer::InvalidEnumerationSymbol);
+}
+
BOOST_AUTO_TEST_SUITE_END();
class TestService : public IceTray::Service {
@@ -201,8 +260,12 @@ BOOST_FIXTURE_TEST_SUITE( ts, TestService );
BOOST_AUTO_TEST_CASE( getLogger )
{
+ auto ic = Ice::initialize();
+ ic->getProperties()->setProperty("test.Endpoints", "default");
+ this->start("test", ic, {});
auto logger = LOGMANAGER()->getLogger("test.domain");
BOOST_REQUIRE(logger);
+ ic->destroy();
}
BOOST_AUTO_TEST_SUITE_END();