mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-06-01 01:54:00 +00:00
Implement pipeline logging with bounded channels and orchestrator integration
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_BIERGARTEN_DATA_GENERATOR_H_
|
||||
|
||||
/**
|
||||
* @file biergarten_data_generator.h
|
||||
* @file biergarten_pipeline_orchestrator.h
|
||||
* @brief Core orchestration class for pipeline data generation.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* This class encapsulates the core logic for generating brewery data.
|
||||
* It handles location loading, city enrichment, and brewery generation.
|
||||
*/
|
||||
class BiergartenDataGenerator {
|
||||
class BiergartenPipelineOrchestrator {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a BiergartenDataGenerator with injected dependencies.
|
||||
@@ -30,10 +30,11 @@ class BiergartenDataGenerator {
|
||||
* @param generator Brewery and user data generator.
|
||||
* @param exporter Storage backend for generated brewery data.
|
||||
*/
|
||||
BiergartenDataGenerator(std::unique_ptr<IEnrichmentService> context_service,
|
||||
std::unique_ptr<DataGenerator> generator,
|
||||
std::unique_ptr<IExportService> exporter,
|
||||
const ApplicationOptions& application_options);
|
||||
BiergartenPipelineOrchestrator(
|
||||
std::unique_ptr<IEnrichmentService> context_service,
|
||||
std::unique_ptr<DataGenerator> generator,
|
||||
std::unique_ptr<IExportService> exporter,
|
||||
const ApplicationOptions& application_options);
|
||||
|
||||
/**
|
||||
* @brief Run the data generation pipeline.
|
||||
@@ -57,7 +58,7 @@ class BiergartenDataGenerator {
|
||||
/// @brief Storage backend for generated brewery records.
|
||||
std::unique_ptr<IExportService> exporter_;
|
||||
|
||||
const ApplicationOptions application_options_;
|
||||
ApplicationOptions application_options_;
|
||||
|
||||
/**
|
||||
* @brief Load locations from JSON and sample cities.
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
// Created by aaronpo on 29/04/2026.
|
||||
//
|
||||
|
||||
#ifndef CONCURRENCY_INTRO_CPP_INCLUDES_BOUNDEDCHANNEL_H_
|
||||
#define CONCURRENCY_INTRO_CPP_INCLUDES_BOUNDEDCHANNEL_H_
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_CONCURRENCY_BOUNDED_CHANNEL_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_CONCURRENCY_BOUNDED_CHANNEL_H_
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
#include <cstddef>
|
||||
|
||||
/**
|
||||
* @file BoundedChannel.h
|
||||
* @file bounded_channel.h
|
||||
* @brief A thread-safe, bounded multi-producer/multi-consumer channel.
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
class BoundedChannel {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Internal state — all access must be guarded by mutex_.
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -44,7 +43,6 @@ class BoundedChannel {
|
||||
bool closed_ = false;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Construct a bounded channel with the given capacity.
|
||||
* @param capacity Maximum number of items the channel may hold.
|
||||
@@ -68,10 +66,10 @@ class BoundedChannel {
|
||||
/**
|
||||
* @brief Close the channel and unblock all waiting threads. Idempotent.
|
||||
*/
|
||||
void close();
|
||||
void Close();
|
||||
};
|
||||
|
||||
// Include the template implementation
|
||||
#include "BoundedChannel.tcc"
|
||||
#include "bounded_channel.tcc"
|
||||
|
||||
#endif // CONCURRENCY_INTRO_CPP_INCLUDES_BOUNDEDCHANNEL_H_
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_CONCURRENCY_BOUNDED_CHANNEL_H_
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "BoundedChannel.h"
|
||||
#include "bounded_channel.h"
|
||||
|
||||
template <typename T>
|
||||
void BoundedChannel<T>::Send(T item) {
|
||||
@@ -42,7 +42,7 @@ std::optional<T> BoundedChannel<T>::Receive() {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BoundedChannel<T>::close() {
|
||||
void BoundedChannel<T>::Close() {
|
||||
// Acquire exclusive ownership of the mutex to ensure visibility of the flag.
|
||||
std::unique_lock lock(mutex_);
|
||||
|
||||
37
tooling/pipeline/includes/services/logging/channel_logger.h
Normal file
37
tooling/pipeline/includes/services/logging/channel_logger.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file services/logging/channel_logger.h
|
||||
* @brief Channel-backed implementation of the Logger interface.
|
||||
*
|
||||
* ChannelLogger constructs LogEntry values and forwards them to a
|
||||
* BoundedChannel<LogEntry> for asynchronous consumption by LogConsumer.
|
||||
* The channel is injected by reference; ChannelLogger does not own it.
|
||||
*/
|
||||
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_CHANNEL_LOGGER_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_CHANNEL_LOGGER_H_
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "concurrency/bounded_channel.h"
|
||||
#include "services/logging/log_entry.h"
|
||||
#include "services/logging/logger.h"
|
||||
|
||||
class ChannelLogger final : public ILogger {
|
||||
public:
|
||||
explicit ChannelLogger(BoundedChannel<LogEntry>& channel);
|
||||
|
||||
ChannelLogger(const ChannelLogger&) = delete;
|
||||
ChannelLogger& operator=(const ChannelLogger&) = delete;
|
||||
ChannelLogger(ChannelLogger&&) = delete;
|
||||
ChannelLogger& operator=(ChannelLogger&&) = delete;
|
||||
|
||||
~ChannelLogger() override = default;
|
||||
|
||||
void Log(LogLevel level, PipelinePhase phase,
|
||||
std::string_view message) override;
|
||||
|
||||
private:
|
||||
BoundedChannel<LogEntry>& channel_;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_CHANNEL_LOGGER_H_
|
||||
44
tooling/pipeline/includes/services/logging/log_consumer.h
Normal file
44
tooling/pipeline/includes/services/logging/log_consumer.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file services/logging/log_consumer.h
|
||||
* @brief Dedicated log drain worker for the pipeline logging channel.
|
||||
*
|
||||
* LogConsumer runs on its own thread, draining LogEntry items from a
|
||||
* BoundedChannel<LogEntry> and forwarding them to spdlog. Exits cleanly
|
||||
* when the channel is closed.
|
||||
*/
|
||||
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_CONSUMER_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_CONSUMER_H_
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "concurrency/bounded_channel.h"
|
||||
#include "services/logging/log_entry.h"
|
||||
|
||||
class LogConsumer {
|
||||
public:
|
||||
explicit LogConsumer(BoundedChannel<LogEntry>& channel);
|
||||
|
||||
LogConsumer(const LogConsumer&) = delete;
|
||||
LogConsumer& operator=(const LogConsumer&) = delete;
|
||||
LogConsumer(LogConsumer&&) = delete;
|
||||
LogConsumer& operator=(LogConsumer&&) = delete;
|
||||
|
||||
/**
|
||||
* @brief Drains the channel until it is closed.
|
||||
*
|
||||
* Intended to be run on a dedicated std::thread. Exits when:
|
||||
* - The channel is closed and the queue is fully drained.
|
||||
*/
|
||||
void Run();
|
||||
|
||||
private:
|
||||
BoundedChannel<LogEntry>& channel_;
|
||||
|
||||
static spdlog::level::level_enum ToSpdlogLevel(LogLevel level);
|
||||
static std::string ToString(PipelinePhase phase);
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_CONSUMER_H_
|
||||
41
tooling/pipeline/includes/services/logging/log_entry.h
Normal file
41
tooling/pipeline/includes/services/logging/log_entry.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @file services/logging/log_entry.h
|
||||
* @brief POD struct representing a single log event in the pipeline.
|
||||
*
|
||||
* LogEntry is produced by PipelineLogger and consumed by LogWorker via
|
||||
* BoundedChannel<LogEntry>. All fields are value types so entries are
|
||||
* safely movable across the channel without shared ownership.
|
||||
*/
|
||||
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_ENTRY_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_ENTRY_H_
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
enum class LogLevel {
|
||||
Debug,
|
||||
Info,
|
||||
Warn,
|
||||
Error,
|
||||
};
|
||||
|
||||
enum class PipelinePhase {
|
||||
Startup,
|
||||
UserGeneration,
|
||||
BreweryAndBeerGeneration,
|
||||
CheckinGeneration,
|
||||
RatingGeneration,
|
||||
FollowGeneration,
|
||||
Teardown,
|
||||
};
|
||||
|
||||
struct LogEntry {
|
||||
std::chrono::system_clock::time_point timestamp =
|
||||
std::chrono::system_clock::now();
|
||||
LogLevel level;
|
||||
PipelinePhase phase;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOG_ENTRY_H_
|
||||
31
tooling/pipeline/includes/services/logging/logger.h
Normal file
31
tooling/pipeline/includes/services/logging/logger.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @file services/logging/logger.h
|
||||
* @brief Abstract interface for pipeline logging.
|
||||
*
|
||||
* Kept intentionally narrow. Components that need to log depend on Logger,
|
||||
* not on PipelineLogger or any channel type.
|
||||
*/
|
||||
|
||||
#ifndef BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOGGER_H_
|
||||
#define BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOGGER_H_
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "services/logging/log_entry.h"
|
||||
|
||||
class ILogger {
|
||||
public:
|
||||
ILogger() = default;
|
||||
ILogger(const ILogger&) = delete;
|
||||
ILogger& operator=(const ILogger&) = delete;
|
||||
ILogger(ILogger&&) = delete;
|
||||
ILogger& operator=(ILogger&&) = delete;
|
||||
virtual ~ILogger() = default;
|
||||
|
||||
virtual void Log(LogLevel level, PipelinePhase phase,
|
||||
std::string_view message) = 0;
|
||||
};
|
||||
|
||||
#endif // BIERGARTEN_PIPELINE_INCLUDES_SERVICES_LOGGING_LOGGER_H_
|
||||
Reference in New Issue
Block a user