diff options
-rw-r--r-- | icetray/icetray/logWriter.ice | 6 | ||||
-rw-r--r-- | icetray/icetray/logWriterConsole.cpp | 86 | ||||
-rw-r--r-- | icetray/icetray/logWriterConsole.h | 22 | ||||
-rw-r--r-- | icetray/icetray/logger.cpp | 18 | ||||
-rw-r--r-- | icetray/icetray/logger.h | 18 | ||||
-rw-r--r-- | icetray/unittests/testIceTrayLogger.cpp | 125 |
6 files changed, 215 insertions, 60 deletions
diff --git a/icetray/icetray/logWriter.ice b/icetray/icetray/logWriter.ice index 3d68f64..e55179b 100644 --- a/icetray/icetray/logWriter.ice +++ b/icetray/icetray/logWriter.ice @@ -14,11 +14,13 @@ module IceTray { INFO = 6, DEBUG = 7 }; + ["slicer:ignore"] + sequence<string> Domain; interface LogWriter { optional(0) LogLevel lowestLevel(); - optional(0) LogLevel level(string domain); - void message(LogLevel level, string domain, string message); + optional(0) LogLevel level(Domain domain); + void message(LogLevel level, Domain domain, string message); }; }; }; diff --git a/icetray/icetray/logWriterConsole.cpp b/icetray/icetray/logWriterConsole.cpp index 06c72eb..387c2d3 100644 --- a/icetray/icetray/logWriterConsole.cpp +++ b/icetray/icetray/logWriterConsole.cpp @@ -1,24 +1,82 @@ #include <logWriter.h> -#include "logger.h" +#include "logWriterConsole.h" #include <compileTimeFormatter.h> #include <slicer/modelPartsTypes.h> +namespace AdHoc { + AdHocFormatter(DomainFmt, ".%?"); + StreamWriterT('d') { + template<typename ... Pn> + static void write(stream & s, int width, const IceTray::Logging::Domain & domain, const Pn & ... pn) + { + auto di = domain.begin(); + if (di == domain.end()) { + return StreamWriter::next(s, pn...); + } + + if (width == -1) { + s << *di++; + while (di != domain.end()) { + DomainFmt::write(s, *di++); + } + } + else { + int target = width; + while (di != domain.end()) { + int total = di == domain.begin() ? -1 : 0; + for (auto dic = di; dic != domain.end(); dic++) { + total += 1 + dic->length(); + } + if (di == domain.begin()) { + if (total > target) { + s << di->front(); + target -= 1; + } + else { + s << *di; + target -= di->length(); + } + } + else { + if (total > target) { + DomainFmt::write(s, di->front()); + target -= 2; + } + else { + DomainFmt::write(s, *di); + target -= 1 + di->length(); + } + } + di++; + } + } + StreamWriter::next(s, pn...); + } + }; +} + namespace IceTray { namespace Logging { - AdHocFormatter(LogMsg, "%?: %?: %?\n"); - class ConsoleLogWriter : public AbstractLogWriter { - public: - ConsoleLogWriter(Ice::Properties * p) : - AbstractLogWriter("logging.console", p) - { - } + AdHocFormatter(LogMsg, "%?: %d: %?\n"); + ConsoleLogWriter::ConsoleLogWriter(Ice::Properties * p) : + AbstractLogWriter("logging.console", p), + width(p ? p->getPropertyAsIntWithDefault("logging.console.width", -1) : -1) + { + } - void message(LogLevel priority, const std::string & domain, const std::string & message, const Ice::Current &) override - { - LogMsg::write(priority < WARNING ? std::cerr : std::cout, - Slicer::ModelPartForEnum<LogLevel>::lookup(priority), domain, message); - } - }; + void + ConsoleLogWriter::message(LogLevel priority, const Domain & domain, const std::string & message, const Ice::Current &) + { + writeStream(priority < WARNING ? std::cerr : std::cout, + width, priority, domain, message); + } + + std::ostream & + ConsoleLogWriter::writeStream(std::ostream & s, int width, LogLevel priority, const Domain & domain, const std::string & message) + { + return LogMsg::write(s, + Slicer::ModelPartForEnum<LogLevel>::lookup(priority), width, domain, message); + } FACTORY(ConsoleLogWriter, LogWriterFactory); } } diff --git a/icetray/icetray/logWriterConsole.h b/icetray/icetray/logWriterConsole.h new file mode 100644 index 0000000..1c5cf3b --- /dev/null +++ b/icetray/icetray/logWriterConsole.h @@ -0,0 +1,22 @@ +#ifndef ICETRAY_LOGGING_CONSOLE_H +#define ICETRAY_LOGGING_CONSOLE_H + +#include "logger.h" + +namespace IceTray { + namespace Logging { + class ConsoleLogWriter : public AbstractLogWriter { + public: + ConsoleLogWriter(Ice::Properties * p); + + void message(LogLevel priority, const Domain & domain, const std::string & message, const Ice::Current &) override; + + static DLL_PUBLIC std::ostream & writeStream(std::ostream &, int width, LogLevel priority, const Domain & domain, const std::string & message); + + const int width; + }; + } +} + +#endif + diff --git a/icetray/icetray/logger.cpp b/icetray/icetray/logger.cpp index e36e193..8c5c36b 100644 --- a/icetray/icetray/logger.cpp +++ b/icetray/icetray/logger.cpp @@ -14,7 +14,7 @@ template class ::AdHoc::GlobalStatic<::IceTray::Logging::LogManager>; namespace IceTray { namespace Logging { - LoggerBase::LoggerBase(const std::string & domain) : + LoggerBase::LoggerBase(const Domain & domain) : domain(domain) { } @@ -23,13 +23,13 @@ namespace IceTray { { } - const std::string & + const Domain & LoggerBase::getDomain() const { return domain; } - Logger::Logger(const std::string & domain) : LoggerBase(domain) { } + Logger::Logger(const Domain & domain) : LoggerBase(domain) { } void Logger::message(LogLevel priority, const std::string & msg) const @@ -108,14 +108,15 @@ namespace IceTray { LoggerPtr LogManager::getLogger(const std::string & domain) { - auto logger = LoggerPtr(new Logger(domain)); - logger->logs = getLogsForDomain(domain); + auto domainTokens = AbstractLogWriter::splitDomain(domain); + auto logger = LoggerPtr(new Logger(domainTokens)); + logger->logs = getLogsForDomain(domainTokens); loggers.insert(logger.get()); return logger; } LogLevelWriters - LogManager::getLogsForDomain(const std::string & domain) const + LogManager::getLogsForDomain(const Domain & domain) const { SharedLock(_lock); LogLevelWriters logs; @@ -206,11 +207,10 @@ namespace IceTray { } IceUtil::Optional<LogLevel> - AbstractLogWriter::level(const std::string & domain, const Ice::Current &) + AbstractLogWriter::level(const Domain & 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)) { + if (boost::algorithm::starts_with(domain, d->first)) { return d->second; } } diff --git a/icetray/icetray/logger.h b/icetray/icetray/logger.h index 81d650c..0420415 100644 --- a/icetray/icetray/logger.h +++ b/icetray/icetray/logger.h @@ -22,21 +22,21 @@ namespace IceTray { class DLL_PUBLIC LoggerBase { public: - LoggerBase(const std::string & domain); + LoggerBase(const Domain & domain); ~LoggerBase(); - const std::string & getDomain() const; + const Domain & getDomain() const; protected: friend class LogManager; mutable boost::shared_mutex _lock; LogLevelWriters logs; - const std::string domain; + const Domain domain; }; class DLL_PUBLIC Logger : public LoggerBase { public: - Logger(const std::string & domain); + Logger(const Domain & domain); void message(LogLevel priority, const std::string & msg) const; void messagef(LogLevel priority, const char * msgfmt, ...) const __attribute__ ((format (printf, 3, 4))); @@ -78,7 +78,7 @@ namespace IceTray { } LoggerPtr getLogger(const std::type_info &); LoggerPtr getLogger(const std::string &); - LogLevelWriters getLogsForDomain(const std::string &) const; + LogLevelWriters getLogsForDomain(const Domain &) const; void addWriter(LogWriterPrx writer); void removeWriter(LogWriterPrx writer); @@ -94,18 +94,18 @@ namespace IceTray { class DLL_PUBLIC AbstractLogWriter : public LogWriter { public: IceUtil::Optional<LogLevel> lowestLevel(const Ice::Current &) override; - IceUtil::Optional<LogLevel> level(const std::string &, const Ice::Current &) override; + IceUtil::Optional<LogLevel> level(const Domain &, const Ice::Current &) override; protected: AbstractLogWriter(); AbstractLogWriter(LogLevel level); AbstractLogWriter(const std::string & prefix, Ice::PropertiesPtr p); - typedef std::map<Ice::StringSeq, LogLevel> LogDomains; + typedef std::map<Domain, LogLevel> LogDomains; LogDomains logDomains; - private: - static Ice::StringSeq splitDomain(const std::string &); + public: + static Domain splitDomain(const std::string &); }; typedef AdHoc::Factory<LogWriter, Ice::Properties *> LogWriterFactory; diff --git a/icetray/unittests/testIceTrayLogger.cpp b/icetray/unittests/testIceTrayLogger.cpp index 2a7fa50..81f0023 100644 --- a/icetray/unittests/testIceTrayLogger.cpp +++ b/icetray/unittests/testIceTrayLogger.cpp @@ -9,12 +9,13 @@ #include <compileTimeFormatter.h> #include <boost/format.hpp> #include <slicer/common.h> +#include <logWriterConsole.h> using namespace IceTray::Logging; struct LogEntry { LogLevel priority; - std::string domain; + Domain domain; std::string message; }; @@ -31,7 +32,7 @@ class TestLogWriter : public AbstractLogWriter { { } - void message(LogLevel priority, const std::string & domain, const std::string & message, const Ice::Current &) override + void message(LogLevel priority, const Domain & domain, const std::string & message, const Ice::Current &) override { msgs.push_back({priority, domain, message}); } @@ -40,16 +41,32 @@ class TestLogWriter : public AbstractLogWriter { }; FACTORY(TestLogWriter, LogWriterFactory); +namespace std { + ostream & + operator<<(ostream & s, const Domain & domain) { + for (const auto & d : domain) { + s << "::" << d; + } + return s; + } +} + class StaticLogTest { public: static IceTray::Logging::LoggerPtr staticLog; }; IceTray::Logging::LoggerPtr staticLog = LOGMANAGER()->getLogger<IceTray::Service>(); +Domain other = {"other"}; +Domain test = {"test"}; +Domain testDomain = {"test", "domain"}; +Domain testDebug = {"test", "debug"}; + BOOST_AUTO_TEST_CASE( staticLogInit ) { BOOST_REQUIRE(staticLog); - BOOST_REQUIRE_EQUAL("IceTray::Service", staticLog->getDomain()); + Domain expected = {"IceTray", "Service"}; + BOOST_REQUIRE_EQUAL(expected, staticLog->getDomain()); } class TestLogImpl { @@ -90,6 +107,12 @@ BOOST_AUTO_TEST_CASE(no_writers) { log->message(DEBUG, ""); } +BOOST_AUTO_TEST_CASE(ostreamDomain) { + std::stringstream str; + str << testDomain; + BOOST_REQUIRE_EQUAL("::test::domain", str.str()); +} + BOOST_AUTO_TEST_CASE(priority_filtering) { auto w = new TestLogWriter(WARNING); auto e = new TestLogWriter(ERR); @@ -154,7 +177,7 @@ BOOST_AUTO_TEST_CASE(formatter_plain) log->message(DEBUG, "plain message."); BOOST_REQUIRE_EQUAL(1, d->msgs.size()); BOOST_REQUIRE_EQUAL("plain message.", d->msgs.front().message); - BOOST_REQUIRE_EQUAL("test.domain", d->msgs.front().domain); + BOOST_REQUIRE_EQUAL(testDomain, d->msgs.front().domain); } BOOST_AUTO_TEST_CASE(formatter_libc) @@ -164,7 +187,7 @@ BOOST_AUTO_TEST_CASE(formatter_libc) log->messagef(DEBUG, "plain %s.", "message"); BOOST_REQUIRE_EQUAL(1, d->msgs.size()); BOOST_REQUIRE_EQUAL("plain message.", d->msgs.front().message); - BOOST_REQUIRE_EQUAL("test.domain", d->msgs.front().domain); + BOOST_REQUIRE_EQUAL(testDomain, d->msgs.front().domain); } BOOST_AUTO_TEST_CASE(formatter_boost_format) @@ -174,7 +197,7 @@ BOOST_AUTO_TEST_CASE(formatter_boost_format) log->messagebf(DEBUG, "plain %s", std::string("message")); BOOST_REQUIRE_EQUAL(1, d->msgs.size()); BOOST_REQUIRE_EQUAL("plain message", d->msgs.front().message); - BOOST_REQUIRE_EQUAL("test.domain", d->msgs.front().domain); + BOOST_REQUIRE_EQUAL(testDomain, d->msgs.front().domain); } AdHocFormatter(Plain, "plain %?."); @@ -185,15 +208,15 @@ BOOST_AUTO_TEST_CASE(formatter_adhoc_compiletime) log->messagectf<Plain>(DEBUG, "message"); BOOST_REQUIRE_EQUAL(1, d->msgs.size()); BOOST_REQUIRE_EQUAL("plain message.", d->msgs.front().message); - BOOST_REQUIRE_EQUAL("test.domain", d->msgs.front().domain); + BOOST_REQUIRE_EQUAL(testDomain, 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_REQUIRE(!l->level(test)); + BOOST_REQUIRE(!l->level(testDomain)); BOOST_REQUIRE(!l->lowestLevel()); } @@ -201,8 +224,8 @@ 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_REQUIRE_EQUAL(ERR, *l->level(test)); + BOOST_REQUIRE_EQUAL(ERR, *l->level(testDomain)); BOOST_REQUIRE(l->lowestLevel()); BOOST_REQUIRE_EQUAL(ERR, *l->lowestLevel()); } @@ -211,8 +234,8 @@ 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_REQUIRE_EQUAL(WARNING, *l->level(test)); + BOOST_REQUIRE_EQUAL(WARNING, *l->level(testDomain)); BOOST_REQUIRE(l->lowestLevel()); BOOST_REQUIRE_EQUAL(WARNING, *l->lowestLevel()); } @@ -226,10 +249,10 @@ BOOST_AUTO_TEST_CASE( domains_fromProperties ) 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_REQUIRE_EQUAL(WARNING, *l->level(test)); + BOOST_REQUIRE_EQUAL(WARNING, *l->level(other)); + BOOST_REQUIRE_EQUAL(EMERG, *l->level(testDomain)); + BOOST_REQUIRE_EQUAL(DEBUG, *l->level(testDebug)); BOOST_REQUIRE(l->lowestLevel()); BOOST_REQUIRE_EQUAL(DEBUG, *l->lowestLevel()); } @@ -241,8 +264,8 @@ BOOST_AUTO_TEST_CASE( domains_fromProperties_noDefault ) 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_REQUIRE_EQUAL(EMERG, *l->level(testDomain)); + BOOST_REQUIRE_EQUAL(DEBUG, *l->level(testDebug)); BOOST_REQUIRE(l->lowestLevel()); BOOST_REQUIRE_EQUAL(DEBUG, *l->lowestLevel()); } @@ -253,10 +276,10 @@ BOOST_AUTO_TEST_CASE( domains_fromProperties_onlyDefault ) 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_REQUIRE_EQUAL(INFO, *l->level(test)); + BOOST_REQUIRE_EQUAL(INFO, *l->level(other)); + BOOST_REQUIRE_EQUAL(INFO, *l->level(testDomain)); + BOOST_REQUIRE_EQUAL(INFO, *l->level(testDebug)); BOOST_REQUIRE(l->lowestLevel()); BOOST_REQUIRE_EQUAL(INFO, *l->lowestLevel()); } @@ -289,7 +312,7 @@ BOOST_AUTO_TEST_CASE( getLogger ) this->start("test", ic, {}); auto logger = LOGMANAGER()->getLogger("test.domain"); BOOST_REQUIRE(logger); - BOOST_REQUIRE_EQUAL("test.domain", logger->getDomain()); + BOOST_REQUIRE_EQUAL(testDomain, logger->getDomain()); this->stop(); ic->destroy(); } @@ -298,7 +321,8 @@ BOOST_AUTO_TEST_CASE( getLoggerForType ) { auto logger = LOGMANAGER()->getLogger<IceTray::Service>(); BOOST_REQUIRE(logger); - BOOST_REQUIRE_EQUAL("IceTray::Service", logger->getDomain()); + Domain expected = {"IceTray", "Service"}; + BOOST_REQUIRE_EQUAL(expected, logger->getDomain()); } BOOST_AUTO_TEST_SUITE_END(); @@ -307,6 +331,55 @@ BOOST_AUTO_TEST_CASE( console ) { IceTray::Logging::LogWriterPtr lwp = IceTray::Logging::LogWriterFactory::createNew("ConsoleLogWriter", NULL); - lwp->message(DEBUG, "some.domain", "some message"); + lwp->message(DEBUG, testDomain, "some message"); +} + +BOOST_AUTO_TEST_CASE( consoleNoWidth ) +{ + std::stringstream str; + ConsoleLogWriter::writeStream(str, -1, DEBUG, testDomain, "message"); + BOOST_REQUIRE_EQUAL("DEBUG: test.domain: message\n", str.str()); +} + +BOOST_AUTO_TEST_CASE( consoleWidthJustRight ) +{ + std::stringstream str; + ConsoleLogWriter::writeStream(str, 11, DEBUG, testDomain, "message"); + BOOST_REQUIRE_EQUAL("DEBUG: test.domain: message\n", str.str()); +} + +BOOST_AUTO_TEST_CASE( consoleWidthSmall ) +{ + std::stringstream str; + ConsoleLogWriter::writeStream(str, 10, DEBUG, testDomain, "message"); + BOOST_REQUIRE_EQUAL("DEBUG: t.domain: message\n", str.str()); +} + +BOOST_AUTO_TEST_CASE( consoleWidthTiny ) +{ + std::stringstream str; + ConsoleLogWriter::writeStream(str, 8, DEBUG, testDomain, "message"); + BOOST_REQUIRE_EQUAL("DEBUG: t.domain: message\n", str.str()); +} + +BOOST_AUTO_TEST_CASE( consoleWidthTooTiny ) +{ + std::stringstream str; + ConsoleLogWriter::writeStream(str, 7, DEBUG, testDomain, "message"); + BOOST_REQUIRE_EQUAL("DEBUG: t.d: message\n", str.str()); +} + +BOOST_AUTO_TEST_CASE( consoleWidthOverflow ) +{ + std::stringstream str; + ConsoleLogWriter::writeStream(str, 1, DEBUG, testDomain, "message"); + BOOST_REQUIRE_EQUAL("DEBUG: t.d: message\n", str.str()); +} + +BOOST_AUTO_TEST_CASE( consoleNoDomain ) +{ + std::stringstream str; + ConsoleLogWriter::writeStream(str, 0, DEBUG, {}, "message"); + BOOST_REQUIRE_EQUAL("DEBUG: : message\n", str.str()); } |