From patchwork Mon Jan 21 00:59:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 283 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AFA3F60C82 for ; Mon, 21 Jan 2019 01:59:35 +0100 (CET) Received: from pendragon.bb.dnainternet.fi (dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4E2B8D80 for ; Mon, 21 Jan 2019 01:59:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1548032375; bh=mEuK0o21xBH6Uqfcuz+k921mCyRQmJY5dm7UkPI1dl8=; h=From:To:Subject:Date:In-Reply-To:References:From; b=kDtY3MpO/0Euag3EzHI+eHspAxDXsLBzySJRWho9izCWzv8yZ4+HJl9IkImmz+ZFm JTkOXzzyB/exgjJ1oJ85M8qhWYjoDwbf+SDI3l2b+nVqyp1YHXq+k2fNFqwpezQafj iCQB4TNkpEPysd6d+3Bx+OMNyghp9n+BD3teZyGQ= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 21 Jan 2019 02:59:27 +0200 Message-Id: <20190121005930.10112-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20190121005930.10112-1-laurent.pinchart@ideasonboard.com> References: <20190121005930.10112-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 3/6] libcamera: log: Add log categories X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 21 Jan 2019 00:59:36 -0000 Log categories are used to group log messages by topic. Introduce support for categories with a new LOGC() macro. Support for configuring log level per category will be introduced in a subsequent commit. Signed-off-by: Laurent Pinchart --- src/libcamera/include/log.h | 45 +++++++- src/libcamera/log.cpp | 217 ++++++++++++++++++++++++++++++------ 2 files changed, 222 insertions(+), 40 deletions(-) diff --git a/src/libcamera/include/log.h b/src/libcamera/include/log.h index cc3f9404a3d4..c7644291724d 100644 --- a/src/libcamera/include/log.h +++ b/src/libcamera/include/log.h @@ -19,26 +19,63 @@ enum LogSeverity { LogFatal, }; +class LogCategory +{ +public: + explicit LogCategory(const char *name); + ~LogCategory(); + + const char *name() const { return name_; } + LogSeverity severity() const { return severity_; } + void setSeverity(LogSeverity severity); + + static const LogCategory &defaultCategory(); + +private: + const char *name_; + LogSeverity severity_; +}; + +#define LOG_CATEGORY(name) logCategory##name + +#define LOG_DECLARE_CATEGORY(name) \ +extern const LogCategory &LOG_CATEGORY(name)(); + +#define LOG_DEFINE_CATEGORY(name) \ +const LogCategory &LOG_CATEGORY(name)() \ +{ \ + static LogCategory category(#name); \ + return category; \ +} + class LogMessage { public: LogMessage(const char *fileName, unsigned int line, LogSeverity severity); + LogMessage(const char *fileName, unsigned int line, + const LogCategory &category, LogSeverity severity); LogMessage(const LogMessage &) = delete; ~LogMessage(); - std::ostream &stream() { return msgStream; } + std::ostream &stream() { return msgStream_; } private: - std::ostringstream msgStream; + void init(const char *fileName, unsigned int line); + + std::ostringstream msgStream_; + const LogCategory &category_; LogSeverity severity_; }; -#define LOG(severity) LogMessage(__FILE__, __LINE__, Log##severity).stream() +#define LOG(severity) \ + LogMessage(__FILE__, __LINE__, Log##severity).stream() +#define LOGC(category, severity) \ + LogMessage(__FILE__, __LINE__, LOG_CATEGORY(category)(), Log##severity).stream() #ifndef NDEBUG #define ASSERT(condition) static_cast(({ \ - if (!(condition)) \ + if (!(condition)) \ LOG(Fatal) << "assertion \"" #condition "\" failed"; \ })) #else diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp index 74cba383363d..8f3d1c181245 100644 --- a/src/libcamera/log.cpp +++ b/src/libcamera/log.cpp @@ -37,32 +37,64 @@ namespace libcamera { */ /** - * \def LOG(severity) - * \brief Log a message + * \class LogCategory + * \brief A category of log message * - * Return an std::ostream reference to which a message can be logged using the - * iostream API. The \a severity controls whether the message is printed or - * dropped, depending on the global log level. - * - * If the severity is set to Fatal, execution is aborted and the program - * terminates immediately after printing the message. + * The LogCategory class represents a category of log messages, related to an + * area of the library. It groups all messages belonging to the same category, + * and is used to control the log level per group. */ /** - * \def ASSERT(condition) - * \brief Abort program execution if assertion fails + * \brief Construct a log category + * \param[in] name The category name + */ +LogCategory::LogCategory(const char *name) + : name_(name), severity_(LogSeverity::LogInfo) +{ +} + +LogCategory::~LogCategory() +{ +} + +/** + * \fn LogCategory::name() + * \brief Retrieve the log category name + * \return The log category name + */ + +/** + * \fn LogCategory::severity() + * \brief Retrieve the severity of the log category + * \sa setSeverity() + * \return Return the severity of the log category + */ + +/** + * \brief Set the severity of the log category * - * If \a condition is false, ASSERT() logs an error message with the Fatal log - * level and aborts program execution. + * Messages of severity higher than or equal to the severity of the log category + * are printed, other messages are discarded. + */ +void LogCategory::setSeverity(LogSeverity severity) +{ + severity_ = severity; +} + +/** + * \brief Retrieve the default log category * - * If the macro NDEBUG is defined before including log.h, ASSERT() generates no - * code. + * The default log category is named "default" and is used by the LOG() macro + * when no log category is specified. * - * Using conditions that have side effects with ASSERT() is not recommended, as - * these effects would depend on whether NDEBUG is defined or not. Similarly, - * ASSERT() should not be used to check for errors that can occur under normal - * conditions as those checks would then be removed when compiling with NDEBUG. + * \return A pointer to the default log category */ +const LogCategory &LogCategory::defaultCategory() +{ + static LogCategory category("default"); + return category; +} static const char *log_severity_name(LogSeverity severity) { @@ -90,10 +122,11 @@ static const char *log_severity_name(LogSeverity severity) */ /** - * \param fileName The file name where the message is logged from - * \param line The line number where the message is logged from - * \param severity The log message severity, controlling how the message will be - * displayed + * \brief Construct a log message for the default category + * \param[in] fileName The file name where the message is logged from + * \param[in] line The line number where the message is logged from + * \param[in] severity The log message severity, controlling how the message + * will be displayed * * Create a log message pertaining to line \a line of file \a fileName. The * \a severity argument sets the message severity to control whether it will be @@ -101,29 +134,57 @@ static const char *log_severity_name(LogSeverity severity) */ LogMessage::LogMessage(const char *fileName, unsigned int line, LogSeverity severity) - : severity_(severity) + : category_(LogCategory::defaultCategory()), severity_(severity) +{ + init(fileName, line); +} + +/** + * \brief Construct a log message for a given category + * \param[in] fileName The file name where the message is logged from + * \param[in] line The line number where the message is logged from + * \param[in] category The log message category, controlling how the message + * will be displayed + * \param[in] severity The log message severity, controlling how the message + * will be displayed + * + * Create a log message pertaining to line \a line of file \a fileName. The + * \a severity argument sets the message severity to control whether it will be + * output or dropped. + */ +LogMessage::LogMessage(const char *fileName, unsigned int line, + const LogCategory &category, LogSeverity severity) + : category_(category), severity_(severity) +{ + init(fileName, line); +} + +void LogMessage::init(const char *fileName, unsigned int line) { /* Log the timestamp, severity and file information. */ struct timespec timestamp; clock_gettime(CLOCK_MONOTONIC, ×tamp); - msgStream.fill('0'); - msgStream << "[" << timestamp.tv_sec / (60 * 60) << ":" - << std::setw(2) << (timestamp.tv_sec / 60) % 60 << ":" - << std::setw(2) << timestamp.tv_sec % 60 << "." - << std::setw(9) << timestamp.tv_nsec << "]"; - msgStream.fill(' '); - - msgStream << " " << log_severity_name(severity); - msgStream << " " << basename(fileName) << ":" << line << " "; + msgStream_.fill('0'); + msgStream_ << "[" << timestamp.tv_sec / (60 * 60) << ":" + << std::setw(2) << (timestamp.tv_sec / 60) % 60 << ":" + << std::setw(2) << timestamp.tv_sec % 60 << "." + << std::setw(9) << timestamp.tv_nsec << "]"; + msgStream_.fill(' '); + + msgStream_ << " " << log_severity_name(severity_); + msgStream_ << " " << category_.name(); + msgStream_ << " " << basename(fileName) << ":" << line << " "; } LogMessage::~LogMessage() { - msgStream << std::endl; + msgStream_ << std::endl; - std::string msg(msgStream.str()); - fwrite(msg.data(), msg.size(), 1, stderr); - fflush(stderr); + if (severity_ >= category_.severity()) { + std::string msg(msgStream_.str()); + fwrite(msg.data(), msg.size(), 1, stderr); + fflush(stderr); + } if (severity_ == LogSeverity::LogFatal) std::abort(); @@ -139,4 +200,88 @@ LogMessage::~LogMessage() * \return A reference to the log message stream */ +/** + * \def LOG_CATEGORY(name) + * \brief Name of the log category symbol for a category name + */ + +/** + * \def LOG_DECLARE_CATEGORY(name) + * \brief Declare a category of log messages + * + * This macro is used to declare a log category defined in another compilation + * unit by the LOG_DEFINE_CATEGORY() macro. + * + * The LOG_DECLARE_CATEGORY() macro must be used in the libcamera namespace. + * + * \sa LogCategory + */ + +/** + * \def LOG_DECLARE_CATEGORY(name) + * \brief Declare a category of log messages + * + * This macro is used to declare a log category defined in another compilation + * unit by the LOG_DEFINE_CATEGORY() macro. + * + * The LOG_DECLARE_CATEGORY() macro must be used in the libcamera namespace. + * + * \sa LogCategory + */ + +/** + * \def LOG_DEFINE_CATEGORY(name) + * \brief Define a category of log messages + * + * This macro is used to define a log category that can then be used with the + * LOGC() macro. Category names shall be unique, if a category is shared between + * compilation units, it shall be defined in one compilation unit only and + * declared with LOG_DECLARE_CATEGORY() in the other compilation units. + * + * The LOG_DEFINE_CATEGORY() macro must be used in the libcamera namespace. + * + * \sa LogCategory + */ + +/** + * \def LOG(severity) + * \brief Log a message + * + * Return an std::ostream reference to which a message can be logged using the + * iostream API. The \a severity controls whether the message is printed or + * discarded, depending on the global log level. + * + * If the severity is set to Fatal, execution is aborted and the program + * terminates immediately after printing the message. + */ + +/** + * \def LOGC(category, severity) + * \brief Log a message with a category + * + * Return an std::ostream reference to which a message can be logged using the + * iostream API. The \a category and \a severity controls whether the message is + * printed or discarded, depending on if the \a category is enabled and on the + * log level for the \a category. + * + * If the severity is set to Fatal, execution is aborted and the program + * terminates immediately after printing the message. + */ + +/** + * \def ASSERT(condition) + * \brief Abort program execution if assertion fails + * + * If \a condition is false, ASSERT() logs an error message with the Fatal log + * level and aborts program execution. + * + * If the macro NDEBUG is defined before including log.h, ASSERT() generates no + * code. + * + * Using conditions that have side effects with ASSERT() is not recommended, as + * these effects would depend on whether NDEBUG is defined or not. Similarly, + * ASSERT() should not be used to check for errors that can occur under normal + * conditions as those checks would then be removed when compiling with NDEBUG. + */ + } /* namespace libcamera */