diff --git a/libuavcan/include/uavcan/protocol/logger.hpp b/libuavcan/include/uavcan/protocol/logger.hpp index 7f82687e0e..b6267dbcad 100644 --- a/libuavcan/include/uavcan/protocol/logger.hpp +++ b/libuavcan/include/uavcan/protocol/logger.hpp @@ -19,7 +19,18 @@ namespace uavcan class ILogSink { public: + typedef typename StorageType::Type LogLevel; + virtual ~ILogSink() { } + + /** + * Logger will not sink messages with level lower than returned by this method. + */ + virtual LogLevel getLogLevel() const = 0; + + /** + * Logger will call this method for every log message with level not less than the current level of this sink. + */ virtual void log(const protocol::debug::LogMessage& message) = 0; }; @@ -27,7 +38,7 @@ public: class Logger { public: - typedef typename StorageType::Type LogLevel; + typedef ILogSink::LogLevel LogLevel; static const LogLevel LevelAboveAll = (protocol::debug::LogLevel::FieldTypes::value::BitLen << 1) - 1; @@ -39,6 +50,8 @@ private: LogLevel level_; ILogSink* external_sink_; + LogLevel getExternalSinkLevel() const; + public: Logger(INode& node) : logmsg_pub_(node) @@ -65,7 +78,7 @@ public: template int log(LogLevel level, const char* source, const char* format, Args... args) { - if (level >= level_) + if (level >= level_ || level >= getExternalSinkLevel()) { msg_buf_.level.value = level; msg_buf_.source = source; @@ -78,25 +91,25 @@ public: } template - int logDebug(const char* source, const char* format, Args... args) + inline int logDebug(const char* source, const char* format, Args... args) { return log(protocol::debug::LogLevel::DEBUG, source, format, args...); } template - int logInfo(const char* source, const char* format, Args... args) + inline int logInfo(const char* source, const char* format, Args... args) { return log(protocol::debug::LogLevel::INFO, source, format, args...); } template - int logWarning(const char* source, const char* format, Args... args) + inline int logWarning(const char* source, const char* format, Args... args) { return log(protocol::debug::LogLevel::WARNING, source, format, args...); } template - int logError(const char* source, const char* format, Args... args) + inline int logError(const char* source, const char* format, Args... args) { return log(protocol::debug::LogLevel::ERROR, source, format, args...); } @@ -105,7 +118,7 @@ public: int log(LogLevel level, const char* source, const char* text) { - if (level >= level_) + if (level >= level_ || level >= getExternalSinkLevel()) { msg_buf_.level.value = level; msg_buf_.source = source; diff --git a/libuavcan/src/protocol/logger.cpp b/libuavcan/src/protocol/logger.cpp index ce63cabf47..afcf655933 100644 --- a/libuavcan/src/protocol/logger.cpp +++ b/libuavcan/src/protocol/logger.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2014 Pavel Kirienko */ +#include #include namespace uavcan @@ -9,18 +10,23 @@ namespace uavcan const Logger::LogLevel Logger::LevelAboveAll; +Logger::LogLevel Logger::getExternalSinkLevel() const +{ + return (external_sink_ == NULL) ? LevelAboveAll : external_sink_->getLogLevel(); +} + int Logger::log(const protocol::debug::LogMessage& message) { + int retval = 0; + if (message.level.value >= getExternalSinkLevel()) + { + external_sink_->log(message); + } if (message.level.value >= level_) { - const int res = logmsg_pub_.broadcast(message); - if (external_sink_) - { - external_sink_->log(message); - } - return res; + retval = logmsg_pub_.broadcast(message); } - return 0; + return retval; } } diff --git a/libuavcan/test/protocol/logger.cpp b/libuavcan/test/protocol/logger.cpp index d11ec22b65..9b8c00466d 100644 --- a/libuavcan/test/protocol/logger.cpp +++ b/libuavcan/test/protocol/logger.cpp @@ -10,6 +10,13 @@ struct LogSink : public uavcan::ILogSink { std::queue msgs; + LogLevel level; + + LogSink() + : level(uavcan::protocol::debug::LogLevel::ERROR) + { } + + LogLevel getLogLevel() const { return level; } void log(const uavcan::protocol::debug::LogMessage& message) { @@ -31,6 +38,11 @@ struct LogSink : public uavcan::ILogSink bool popMatchByLevelAndText(int level, const std::string& source, const std::string& text) { + if (msgs.empty()) + { + std::cout << "LogSink is empty" << std::endl; + return false; + } const uavcan::protocol::debug::LogMessage m = pop(); return level == m.level.value && @@ -65,7 +77,14 @@ TEST(Logger, Basic) SubscriberWithCollector log_sub(nodes.b); ASSERT_LE(0, log_sub.start()); + // Sink test ASSERT_EQ(0, logger.logDebug("foo", "Debug (ignored due to low logging level)")); + ASSERT_TRUE(sink.msgs.empty()); + + sink.level = uavcan::protocol::debug::LogLevel::DEBUG; + ASSERT_EQ(0, logger.logDebug("foo", "Debug (sink only)")); + ASSERT_TRUE(sink.popMatchByLevelAndText(uavcan::protocol::debug::LogLevel::DEBUG, "foo", "Debug (sink only)")); + ASSERT_LE(0, logger.logError("foo", "Error")); nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(2)); ASSERT_EQ(log_sub.collector.msg->level.value, uavcan::protocol::debug::LogLevel::ERROR);