12#ifdef LOGGER_WITH_ANALYSIS
22#include <kcenon/common/patterns/result.h>
28#include <shared_mutex>
30#include <unordered_map>
36using log_level = common::interfaces::log_level;
53bool meets_threshold(log_level level, log_level minimum) {
54 return static_cast<int>(level) >=
static_cast<int>(minimum);
66 std::vector<std::shared_ptr<log_writer_interface>>
writers_;
67 std::unordered_map<std::string, std::shared_ptr<log_writer_interface>>
named_writers_;
69 std::unique_ptr<backends::integration_backend>
backend_;
71 std::unique_ptr<log_filter_interface>
filter_;
76#ifdef LOGGER_WITH_ANALYSIS
78 std::unique_ptr<analysis::realtime_log_analyzer> realtime_analyzer_;
79 mutable std::shared_mutex analyzer_mutex_;
86 std::unique_ptr<sampling::log_sampler>
sampler_;
95 impl(
bool async, std::size_t buffer_size, std::unique_ptr<backends::integration_backend> backend)
105 backend_ = std::make_unique<backends::standalone_backend>();
109 if (
backend_->requires_initialization()) {
110 backend_->initialize();
135 const std::string& message,
136 const std::string& file,
138 const std::string& function,
140#ifdef LOGGER_WITH_ANALYSIS
143 std::shared_lock<std::shared_mutex> lock(analyzer_mutex_);
144 if (realtime_analyzer_) {
146 analyzed_entry.
level = level;
147 analyzed_entry.
message = message;
152 realtime_analyzer_->analyze(analyzed_entry);
158 std::vector<std::string> routed_writer_names;
159 bool is_exclusive =
false;
163 routed_writer_names =
router_->get_writers_for_log(entry);
164 is_exclusive =
router_->is_exclusive_routing();
168 auto now = std::chrono::system_clock::now();
173 if (!routed_writer_names.empty()) {
174 std::unordered_map<std::string, std::shared_ptr<log_writer_interface>> local_named_writers;
181 log_entry entry(level, message, file, line, function, now);
183 for (
const auto& writer_name : routed_writer_names) {
184 auto it = local_named_writers.find(writer_name);
185 if (it != local_named_writers.end() && it->second) {
186 it->second->write(entry);
193 std::vector<std::shared_ptr<log_writer_interface>> local_writers;
200 log_entry entry(level, message, file, line, function, now);
202 for (
auto& writer : local_writers) {
204 writer->write(entry);
211logger::logger(
bool async, std::size_t buffer_size, std::unique_ptr<backends::integration_backend> backend)
212 : pimpl_(std::make_unique<
impl>(async, buffer_size, std::move(backend))) {
230 std::shared_lock<std::shared_mutex> lock(
pimpl_->writers_mutex_);
231 for (
const auto& writer :
pimpl_->writers_) {
233 pimpl_->collector_->add_writer(writer);
239 pimpl_->collector_->start();
250 pimpl_->collector_->stop();
261bool logger::is_running()
const {
267 std::shared_ptr<log_writer_interface> shared_writer(std::move(writer));
270 std::lock_guard<std::shared_mutex> lock(
pimpl_->writers_mutex_);
271 pimpl_->writers_.push_back(shared_writer);
276 pimpl_->collector_->add_writer(shared_writer);
284 return common::make_error<std::monostate>(
286 "Logger not initialized",
290 return common::make_error<std::monostate>(
292 "Writer cannot be null",
296 std::shared_ptr<log_writer_interface> shared_writer(std::move(writer));
299 std::lock_guard<std::shared_mutex> lock(
pimpl_->writers_mutex_);
300 pimpl_->writers_.push_back(shared_writer);
302 pimpl_->named_writers_[name] = shared_writer;
308 pimpl_->collector_->add_writer(shared_writer);
317 std::lock_guard<std::shared_mutex> lock(
pimpl_->writers_mutex_);
319 pimpl_->named_writers_.clear();
324 pimpl_->collector_->clear_writers();
330bool logger::remove_writer(
const std::string& name) {
331 if (!
pimpl_ || name.empty()) {
335 std::lock_guard<std::shared_mutex> lock(
pimpl_->writers_mutex_);
337 auto it =
pimpl_->named_writers_.find(name);
338 if (it ==
pimpl_->named_writers_.end()) {
342 auto writer_to_remove = it->second;
345 pimpl_->named_writers_.erase(it);
348 auto vec_it = std::find(
pimpl_->writers_.begin(),
pimpl_->writers_.end(), writer_to_remove);
349 if (vec_it !=
pimpl_->writers_.end()) {
350 pimpl_->writers_.erase(vec_it);
360 if (!
pimpl_ || name.empty()) {
364 std::shared_lock<std::shared_mutex> lock(
pimpl_->writers_mutex_);
366 auto it =
pimpl_->named_writers_.find(name);
367 if (it !=
pimpl_->named_writers_.end() && it->second) {
368 return it->second.get();
379 const std::string& message) {
380 if (!
pimpl_ || !meets_threshold(level,
pimpl_->min_level_.load())) {
389 std::shared_lock<std::shared_mutex> filter_lock(
pimpl_->filter_mutex_);
391 if (!
pimpl_->filter_->should_log(entry)) {
399 std::shared_lock<std::shared_mutex> sampler_lock(
pimpl_->sampler_mutex_);
400 if (
pimpl_->sampler_ &&
pimpl_->sampler_->is_enabled()) {
401 if (!
pimpl_->sampler_->should_sample(entry)) {
408 auto start_time = std::chrono::high_resolution_clock::now();
411 pimpl_->dispatch_to_writers(level, message,
"", 0,
"", entry);
414 if (
pimpl_->metrics_enabled_) {
415 auto end_time = std::chrono::high_resolution_clock::now();
416 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
424 std::string_view message,
425 const common::source_location& loc) {
426 if (!
pimpl_ || !meets_threshold(level,
pimpl_->min_level_.load())) {
430 std::string msg_str(message);
431 std::string file_str(loc.file_name());
432 int line = loc.line();
433 std::string func_str(loc.function_name());
436 log_entry entry(level, msg_str, file_str, line, func_str);
440 std::shared_lock<std::shared_mutex> filter_lock(
pimpl_->filter_mutex_);
442 if (!
pimpl_->filter_->should_log(entry)) {
450 std::shared_lock<std::shared_mutex> sampler_lock(
pimpl_->sampler_mutex_);
451 if (
pimpl_->sampler_ &&
pimpl_->sampler_->is_enabled()) {
452 if (!
pimpl_->sampler_->should_sample(entry)) {
459 auto start_time = std::chrono::high_resolution_clock::now();
464 auto now = std::chrono::system_clock::now();
465 pimpl_->collector_->enqueue(level, msg_str, file_str, line, func_str, now);
468 if (
pimpl_->metrics_enabled_) {
469 auto end_time = std::chrono::high_resolution_clock::now();
470 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
477 pimpl_->dispatch_to_writers(level, msg_str, file_str, line, func_str, entry);
480 if (
pimpl_->metrics_enabled_) {
481 auto end_time = std::chrono::high_resolution_clock::now();
482 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
490 if (!
pimpl_ || !meets_threshold(entry.level,
pimpl_->min_level_.load())) {
494 std::string msg_str(entry.message);
495 std::string file_str(entry.file);
496 int line = entry.line;
497 std::string func_str(entry.function);
500 log_entry internal_entry(entry.level, msg_str, file_str, line, func_str);
504 std::shared_lock<std::shared_mutex> filter_lock(
pimpl_->filter_mutex_);
506 if (!
pimpl_->filter_->should_log(internal_entry)) {
514 std::shared_lock<std::shared_mutex> sampler_lock(
pimpl_->sampler_mutex_);
515 if (
pimpl_->sampler_ &&
pimpl_->sampler_->is_enabled()) {
516 if (!
pimpl_->sampler_->should_sample(internal_entry)) {
523 auto start_time = std::chrono::high_resolution_clock::now();
527 auto now = std::chrono::system_clock::now();
528 pimpl_->collector_->enqueue(entry.level, msg_str, file_str, line, func_str, now);
530 if (
pimpl_->metrics_enabled_) {
531 auto end_time = std::chrono::high_resolution_clock::now();
532 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
539 pimpl_->dispatch_to_writers(entry.level, msg_str, file_str, line, func_str, internal_entry);
542 if (
pimpl_->metrics_enabled_) {
543 auto end_time = std::chrono::high_resolution_clock::now();
544 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
551bool logger::is_enabled(common::interfaces::log_level level)
const {
552 return pimpl_ && meets_threshold(level,
pimpl_->min_level_.load());
557 return common::make_error<std::monostate>(
559 "Logger not initialized",
563 pimpl_->min_level_.store(level);
567common::interfaces::log_level logger::get_level()
const {
569 return pimpl_->min_level_.load();
571 return common::interfaces::log_level::info;
576 return common::make_error<std::monostate>(
578 "Logger not initialized",
584 pimpl_->collector_->flush();
587 std::vector<std::shared_ptr<log_writer_interface>> local_writers;
589 std::shared_lock<std::shared_mutex> lock(
pimpl_->writers_mutex_);
590 local_writers =
pimpl_->writers_;
593 for (
auto& writer : local_writers) {
608 pimpl_->metrics_enabled_ = enable;
616bool logger::is_metrics_collection_enabled()
const {
624 "Logger not initialized"};
627 if (!
pimpl_->metrics_enabled_) {
630 "Metrics collection is not enabled"};
640int logger::get_emergency_fd()
const {
644 return pimpl_->emergency_fd_.load(std::memory_order_acquire);
647const char* logger::get_emergency_buffer()
const {
651 return pimpl_->emergency_buffer_;
654size_t logger::get_emergency_buffer_size()
const {
658 return pimpl_->emergency_buffer_used_.load(std::memory_order_acquire);
663void logger::set_filter(std::unique_ptr<log_filter_interface> filter) {
665 std::lock_guard<std::shared_mutex> lock(
pimpl_->filter_mutex_);
666 pimpl_->filter_ = std::move(filter);
670bool logger::has_filter()
const {
674 std::shared_lock<std::shared_mutex> lock(
pimpl_->filter_mutex_);
675 return pimpl_->filter_ !=
nullptr;
682 throw std::runtime_error(
"Logger not initialized");
684 std::shared_lock<std::shared_mutex> lock(
pimpl_->router_mutex_);
690 throw std::runtime_error(
"Logger not initialized");
692 std::shared_lock<std::shared_mutex> lock(
pimpl_->router_mutex_);
696void logger::set_router(std::unique_ptr<log_router> router) {
698 std::lock_guard<std::shared_mutex> lock(
pimpl_->router_mutex_);
699 pimpl_->router_ = std::move(router);
703bool logger::has_routing()
const {
707 std::shared_lock<std::shared_mutex> lock(
pimpl_->router_mutex_);
710 return pimpl_->router_ !=
nullptr;
721 ctx_fields =
pimpl_->context_.to_fields();
728 if (!
pimpl_ || !meets_threshold(level,
pimpl_->min_level_.load())) {
734 std::shared_lock<std::shared_mutex> filter_lock(
pimpl_->filter_mutex_);
736 if (!
pimpl_->filter_->should_log(entry)) {
743 std::string file_str;
745 std::string func_str;
746 if (entry.location) {
747 file_str = entry.location->file.to_string();
748 line = entry.location->line;
749 func_str = entry.location->function.to_string();
752 pimpl_->dispatch_to_writers(
754 entry.message.to_string(),
761 ctx_fields.empty() ?
nullptr : &ctx_fields
785#ifdef LOGGER_WITH_ANALYSIS
786void logger::set_realtime_analyzer(std::unique_ptr<analysis::realtime_log_analyzer> analyzer) {
788 std::lock_guard<std::shared_mutex> lock(
pimpl_->analyzer_mutex_);
789 pimpl_->realtime_analyzer_ = std::move(analyzer);
793analysis::realtime_log_analyzer* logger::get_realtime_analyzer() {
795 std::shared_lock<std::shared_mutex> lock(
pimpl_->analyzer_mutex_);
796 return pimpl_->realtime_analyzer_.get();
801const analysis::realtime_log_analyzer* logger::get_realtime_analyzer()
const {
803 std::shared_lock<std::shared_mutex> lock(
pimpl_->analyzer_mutex_);
804 return pimpl_->realtime_analyzer_.get();
809bool logger::has_realtime_analysis()
const {
811 std::shared_lock<std::shared_mutex> lock(
pimpl_->analyzer_mutex_);
812 return pimpl_->realtime_analyzer_ !=
nullptr;
822void logger::set_sampler(std::unique_ptr<sampling::log_sampler> sampler) {
824 std::lock_guard<std::shared_mutex> lock(
pimpl_->sampler_mutex_);
825 pimpl_->sampler_ = std::move(sampler);
831 std::shared_lock<std::shared_mutex> lock(
pimpl_->sampler_mutex_);
832 return pimpl_->sampler_.get();
839 std::shared_lock<std::shared_mutex> lock(
pimpl_->sampler_mutex_);
840 return pimpl_->sampler_.get();
845bool logger::has_sampling()
const {
847 std::shared_lock<std::shared_mutex> lock(
pimpl_->sampler_mutex_);
848 return pimpl_->sampler_ !=
nullptr &&
pimpl_->sampler_->is_enabled();
855 std::shared_lock<std::shared_mutex> lock(
pimpl_->sampler_mutex_);
857 return pimpl_->sampler_->get_stats();
863void logger::reset_sampling_stats() {
865 std::shared_lock<std::shared_mutex> lock(
pimpl_->sampler_mutex_);
867 pimpl_->sampler_->reset_stats();
Base interface for all log writers and decorators.
std::atomic< size_t > emergency_buffer_used_
unified_log_context context_
void dispatch_to_writers(log_level level, const std::string &message, const std::string &file, int line, const std::string &function, const log_entry &entry)
Dispatch log to writers with routing support.
std::unique_ptr< log_filter_interface > filter_
std::unordered_map< std::string, std::shared_ptr< log_writer_interface > > named_writers_
std::unique_ptr< backends::integration_backend > backend_
impl(bool async, std::size_t buffer_size, std::unique_ptr< backends::integration_backend > backend)
std::unique_ptr< log_collector > collector_
std::shared_mutex sampler_mutex_
static constexpr size_t emergency_buffer_size_
std::shared_mutex router_mutex_
std::atomic< log_level > min_level_
std::shared_mutex writers_mutex_
char emergency_buffer_[emergency_buffer_size_]
std::unique_ptr< sampling::log_sampler > sampler_
std::shared_mutex filter_mutex_
std::unique_ptr< log_router > router_
std::vector< std::shared_ptr< log_writer_interface > > writers_
std::atomic< int > emergency_fd_
std::unique_ptr< impl > pimpl_
common::VoidResult stop()
Stop the logger.
common::VoidResult flush() override
Flush any buffered log messages (ILogger interface)
static result ok_value(const T &value)
Log router for directing messages to specific writers.
Thread-safe log sampler with multiple strategy support.
Fluent builder for creating structured log entries.
Unified interface for managing all types of logging context.
Asynchronous log collector using C++20 std::jthread kcenon.
Data structures for representing log entries and source locations kcenon.
Interface for log filters used by filtered_logger.
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.
common::interfaces::log_level log_level
void record_message_logged(uint64_t time_ns)
Record a logged message.
LOGGER_SYSTEM_API logger_performance_stats g_logger_stats
Global logger metrics instance.
std::unordered_map< std::string, log_value > log_fields
Type alias for structured fields map.
common::VoidResult make_logger_void_result(logger_error_code code, const std::string &message="")
std::unique_ptr< log_writer_interface > log_writer_ptr
Type alias for writer unique pointer.
Real-time log analysis with anomaly detection.
Standalone integration backend implementation kcenon.
std::string function_name
std::chrono::system_clock::time_point timestamp
Represents a single log entry with all associated metadata.
std::chrono::system_clock::time_point timestamp
Timestamp when the log entry was created.
Statistics about sampling behavior.
Conditionally enables thread_system integration when available.
Unified interface for managing all types of logging context.