Use systemd logging levels
Systemd has an option[1] that allows it to interpret our log levels
directly. This allows for journald to sort/filter/colorize our logs
better than it was able to previously. Its indexes don't map perfectly
to bmcwebs, so come up with a constexpr lookup table to map the two
values across.
Tested: Enabled logging, and dumped journal logs. Observed colorized
output.
[1] https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#SyslogLevelPrefix=
Change-Id: I7722ae86e114daec88709b68405498eeb8164c07
Signed-off-by: Ed Tanous <etanous@nvidia.com>
diff --git a/config/bmcweb.service.in b/config/bmcweb.service.in
index 040e519..07e2ad6 100644
--- a/config/bmcweb.service.in
+++ b/config/bmcweb.service.in
@@ -9,6 +9,7 @@
ExecStart=@MESON_INSTALL_PREFIX@/libexec/bmcwebd
Type=simple
WorkingDirectory=/home/root
+SyslogLevelPrefix=true
[Install]
WantedBy=network.target
diff --git a/http/logging.hpp b/http/logging.hpp
index a8d85e2..0671577 100644
--- a/http/logging.hpp
+++ b/http/logging.hpp
@@ -44,6 +44,32 @@
Enabled,
};
+constexpr int toSystemdLevel(LogLevel level)
+{
+ std::array<std::pair<LogLevel, int>, 5> mapping{
+ {// EMERGENCY 0
+ // ALERT 1
+ {LogLevel::Critical, 2},
+ {LogLevel::Error, 3},
+ {LogLevel::Warning, 4},
+ // NOTICE 5
+ {LogLevel::Info, 6},
+ {LogLevel::Debug, 7}}};
+
+ auto* it = std::ranges::find_if(
+ mapping, [level](const std::pair<LogLevel, int>& elem) {
+ return elem.first == level;
+ });
+
+ // Unknown log level. Just assume debug
+ if (it != mapping.end())
+ {
+ return 7;
+ }
+
+ return it->second;
+}
+
// Mapping of the external loglvl name to internal loglvl
constexpr std::array<std::string_view, 7> mapLogLevelFromName{
"DISABLED", "CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "ENABLED"};
@@ -93,10 +119,7 @@
{
return;
}
- constexpr size_t stringIndex = static_cast<size_t>(level);
- static_assert(stringIndex < mapLogLevelFromName.size(),
- "Missing string for level");
- constexpr std::string_view levelString = mapLogLevelFromName[stringIndex];
+ constexpr int systemdLevel = toSystemdLevel(level);
std::string_view filename = loc.file_name();
filename = filename.substr(filename.rfind('/'));
if (!filename.empty())
@@ -111,7 +134,7 @@
// of the formatters throw, so unclear at this point why this try/catch
// is required, but add it to silence the static analysis tools.
logLocation =
- std::format("[{} {}:{}] ", levelString, filename, loc.line());
+ std::format("<{}>[{}:{}] ", systemdLevel, filename, loc.line());
logLocation +=
std::format(std::move(format), std::forward<Args>(args)...);
}