summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-02-03 19:17:46 +0100
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2022-06-06 15:09:42 +0300
commit575703894624306950c0540182afc48ba3732f8c (patch)
tree79970d8e30a48c3455cd80399690bb0993b3f610 /src
parent7ee7dc3369ebf26d142b6352cb3d309f48600433 (diff)
libcamera: base: log: Add coloring to the log output
Extend the logger to support coloring messages. The log level is colorized with per-level colors, and the category with a fixed color. This makes the log output more readable. Coloring is enabled by default when logging to std::cerr, and can be disabled by setting the LIBCAMERA_LOG_NO_COLOR environment variable. When logging to a file with LIBCAMERA_LOG_FILE, coloring is disabled. It can be enabled for file logging using the logSetFile() function. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/base/log.cpp110
1 files changed, 86 insertions, 24 deletions
diff --git a/src/libcamera/base/log.cpp b/src/libcamera/base/log.cpp
index 26f14207..eefdda4b 100644
--- a/src/libcamera/base/log.cpp
+++ b/src/libcamera/base/log.cpp
@@ -104,8 +104,8 @@ static const char *log_severity_name(LogSeverity severity)
class LogOutput
{
public:
- LogOutput(const char *path);
- LogOutput(std::ostream *stream);
+ LogOutput(const char *path, bool color);
+ LogOutput(std::ostream *stream, bool color);
LogOutput();
~LogOutput();
@@ -119,14 +119,16 @@ private:
std::ostream *stream_;
LoggingTarget target_;
+ bool color_;
};
/**
* \brief Construct a log output based on a file
* \param[in] path Full path to log file
+ * \param[in] color True to output colored messages
*/
-LogOutput::LogOutput(const char *path)
- : target_(LoggingTargetFile)
+LogOutput::LogOutput(const char *path, bool color)
+ : target_(LoggingTargetFile), color_(color)
{
stream_ = new std::ofstream(path);
}
@@ -134,9 +136,10 @@ LogOutput::LogOutput(const char *path)
/**
* \brief Construct a log output based on a stream
* \param[in] stream Stream to send log output to
+ * \param[in] color True to output colored messages
*/
-LogOutput::LogOutput(std::ostream *stream)
- : stream_(stream), target_(LoggingTargetStream)
+LogOutput::LogOutput(std::ostream *stream, bool color)
+ : stream_(stream), target_(LoggingTargetStream), color_(color)
{
}
@@ -144,7 +147,7 @@ LogOutput::LogOutput(std::ostream *stream)
* \brief Construct a log output to syslog
*/
LogOutput::LogOutput()
- : stream_(nullptr), target_(LoggingTargetSyslog)
+ : stream_(nullptr), target_(LoggingTargetSyslog), color_(false)
{
openlog("libcamera", LOG_PID, 0);
}
@@ -179,28 +182,66 @@ bool LogOutput::isValid() const
}
}
+namespace {
+
+/*
+ * For more information about ANSI escape codes, see
+ * https://en.wikipedia.org/wiki/ANSI_escape_code#Colors.
+ */
+constexpr const char *kColorReset = "\033[0m";
+constexpr const char *kColorBrightRed = "\033[1;31m";
+constexpr const char *kColorBrightGreen = "\033[1;32m";
+constexpr const char *kColorBrightYellow = "\033[1;33m";
+constexpr const char *kColorBrightBlue = "\033[1;34m";
+constexpr const char *kColorBrightMagenta = "\033[1;35m";
+constexpr const char *kColorBrightCyan = "\033[1;36m";
+constexpr const char *kColorBrightWhite = "\033[1;37m";
+
+} /* namespace */
+
/**
* \brief Write message to log output
* \param[in] msg Message to write
*/
void LogOutput::write(const LogMessage &msg)
{
+ static const char *const severityColors[] = {
+ kColorBrightCyan,
+ kColorBrightGreen,
+ kColorBrightYellow,
+ kColorBrightRed,
+ kColorBrightMagenta,
+ };
+
+ const char *categoryColor = color_ ? kColorBrightWhite : "";
+ const char *fileColor = color_ ? kColorBrightBlue : "";
+ const char *resetColor = color_ ? kColorReset : "";
+ const char *severityColor = "";
+ LogSeverity severity = msg.severity();
std::string str;
+ if (color_) {
+ if (static_cast<unsigned int>(severity) < std::size(severityColors))
+ severityColor = severityColors[severity];
+ else
+ severityColor = kColorBrightWhite;
+ }
+
switch (target_) {
case LoggingTargetSyslog:
- str = std::string(log_severity_name(msg.severity())) + " "
+ str = std::string(log_severity_name(severity)) + " "
+ msg.category().name() + " " + msg.fileInfo() + " "
+ msg.msg();
- writeSyslog(msg.severity(), str);
+ writeSyslog(severity, str);
break;
case LoggingTargetStream:
case LoggingTargetFile:
str = "[" + utils::time_point_to_string(msg.timestamp()) + "] ["
+ std::to_string(Thread::currentId()) + "] "
- + log_severity_name(msg.severity()) + " "
- + msg.category().name() + " " + msg.fileInfo() + " "
- + msg.msg();
+ + severityColor + log_severity_name(severity) + " "
+ + categoryColor + msg.category().name() + " "
+ + fileColor + msg.fileInfo() + " "
+ + resetColor + msg.msg();
writeStream(str);
break;
default:
@@ -253,8 +294,8 @@ public:
void write(const LogMessage &msg);
void backtrace();
- int logSetFile(const char *path);
- int logSetStream(std::ostream *stream);
+ int logSetFile(const char *path, bool color);
+ int logSetStream(std::ostream *stream, bool color);
int logSetTarget(LoggingTarget target);
void logSetLevel(const char *category, const char *level);
@@ -298,35 +339,47 @@ bool Logger::destroyed_ = false;
/**
* \brief Direct logging to a file
* \param[in] path Full path to the log file
+ * \param[in] color True to output colored messages
*
* This function directs the log output to the file identified by \a path. The
* previous log target, if any, is closed, and all new log messages will be
* written to the new log file.
*
+ * \a color controls whether or not the messages will be colored with standard
+ * ANSI escape codes. This is done regardless of whether \a path refers to a
+ * standard file or a TTY, the caller is responsible for disabling coloring when
+ * not suitable for the log target.
+ *
* If the function returns an error, the log target is not changed.
*
* \return Zero on success, or a negative error code otherwise
*/
-int logSetFile(const char *path)
+int logSetFile(const char *path, bool color)
{
- return Logger::instance()->logSetFile(path);
+ return Logger::instance()->logSetFile(path, color);
}
/**
* \brief Direct logging to a stream
* \param[in] stream Stream to send log output to
+ * \param[in] color True to output colored messages
*
* This function directs the log output to \a stream. The previous log target,
* if any, is closed, and all new log messages will be written to the new log
* stream.
*
+ * \a color controls whether or not the messages will be colored with standard
+ * ANSI escape codes. This is done regardless of whether \a stream refers to a
+ * standard file or a TTY, the caller is responsible for disabling coloring when
+ * not suitable for the log target.
+ *
* If the function returns an error, the log file is not changed
*
* \return Zero on success, or a negative error code otherwise.
*/
-int logSetStream(std::ostream *stream)
+int logSetStream(std::ostream *stream, bool color)
{
- return Logger::instance()->logSetStream(stream);
+ return Logger::instance()->logSetStream(stream, color);
}
/**
@@ -437,14 +490,16 @@ void Logger::backtrace()
/**
* \brief Set the log file
* \param[in] path Full path to the log file
+ * \param[in] color True to output colored messages
*
* \sa libcamera::logSetFile()
*
* \return Zero on success, or a negative error code otherwise.
*/
-int Logger::logSetFile(const char *path)
+int Logger::logSetFile(const char *path, bool color)
{
- std::shared_ptr<LogOutput> output = std::make_shared<LogOutput>(path);
+ std::shared_ptr<LogOutput> output =
+ std::make_shared<LogOutput>(path, color);
if (!output->isValid())
return -EINVAL;
@@ -455,14 +510,16 @@ int Logger::logSetFile(const char *path)
/**
* \brief Set the log stream
* \param[in] stream Stream to send log output to
+ * \param[in] color True to output colored messages
*
* \sa libcamera::logSetStream()
*
* \return Zero on success, or a negative error code otherwise.
*/
-int Logger::logSetStream(std::ostream *stream)
+int Logger::logSetStream(std::ostream *stream, bool color)
{
- std::shared_ptr<LogOutput> output = std::make_shared<LogOutput>(stream);
+ std::shared_ptr<LogOutput> output =
+ std::make_shared<LogOutput>(stream, color);
std::atomic_store(&output_, output);
return 0;
}
@@ -514,10 +571,15 @@ void Logger::logSetLevel(const char *category, const char *level)
/**
* \brief Construct a logger
+ *
+ * If the environment variable is not set, log to std::cerr. The log messages
+ * are then colored by default. This can be overridden by setting the
+ * LIBCAMERA_LOG_NO_COLOR environment variable to disable coloring.
*/
Logger::Logger()
{
- logSetStream(&std::cerr);
+ bool color = !utils::secure_getenv("LIBCAMERA_LOG_NO_COLOR");
+ logSetStream(&std::cerr, color);
parseLogFile();
parseLogLevels();
@@ -543,7 +605,7 @@ void Logger::parseLogFile()
return;
}
- logSetFile(file);
+ logSetFile(file, false);
}
/**