/** * @brief LogDispatcher implementation for asynchronous pipeline logging. * * LogDispatcher drains LogEntry items from a BoundedChannel and forwards them * to spdlog for final output. */ #include "services/logging/log_dispatcher.h" #include #include #include "concurrency/bounded_channel.h" #include "services/logging/log_entry.h" namespace { [[nodiscard]] constexpr std::string_view PipelinePhaseToString( PipelinePhase phase) { switch (phase) { case PipelinePhase::Startup: return "Startup"; case PipelinePhase::UserGeneration: return "User Generation"; case PipelinePhase::BreweryAndBeerGeneration: return "Brewery & Beer Gen"; case PipelinePhase::CheckinGeneration: return "Checkin Gen"; case PipelinePhase::RatingGeneration: return "Rating Gen"; case PipelinePhase::FollowGeneration: return "Follow Gen"; case PipelinePhase::Teardown: return "Teardown"; } return "Unknown"; } } // namespace LogDispatcher::LogDispatcher(BoundedChannel& channel) : channel_(channel) {} void LogDispatcher::Run() { auto logger = spdlog::default_logger(); while (true) { auto entry = channel_.Receive(); if (!entry.has_value()) { // Channel is closed and drained. break; } const auto& log = entry.value(); logger->log(ToSpdlogLevel(log.level), "{:<20} │ thread: {:016x} │ [{}:{}] │ {}", PipelinePhaseToString(log.phase), std::hash{}(log.thread_id), log.origin.file_name(), log.origin.line(), log.message); } } spdlog::level::level_enum LogDispatcher::ToSpdlogLevel(LogLevel level) { switch (level) { case LogLevel::Debug: return spdlog::level::debug; case LogLevel::Info: return spdlog::level::info; case LogLevel::Warn: return spdlog::level::warn; case LogLevel::Error: return spdlog::level::err; } return spdlog::level::info; }