feat: Use spdlog logger (#2372)

This commit is contained in:
Ayaz Salikhov
2025-08-11 18:04:04 +01:00
committed by GitHub
parent 707427c63a
commit 9420c506ca
29 changed files with 745 additions and 548 deletions

View File

@@ -21,35 +21,27 @@
#include "util/SourceLocation.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/filesystem.hpp>
#include <boost/json.hpp>
#include <boost/json/conversion.hpp>
#include <boost/json/value.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/expressions/filter.hpp>
#include <boost/log/expressions/keyword.hpp>
#include <boost/log/expressions/predicates/channel_severity_filter.hpp>
#include <boost/log/keywords/channel.hpp>
#include <boost/log/keywords/severity.hpp>
#include <boost/log/sinks/unlocked_frontend.hpp>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/formatter_parser.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <optional>
#include <ostream>
#include <memory>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>
// We forward declare spdlog::logger and spdlog::sinks::sink
// to avoid including the spdlog headers in this header file.
namespace spdlog {
class logger;
namespace sinks {
class sink;
} // namespace sinks
} // namespace spdlog
struct BenchmarkLoggingInitializer;
@@ -85,23 +77,6 @@ enum class Severity {
FTL,
};
/** @cond */
// NOLINTBEGIN(readability-identifier-naming)
BOOST_LOG_ATTRIBUTE_KEYWORD(LogSeverity, "Severity", Severity);
BOOST_LOG_ATTRIBUTE_KEYWORD(LogChannel, "Channel", std::string);
// NOLINTEND(readability-identifier-naming)
/** @endcond */
/**
* @brief Custom labels for @ref Severity in log output.
*
* @param stream std::ostream The output stream
* @param sev Severity The severity to output to the ostream
* @return The same ostream we were given
*/
std::ostream&
operator<<(std::ostream& stream, Severity sev);
/**
* @brief A simple thread-safe logger for the channel specified
* in the constructor.
@@ -111,31 +86,25 @@ operator<<(std::ostream& stream, Severity sev);
* severity levels for each channel.
*/
class Logger final {
using LoggerType = boost::log::sources::severity_channel_logger_mt<Severity, std::string>;
mutable LoggerType logger_;
std::shared_ptr<spdlog::logger> logger_;
friend class LogService; // to expose the Pump interface
friend struct ::BenchmarkLoggingInitializer;
/**
* @brief Helper that pumps data into a log record via `operator<<`.
*/
class Pump final {
using PumpOptType = std::optional<boost::log::aux::record_pump<LoggerType>>;
boost::log::record rec_;
PumpOptType pump_ = std::nullopt;
std::shared_ptr<spdlog::logger> logger_;
Severity const severity_;
SourceLocationType const sourceLocation_;
std::ostringstream stream_;
bool const enabled_;
public:
~Pump() = default;
~Pump();
Pump(LoggerType& logger, Severity sev, SourceLocationType const& loc)
: rec_{logger.open_record(boost::log::keywords::severity = sev)}
{
if (rec_) {
pump_.emplace(boost::log::aux::make_record_pump(logger, rec_));
pump_->stream() << boost::log::add_value("SourceLocation", prettyPath(loc));
}
}
Pump(std::shared_ptr<spdlog::logger> logger, Severity sev, SourceLocationType const& loc);
Pump(Pump&&) = delete;
Pump(Pump const&) = delete;
@@ -145,7 +114,7 @@ class Logger final {
operator=(Pump&&) = delete;
/**
* @brief Perfectly forwards any incoming data into the underlying boost::log pump if the pump is available.
* @brief Perfectly forwards any incoming data into the underlying stream if data should be logged.
*
* @tparam T Type of data to pump
* @param data The data to pump
@@ -155,8 +124,8 @@ class Logger final {
[[maybe_unused]] Pump&
operator<<(T&& data)
{
if (pump_)
pump_->stream() << std::forward<T>(data);
if (enabled_)
stream_ << std::forward<T>(data);
return *this;
}
@@ -165,11 +134,11 @@ class Logger final {
*/
operator bool() const
{
return pump_.has_value();
return enabled_;
}
private:
[[nodiscard]] static std::string
[[nodiscard]] static std::string_view
prettyPath(SourceLocationType const& loc, size_t maxDepth = 3);
};
@@ -194,9 +163,7 @@ public:
*
* @param channel The channel this logger will report into.
*/
Logger(std::string channel) : logger_{boost::log::keywords::channel = channel}
{
}
Logger(std::string channel);
Logger(Logger const&) = default;
~Logger() = default;
@@ -261,6 +228,9 @@ public:
*/
[[nodiscard]] Pump
fatal(SourceLocationType const& loc = CURRENT_SRC_LOCATION) const;
private:
Logger(std::shared_ptr<spdlog::logger> logger);
};
/**
@@ -270,8 +240,19 @@ public:
* entrypoint for logging into the `General` channel as well as raising alerts.
*/
class LogService {
static Logger generalLog; /*< Global logger for General channel */
static boost::log::filter filter;
struct Data {
bool isAsync;
Severity severity;
std::vector<std::shared_ptr<spdlog::sinks::sink>> allSinks;
};
friend class Logger;
private:
static Data data;
static std::shared_ptr<spdlog::logger>
registerLogger(std::string const& channel, Severity severity = data.severity);
public:
LogService() = delete;
@@ -285,6 +266,12 @@ public:
[[nodiscard]] static std::expected<void, std::string>
init(config::ClioConfigDefinition const& config);
/**
* @brief Shutdown spdlog to guarantee output is not lost
*/
static void
shutdown();
/**
* @brief Globally accessible General logger at Severity::TRC severity
*
@@ -292,10 +279,7 @@ public:
* @return The pump to use for logging
*/
[[nodiscard]] static Logger::Pump
trace(SourceLocationType const& loc = CURRENT_SRC_LOCATION)
{
return generalLog.trace(loc);
}
trace(SourceLocationType const& loc = CURRENT_SRC_LOCATION);
/**
* @brief Globally accessible General logger at Severity::DBG severity
@@ -304,10 +288,7 @@ public:
* @return The pump to use for logging
*/
[[nodiscard]] static Logger::Pump
debug(SourceLocationType const& loc = CURRENT_SRC_LOCATION)
{
return generalLog.debug(loc);
}
debug(SourceLocationType const& loc = CURRENT_SRC_LOCATION);
/**
* @brief Globally accessible General logger at Severity::NFO severity
@@ -316,10 +297,7 @@ public:
* @return The pump to use for logging
*/
[[nodiscard]] static Logger::Pump
info(SourceLocationType const& loc = CURRENT_SRC_LOCATION)
{
return generalLog.info(loc);
}
info(SourceLocationType const& loc = CURRENT_SRC_LOCATION);
/**
* @brief Globally accessible General logger at Severity::WRN severity
@@ -328,10 +306,7 @@ public:
* @return The pump to use for logging
*/
[[nodiscard]] static Logger::Pump
warn(SourceLocationType const& loc = CURRENT_SRC_LOCATION)
{
return generalLog.warn(loc);
}
warn(SourceLocationType const& loc = CURRENT_SRC_LOCATION);
/**
* @brief Globally accessible General logger at Severity::ERR severity
@@ -340,10 +315,7 @@ public:
* @return The pump to use for logging
*/
[[nodiscard]] static Logger::Pump
error(SourceLocationType const& loc = CURRENT_SRC_LOCATION)
{
return generalLog.error(loc);
}
error(SourceLocationType const& loc = CURRENT_SRC_LOCATION);
/**
* @brief Globally accessible General logger at Severity::FTL severity
@@ -352,10 +324,7 @@ public:
* @return The pump to use for logging
*/
[[nodiscard]] static Logger::Pump
fatal(SourceLocationType const& loc = CURRENT_SRC_LOCATION)
{
return generalLog.fatal(loc);
}
fatal(SourceLocationType const& loc = CURRENT_SRC_LOCATION);
/**
* @brief Whether the LogService is enabled or not
@@ -370,14 +339,14 @@ private:
std::string logDir;
uint32_t rotationSizeMB;
uint32_t dirMaxSizeMB;
uint32_t rotationHours;
uint32_t dirMaxFiles;
};
friend struct ::BenchmarkLoggingInitializer;
static void
initFileLogging(FileLoggingParams const& params, std::string const& format);
[[nodiscard]]
static std::shared_ptr<spdlog::sinks::sink>
createFileSink(FileLoggingParams const& params);
};
}; // namespace util