diff options
| -rw-r--r-- | icetray/icetray/Jamfile.jam | 1 | ||||
| -rw-r--r-- | icetray/icetray/icetrayService.cpp | 4 | ||||
| -rw-r--r-- | icetray/icetray/logger.cpp | 57 | ||||
| -rw-r--r-- | icetray/icetray/logger.h | 19 | ||||
| -rw-r--r-- | icetray/unittests/testIceTrayLogger.cpp | 127 | 
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();  | 
