This commit is contained in:
Aaron Po
2026-05-15 14:11:34 -04:00
parent e6a20324e4
commit c58e4c1986
7 changed files with 24 additions and 44 deletions

View File

@@ -53,11 +53,6 @@ struct LogEntry {
std::chrono::system_clock::time_point timestamp = std::chrono::system_clock::time_point timestamp =
std::chrono::system_clock::now(); std::chrono::system_clock::now();
std::thread::id calling_thread_id;
/// @brief The thread id of the logger
std::thread::id logging_thread_id =
std::this_thread::get_id(); // captured on construction
/// @brief Severity level of this entry. /// @brief Severity level of this entry.
LogLevel level; LogLevel level;

View File

@@ -9,7 +9,7 @@
void BiergartenPipelineOrchestrator::GenerateBreweries( void BiergartenPipelineOrchestrator::GenerateBreweries(
std::span<const EnrichedCity> cities) { std::span<const EnrichedCity> cities) {
logger_->Log(LogLevel::Info, PipelinePhase::BreweryAndBeerGeneration, logger_->Log(LogLevel::Info, PipelinePhase::BreweryAndBeerGeneration,
"\n=== SAMPLE BREWERY GENERATION ==="); "=== SAMPLE BREWERY GENERATION ===");
generated_breweries_.clear(); generated_breweries_.clear();
size_t skipped_count = 0; size_t skipped_count = 0;

View File

@@ -27,5 +27,5 @@ void BiergartenPipelineOrchestrator::LogResults() const {
++index; ++index;
} }
logger_->Log(LogLevel::Info, PipelinePhase::Teardown, msg.str()); logger_->Log(LogLevel::Debug, PipelinePhase::Teardown, msg.str());
} }

View File

@@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <filesystem> #include <filesystem>
#include <format>
#include <iterator> #include <iterator>
#include <random> #include <random>
@@ -15,14 +16,12 @@
std::vector<Location> BiergartenPipelineOrchestrator::QueryCitiesWithCountries() { std::vector<Location> BiergartenPipelineOrchestrator::QueryCitiesWithCountries() {
logger_->Log(LogLevel::Info, PipelinePhase::Startup, logger_->Log(LogLevel::Info, PipelinePhase::Startup,
"\n=== GEOGRAPHIC DATA OVERVIEW ==="); "=== GEOGRAPHIC DATA OVERVIEW ===");
const std::filesystem::path locations_path = "locations.json"; const std::filesystem::path locations_path = "locations.json";
auto all_locations = JsonLoader::LoadLocations(locations_path, logger_); auto all_locations = JsonLoader::LoadLocations(locations_path, logger_);
logger_->Log(LogLevel::Info, PipelinePhase::Startup,
std::string(" Locations available: ") +
std::to_string(all_locations.size()));
const size_t sample_count = std::min( const size_t sample_count = std::min(
static_cast<size_t>(application_options_.pipeline.location_count), static_cast<size_t>(application_options_.pipeline.location_count),
@@ -40,7 +39,8 @@ std::vector<Location> BiergartenPipelineOrchestrator::QueryCitiesWithCountries()
sample_count_signed, random_generator); sample_count_signed, random_generator);
logger_->Log(LogLevel::Info, PipelinePhase::Startup, logger_->Log(LogLevel::Info, PipelinePhase::Startup,
std::string(" Sampled locations: ") + std::format(" Locations available: {}", all_locations.size()));
std::to_string(sampled_locations.size())); logger_->Log(LogLevel::Info, PipelinePhase::Startup,
std::format(" Sampled locations: {}", sampled_locations.size()));
return sampled_locations; return sampled_locations;
} }

View File

@@ -105,13 +105,5 @@ std::vector<Location> JsonLoader::LoadLocations(
}); });
} }
const std::string msg = std::string("[JsonLoader] Loaded ") +
std::to_string(locations.size()) + " locations from " +
filepath.string();
if (logger) {
logger->Log(LogLevel::Info, PipelinePhase::Startup, msg);
} else {
std::cout << msg << std::endl;
}
return locations; return locations;
} }

View File

@@ -39,14 +39,8 @@ namespace di = boost::di;
static constexpr size_t kLogMaxCount = 512; static constexpr size_t kLogMaxCount = 512;
int main(const int argc, char** argv) { int main(const int argc, char** argv) {
// Configure global spdlog formatting: timestamp, level, and message. spdlog::set_level(spdlog::level::debug);
// Use Unicode box-drawing characters to frame logs for improved readability. spdlog::set_pattern("│ %Y-%m-%d %H:%M:%S.%e │ %^%-7l%$ │ %v");
// The LogDispatcher includes phase and thread info inside the message.
spdlog::set_pattern(R"(┌────────────────────────────────────────────────────────
%^%l%$ | %Y-%m-%d %H:%M:%S:%e
%v
)");
BoundedChannel<LogEntry> log_channel(kLogMaxCount); BoundedChannel<LogEntry> log_channel(kLogMaxCount);
auto log_dispatcher = std::make_unique<LogDispatcher>(log_channel); auto log_dispatcher = std::make_unique<LogDispatcher>(log_channel);
std::thread log_thread([&log_dispatcher] { log_dispatcher->Run(); }); std::thread log_thread([&log_dispatcher] { log_dispatcher->Run(); });
@@ -61,7 +55,7 @@ int main(const int argc, char** argv) {
#endif #endif
log_producer->Log(LogLevel::Info, PipelinePhase::Startup, log_producer->Log(LogLevel::Info, PipelinePhase::Startup,
"=== Starting Biergarten Pipeline ==="); "STARTING PIPELINE");
const std::optional<ApplicationOptions> parsed_options = const std::optional<ApplicationOptions> parsed_options =
ParseArguments(argc, argv, log_producer); ParseArguments(argc, argv, log_producer);
@@ -83,9 +77,8 @@ int main(const int argc, char** argv) {
std::unique_ptr<IPromptDirectory> prompt_directory; std::unique_ptr<IPromptDirectory> prompt_directory;
if (!options.generator.use_mocked) { if (!options.generator.use_mocked) {
try { try {
prompt_directory = prompt_directory = std::make_unique<PromptDirectory>(
std::make_unique<PromptDirectory>(options.pipeline.prompt_dir, options.pipeline.prompt_dir, log_producer);
log_producer);
} catch (const std::exception& dir_error) { } catch (const std::exception& dir_error) {
log_producer->Log( log_producer->Log(
LogLevel::Error, PipelinePhase::Startup, LogLevel::Error, PipelinePhase::Startup,
@@ -107,11 +100,11 @@ int main(const int argc, char** argv) {
di::bind<IExportService>().to<SqliteExportService>(), di::bind<IExportService>().to<SqliteExportService>(),
di::bind<IPromptFormatter>().to<Gemma4JinjaPromptFormatter>(), di::bind<IPromptFormatter>().to<Gemma4JinjaPromptFormatter>(),
di::bind<IEnrichmentService>().to( di::bind<IEnrichmentService>().to(
[options, &log_producer](const auto& inj) [options, &log_producer](
-> std::unique_ptr<IEnrichmentService> { const auto& inj) -> std::unique_ptr<IEnrichmentService> {
if (options.generator.use_mocked) { // if (options.generator.use_mocked) {
return std::make_unique<MockEnrichmentService>(); // return std::make_unique<MockEnrichmentService>();
} // }
return std::make_unique<WikipediaEnrichmentService>( return std::make_unique<WikipediaEnrichmentService>(
inj.template create<std::unique_ptr<WebClient>>(), inj.template create<std::unique_ptr<WebClient>>(),
log_producer); log_producer);
@@ -165,9 +158,9 @@ int main(const int argc, char** argv) {
// Attempt to use the logging infrastructure; if channel/dispatcher are // Attempt to use the logging infrastructure; if channel/dispatcher are
// compromised this is a best-effort fallback. // compromised this is a best-effort fallback.
if (log_producer) { if (log_producer) {
log_producer->Log(LogLevel::Error, PipelinePhase::Teardown, log_producer->Log(
std::string("Unhandled fatal error in main: ") + LogLevel::Error, PipelinePhase::Teardown,
exception.what()); std::string("Unhandled fatal error in main: ") + exception.what());
} }
log_channel.Close(); log_channel.Close();
log_thread.join(); log_thread.join();

View File

@@ -3,6 +3,8 @@
* @brief LogProducer implementation for asynchronous pipeline logging. * @brief LogProducer implementation for asynchronous pipeline logging.
*/ */
#include "services/logging/log_producer.h"
#include <chrono> #include <chrono>
#include <optional> #include <optional>
#include <string> #include <string>
@@ -10,15 +12,13 @@
#include "concurrency/bounded_channel.h" #include "concurrency/bounded_channel.h"
#include "services/logging/log_entry.h" #include "services/logging/log_entry.h"
#include "services/logging/log_producer.h"
LogProducer::LogProducer(BoundedChannel<LogEntry>& channel) LogProducer::LogProducer(BoundedChannel<LogEntry>& channel)
: channel_(channel) {} : channel_(channel) {}
void LogProducer::Log(LogLevel level, PipelinePhase phase, void LogProducer::Log(LogLevel level, PipelinePhase phase,
const std::string_view message) { const std::string_view message) {
channel_.Send(LogEntry{.timestamp = std::chrono::system_clock::now(), channel_.Send(LogEntry{.timestamp = std::chrono::system_clock::now(),
.calling_thread_id = std::this_thread::get_id(),
.level = level, .level = level,
.phase = phase, .phase = phase,
.message = std::string(message)}); .message = std::string(message)});