Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
logger_builder.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#pragma once
6
65#include "logger_config.h"
71#include "logger.h"
82
83// Use common_system interfaces (Phase 2.2.4)
84#include <kcenon/common/interfaces/monitoring_interface.h>
85
86#include <memory>
87#include <vector>
88#include <algorithm>
89#include <cstdlib>
90
91namespace kcenon::logger {
92
117public:
118 logger_builder() : config_(logger_config::default_config()) {}
119
140 config_ = config;
141 return *this;
142 }
143
166 logger_builder& with_async(bool async = true) {
167 config_.async = async;
168 // When disabling async, ensure batch_size is 1
169 if (!async && config_.batch_size > 1) {
171 }
172 return *this;
173 }
174
194 return *this;
195 }
196
216 logger_builder& with_min_level(log_level level) {
217 config_.min_level = level;
218 return *this;
219 }
220
228 return *this;
229 }
230
236 logger_builder& with_batch_writing(bool enable = true) {
238 return *this;
239 }
240
246 logger_builder& with_flush_interval(std::chrono::milliseconds interval) {
247 config_.flush_interval = interval;
248 return *this;
249 }
250
256 logger_builder& with_lock_free(bool enable = true) {
257 config_.use_lock_free = enable;
258 return *this;
259 }
260
266 logger_builder& with_metrics(bool enable = true) {
267 config_.enable_metrics = enable;
268 return *this;
269 }
270
276 logger_builder& with_crash_handler(bool enable = true) {
278 return *this;
279 }
280
288 return *this;
289 }
290
300
308 return *this;
309 }
310
319 logger_builder& with_file_output(const std::string& directory,
320 const std::string& prefix = "app",
321 std::size_t max_size = 100 * 1024 * 1024,
322 std::size_t max_count = 5) {
323 config_.log_directory = directory;
324 config_.log_file_prefix = prefix;
325 config_.max_file_size = max_size;
326 config_.max_file_count = max_count;
327 return *this;
328 }
329
337 logger_builder& with_network_output(const std::string& host,
338 uint16_t port,
339 std::chrono::milliseconds timeout = std::chrono::milliseconds(5000)) {
340 config_.remote_host = host;
341 config_.remote_port = port;
342 config_.network_timeout = timeout;
343 return *this;
344 }
345
352 logger_builder& add_writer(const std::string& name, log_writer_ptr writer) {
353 writers_.push_back({name, std::move(writer)});
354 return *this;
355 }
356
375 logger_builder& add_filter(std::unique_ptr<log_filter_interface> filter) {
376 if (filter) {
377 filters_.push_back(std::move(filter));
378 }
379 return *this;
380 }
381
389 logger_builder& add_level_filter(log_level min_level) {
390 filters_.push_back(std::make_unique<filters::level_filter>(min_level));
391 return *this;
392 }
393
402 logger_builder& add_regex_filter(const std::string& pattern, bool include_matches = true) {
403 filters_.push_back(std::make_unique<filters::regex_filter>(pattern, include_matches));
404 return *this;
405 }
406
414 logger_builder& add_function_filter(std::function<bool(const log_entry&)> predicate) {
415 filters_.push_back(std::make_unique<filters::function_filter>(std::move(predicate)));
416 return *this;
417 }
418
419 // =========================================================================
420 // Routing configuration
421 // =========================================================================
422
447 routes_.push_back(std::move(config));
448 return *this;
449 }
450
461 logger_builder& with_exclusive_routing(bool exclusive = true) {
462 exclusive_routing_ = exclusive;
463 return *this;
464 }
465
484 logger_builder& route_level(log_level level,
485 const std::vector<std::string>& writer_names,
486 bool stop_propagation = false) {
488 config.writer_names = writer_names;
489 config.filter = std::make_unique<filters::level_filter>(level);
490 config.stop_propagation = stop_propagation;
491 routes_.push_back(std::move(config));
492 return *this;
493 }
494
513 logger_builder& route_pattern(const std::string& pattern,
514 const std::vector<std::string>& writer_names,
515 bool stop_propagation = false) {
517 config.writer_names = writer_names;
518 config.filter = std::make_unique<filters::regex_filter>(pattern, true);
519 config.stop_propagation = stop_propagation;
520 routes_.push_back(std::move(config));
521 return *this;
522 }
523
529 logger_builder& with_formatter(std::unique_ptr<log_formatter_interface> formatter) {
530 formatter_ = std::move(formatter);
531 return *this;
532 }
533
560 logger_builder& use_template(const std::string& name) {
561 // Use built-in logger_config templates
562 if (name == "high_performance") {
564 } else if (name == "low_latency") {
566 } else if (name == "debug") {
568 } else if (name == "production") {
570 } else {
572 }
573 return *this;
574 }
575
586 logger_builder& apply_strategy(std::unique_ptr<config_strategy_interface> strategy) {
587 if (strategy) {
588 strategies_.push_back(std::move(strategy));
589 }
590 return *this;
591 }
592
607 return apply_strategy(std::make_unique<deployment_strategy>(env));
608 }
609
624 return apply_strategy(std::make_unique<performance_strategy>(level));
625 }
626
638 auto strategy = std::make_unique<environment_strategy>();
639 if (strategy->is_applicable()) {
640 apply_strategy(std::move(strategy));
641 }
642 return *this;
643 }
644
652 strategies_.clear();
653 return *this;
654 }
655
656
662 const char* env = std::getenv("LOG_ENV");
663 const char* level = std::getenv("LOG_LEVEL");
664
665 if (env) {
666 std::string env_str(env);
667 if (env_str == "production") {
668 use_template("production");
669 } else if (env_str == "debug" || env_str == "development") {
670 use_template("debug");
671 }
672 }
673
674 if (level) {
675 std::string level_str(level);
676 if (level_str == "trace") config_.min_level = log_level::trace;
677 else if (level_str == "debug") config_.min_level = log_level::debug;
678 else if (level_str == "info") config_.min_level = log_level::info;
679 else if (level_str == "warn") config_.min_level = log_level::warning;
680 else if (level_str == "error") config_.min_level = log_level::error;
681 else if (level_str == "fatal") config_.min_level = log_level::critical;
682 }
683
684 return *this;
685 }
686
692 logger_builder& with_monitoring(std::shared_ptr<common::interfaces::IMonitor> monitor) {
693 monitor_ = monitor;
694 config_.enable_metrics = true;
695 return *this;
696 }
697
703 logger_builder& with_health_check_interval(std::chrono::milliseconds interval) {
704 health_check_interval_ = interval;
705 return *this;
706 }
707
708
719 logger_builder& with_backend(std::unique_ptr<backends::integration_backend> backend) {
720 backend_ = std::move(backend);
721 return *this;
722 }
723
734 backend_ = std::make_unique<backends::standalone_backend>();
735 return *this;
736 }
737
743 logger_builder& with_error_handler(std::function<void(const logger_error_code&)> handler) {
744 error_handler_ = handler;
745 return *this;
746 }
747
748 // =========================================================================
749 // Real-time analysis configuration (requires LOGGER_WITH_ANALYSIS)
750 // =========================================================================
751
752#ifdef LOGGER_WITH_ANALYSIS
776 logger_builder& with_realtime_analyzer(
777 std::unique_ptr<analysis::realtime_log_analyzer> analyzer) {
778 realtime_analyzer_ = std::move(analyzer);
779 return *this;
780 }
781
809 logger_builder& with_realtime_analysis(
810 const analysis::realtime_analysis_config& config,
812 realtime_analyzer_ = std::make_unique<analysis::realtime_log_analyzer>(config);
813 if (callback) {
814 realtime_analyzer_->set_anomaly_callback(std::move(callback));
815 }
816 return *this;
817 }
818
831 logger_builder& with_realtime_analysis(
832 size_t error_threshold = 50,
835 error_threshold, std::move(callback));
836 return *this;
837 }
838#endif // LOGGER_WITH_ANALYSIS
839
845 // Set a default format pattern
848 return *this;
849 }
850
851 // =========================================================================
852 // Sampling configuration
853 // =========================================================================
854
875 logger_builder& with_sampler(std::unique_ptr<sampling::log_sampler> sampler) {
876 sampler_ = std::move(sampler);
877 return *this;
878 }
879
899 sampler_ = std::make_unique<sampling::log_sampler>(config);
900 return *this;
901 }
902
903 // Legacy sampling methods (with_random_sampling, with_rate_limiting, with_adaptive_sampling)
904 // removed. Use with_sampling(sampling_config::random_sampling(rate)),
905 // with_sampling(sampling_config::rate_limited(max_per_second)),
906 // with_sampling(sampling_config::adaptive(threshold, min_rate)) instead.
907
941 // Apply all strategies in priority order (highest first)
942 if (!strategies_.empty()) {
943 // Sort strategies by priority (descending)
944 std::sort(strategies_.begin(), strategies_.end(),
945 [](const auto& a, const auto& b) {
946 return a->priority() > b->priority();
947 });
948
949 // Apply each applicable strategy
950 for (const auto& strategy : strategies_) {
951 if (strategy->is_applicable()) {
952 strategy->apply(config_);
953 }
954 }
955 }
956
957 // Validate configuration
958 if (auto validation = config_.validate(); validation.is_err()) {
961 "Configuration validation failed"};
962 }
963
964 // Validate writer count
965 if (!writers_.empty() && writers_.size() > config_.max_writers) {
968 "Number of writers exceeds max_writers configuration"};
969 }
970
971 // Auto-detect backend if not explicitly set
972 // Users can provide thread_system_backend or other backends via with_backend()
973 if (!backend_) {
974 backend_ = std::make_unique<backends::standalone_backend>();
975 }
976
977 // Create logger with validated configuration
978 auto logger_instance = std::make_unique<logger>(config_.async, config_.buffer_size, std::move(backend_));
979
980 // Apply configuration settings
981 logger_instance->set_level(config_.min_level);
982
984 logger_instance->enable_metrics_collection(true);
985 }
986
987 // Add writers (apply batch writing if enabled)
988 for (auto& [name, writer] : writers_) {
989 if (writer) {
990 // Set color output if the writer supports it (console_writer)
991 if (auto* console = dynamic_cast<console_writer*>(writer.get())) {
992 console->set_use_color(config_.enable_color_output);
993 }
994
995 // Wrap with batch writer if enabled and async mode
997 batch_writer::config batch_cfg;
1000
1001 auto batch_wrapped = std::make_unique<batch_writer>(
1002 std::move(writer), batch_cfg
1003 );
1004 logger_instance->add_writer(name, std::move(batch_wrapped));
1005 } else {
1006 logger_instance->add_writer(name, std::move(writer));
1007 }
1008 }
1009 }
1010
1011 // Apply filters if any were added
1012 if (!filters_.empty()) {
1013 // Create composite filter if multiple filters
1014 if (filters_.size() == 1) {
1015 logger_instance->set_filter(std::move(filters_[0]));
1016 } else {
1017 auto composite = std::make_unique<filters::composite_filter>(filters::composite_filter::logic_type::AND);
1018 for (auto& filter : filters_) {
1019 composite->add_filter(std::move(filter));
1020 }
1021 logger_instance->set_filter(std::move(composite));
1022 }
1023 }
1024 filters_.clear(); // Clear after moving
1025
1026 // Apply routing configuration
1027 if (!routes_.empty()) {
1028 auto& router = logger_instance->get_router();
1029 router.set_exclusive_routes(exclusive_routing_);
1030 for (auto& route : routes_) {
1031 router.add_route(std::move(route));
1032 }
1033 }
1034 routes_.clear(); // Clear after moving
1035
1036 // Apply real-time analyzer if configured
1037#ifdef LOGGER_WITH_ANALYSIS
1038 if (realtime_analyzer_) {
1039 logger_instance->set_realtime_analyzer(std::move(realtime_analyzer_));
1040 }
1041#endif // LOGGER_WITH_ANALYSIS
1042
1043 // Apply sampler if configured
1044 if (sampler_) {
1045 logger_instance->set_sampler(std::move(sampler_));
1046 }
1047
1048 // Start logger if async
1049 if (config_.async) {
1050 logger_instance->start();
1051 }
1052
1053 // Store configuration in logger (if we add a config getter)
1055
1056 // Return logger instance (NRVO will be applied automatically)
1057 return logger_instance;
1058 }
1059
1064 const logger_config& get_config() const {
1065 return config_;
1066 }
1067
1073 return config_.validate();
1074 }
1075
1076private:
1078 std::vector<std::pair<std::string, log_writer_ptr>> writers_;
1079 std::vector<std::unique_ptr<log_filter_interface>> filters_;
1080 std::vector<routing::route_config> routes_; // Routing configurations
1081 bool exclusive_routing_ = false; // Exclusive routing mode flag
1082 std::unique_ptr<log_formatter_interface> formatter_;
1083 std::unique_ptr<backends::integration_backend> backend_; // Integration backend (Phase 3.2)
1084 std::vector<std::unique_ptr<config_strategy_interface>> strategies_; // Configuration strategies
1085 mutable logger_config built_config_; // Store last built configuration
1086 std::shared_ptr<common::interfaces::IMonitor> monitor_; // Phase 2.2.4
1087 std::chrono::milliseconds health_check_interval_{1000};
1088 std::function<void(const logger_error_code&)> error_handler_;
1089#ifdef LOGGER_WITH_ANALYSIS
1090 std::unique_ptr<analysis::realtime_log_analyzer> realtime_analyzer_; // Real-time analyzer
1091#endif // LOGGER_WITH_ANALYSIS
1092 std::unique_ptr<sampling::log_sampler> sampler_; // Log sampler for volume reduction
1093};
1094
1095} // namespace kcenon::logger
Batch writer that accumulates log entries and writes them in batches.
static std::unique_ptr< realtime_log_analyzer > create_production(size_t error_threshold=50, realtime_log_analyzer::anomaly_callback callback=nullptr)
Create a production-ready analyzer with sensible defaults.
std::function< void(const anomaly_event &)> anomaly_callback
Callback type for anomaly notifications.
Core console writer for logging to stdout/stderr.
Builder pattern for logger construction with validation.
logger_builder & with_monitoring(std::shared_ptr< common::interfaces::IMonitor > monitor)
Set monitoring interface (Phase 2.2.4)
logger_builder & with_config(const logger_config &config)
logger_builder & add_function_filter(std::function< bool(const log_entry &)> predicate)
Add a function-based filter (convenience method)
logger_builder & with_metrics(bool enable=true)
Enable metrics collection.
logger_builder & with_exclusive_routing(bool exclusive=true)
Set exclusive routing mode.
std::unique_ptr< sampling::log_sampler > sampler_
logger_builder & with_min_level(log_level level)
logger_builder & with_sampler(std::unique_ptr< sampling::log_sampler > sampler)
logger_builder & with_structured_logging(bool enable=true)
Enable structured logging.
logger_builder & with_batch_size(std::size_t size)
Set batch size for processing.
std::unique_ptr< log_formatter_interface > formatter_
logger_builder & use_template(const std::string &name)
std::vector< routing::route_config > routes_
logger_builder & with_lock_free(bool enable=true)
Enable lock-free queue.
std::function< void(const logger_error_code &)> error_handler_
common::VoidResult validate() const
Validate current configuration without building.
logger_builder & with_crash_handler(bool enable=true)
Enable crash handler.
logger_builder & with_default_pattern()
Use default pattern for logging.
logger_builder & with_batch_writing(bool enable=true)
Enable batch writing for writers.
logger_builder & auto_configure()
Auto-configure from environment variables.
logger_builder & detect_environment()
Detect environment from environment variables.
logger_builder & with_network_output(const std::string &host, uint16_t port, std::chrono::milliseconds timeout=std::chrono::milliseconds(5000))
Configure network output.
logger_builder & with_max_queue_size(std::size_t size)
Set max queue size.
logger_builder & with_sampling(const sampling::sampling_config &config)
std::shared_ptr< common::interfaces::IMonitor > monitor_
logger_builder & with_standalone_backend()
Use standalone backend explicitly.
logger_builder & with_file_output(const std::string &directory, const std::string &prefix="app", std::size_t max_size=100 *1024 *1024, std::size_t max_count=5)
Configure file output.
logger_builder & with_overflow_policy(logger_config::overflow_policy policy)
Set queue overflow policy.
logger_builder & with_backend(std::unique_ptr< backends::integration_backend > backend)
Set integration backend explicitly.
logger_builder & add_regex_filter(const std::string &pattern, bool include_matches=true)
Add a regex filter (convenience method)
logger_builder & with_async(bool async=true)
logger_builder & with_health_check_interval(std::chrono::milliseconds interval)
Set health check interval.
std::vector< std::unique_ptr< log_filter_interface > > filters_
logger_builder & with_performance_tuning(performance_level level)
Apply performance tuning.
logger_builder & with_error_handler(std::function< void(const logger_error_code &)> handler)
Set error handler.
logger_builder & for_environment(deployment_env env)
Configure for a specific deployment environment.
std::vector< std::unique_ptr< config_strategy_interface > > strategies_
logger_builder & route_level(log_level level, const std::vector< std::string > &writer_names, bool stop_propagation=false)
logger_builder & add_filter(std::unique_ptr< log_filter_interface > filter)
logger_builder & add_level_filter(log_level min_level)
Add a level filter (convenience method)
std::chrono::milliseconds health_check_interval_
std::vector< std::pair< std::string, log_writer_ptr > > writers_
logger_builder & apply_strategy(std::unique_ptr< config_strategy_interface > strategy)
Apply a configuration strategy.
result< std::unique_ptr< logger > > build()
logger_builder & add_writer(const std::string &name, log_writer_ptr writer)
Add a writer to the logger.
logger_builder & route_pattern(const std::string &pattern, const std::vector< std::string > &writer_names, bool stop_propagation=false)
std::unique_ptr< backends::integration_backend > backend_
logger_builder & with_buffer_size(std::size_t size)
Set buffer size.
logger_builder & clear_strategies()
Clear all registered strategies.
logger_builder & with_flush_interval(std::chrono::milliseconds interval)
Set flush interval.
logger_builder & with_formatter(std::unique_ptr< log_formatter_interface > formatter)
Set formatter for the logger.
const logger_config & get_config() const
Get the current configuration (for inspection)
logger_builder & with_route(routing::route_config config)
Composite configuration strategy for combining multiple strategies.
Interface for logger configuration strategies (Strategy Pattern)
Console writer for logging to stdout/stderr.
Deployment environment configuration strategies.
Environment variable-based configuration strategy.
Log filtering functionality.
Runtime polymorphism interface for integration backends kcenon.
Interface for log message formatters (Strategy Pattern) kcenon.
Log routing functionality.
Log sampling implementation for high-volume scenarios kcenon.
Base interface for all log writers and decorators.
High-performance, thread-safe logging system with asynchronous capabilities.
Configuration structure for logger with validation.
logger_error_code
Error codes specific to the logger system.
deployment_env
Deployment environment types.
@ size
Rotate based on file size only.
performance_level
Performance tuning presets.
std::unique_ptr< log_writer_interface > log_writer_ptr
Type alias for writer unique pointer.
Performance tuning configuration strategies.
Real-time log analysis with anomaly detection.
Standalone integration backend implementation kcenon.
Configuration for batch writer.
std::chrono::milliseconds flush_interval
Represents a single log entry with all associated metadata.
Definition log_entry.h:155
Configuration structure for logger with validation.
log_level min_level
Minimum log level to process.
std::size_t batch_size
Number of messages per batch write.
static logger_config low_latency()
Create a low-latency configuration.
common::VoidResult validate() const
Validate the configuration.
static logger_config production()
Create a production configuration.
bool enable_batch_writing
Enable batch writing mode.
std::size_t max_file_size
Maximum file size in bytes (default: 100MB).
bool async
Enable asynchronous logging.
std::chrono::milliseconds network_timeout
Network operation timeout.
bool enable_color_output
Enable ANSI color output.
bool enable_timestamp
Include timestamp in log entries.
static logger_config default_config()
Create a default configuration.
overflow_policy queue_overflow_policy
Active overflow policy.
bool enable_source_location
Include source file/line in log entries.
bool enable_metrics
Enable performance metrics collection.
static logger_config high_performance()
Create a high-performance configuration.
std::string log_directory
Directory for log file output.
std::string remote_host
Remote log collector hostname.
overflow_policy
Policy for handling queue overflow when max_queue_size is reached.
std::chrono::milliseconds flush_interval
Interval between automatic flushes.
std::size_t buffer_size
Internal buffer size in bytes.
uint16_t remote_port
Remote log collector port.
std::size_t max_writers
Maximum number of concurrent writers.
std::size_t max_file_count
Maximum number of rotating log files.
bool enable_crash_handler
Enable crash signal handler.
bool use_lock_free
Use lock-free queue implementation.
std::size_t max_queue_size
Maximum number of queued messages.
bool enable_structured_logging
Enable structured (JSON) log output.
std::string log_file_prefix
Prefix for log file names.
static logger_config debug_config()
Create a debug configuration.
Route configuration for log messages.
Definition log_router.h:32
std::vector< std::string > writer_names
Definition log_router.h:33
std::unique_ptr< log_filter_interface > filter
Definition log_router.h:34
Configuration for log sampling behavior.
Conditionally enables thread_system integration when available.