Database System 0.1.0
Advanced C++20 Database System with Multi-Backend Support
Loading...
Searching...
No Matches
fallback_logger_backend.cpp
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
6
7#include <chrono>
8#include <ctime>
9#include <filesystem>
10#include <iomanip>
11#include <iostream>
12#include <sstream>
13#include <stdexcept>
14
15namespace
16{
17 inline common::VoidResult make_error(const std::string& msg, int code = -1)
18 {
19 return common::VoidResult(common::error_info{ code, msg, "" });
20 }
21
25 std::string format_timestamp()
26 {
27 auto now = std::chrono::system_clock::now();
28 auto time_t_now = std::chrono::system_clock::to_time_t(now);
29 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
30
31 std::stringstream ss;
32 ss << std::put_time(std::localtime(&time_t_now), "%Y-%m-%d %H:%M:%S");
33 ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
34 return ss.str();
35 }
36
40 const char* log_level_to_string(database::integrated::db_log_level level)
41 {
43
44 switch (level)
45 {
46 case db_log_level::trace:
47 return "TRACE";
48 case db_log_level::debug:
49 return "DEBUG";
50 case db_log_level::info:
51 return "INFO ";
52 case db_log_level::warning:
53 return "WARN ";
54 case db_log_level::error:
55 return "ERROR";
56 case db_log_level::critical:
57 return "CRIT ";
58 case db_log_level::fatal:
59 return "FATAL";
60 default:
61 return "UNKN ";
62 }
63 }
64}
65
66namespace database
67{
68namespace integrated
69{
70namespace adapters
71{
72namespace backends
73{
74
76 : config_(config), initialized_(false)
77{
78}
79
87
89{
90 if (initialized_)
91 {
92 return common::ok();
93 }
94
95 try
96 {
97 // Open log file if file logging enabled
99 {
100 // Create directory if it doesn't exist
101 std::filesystem::path log_dir(config_.log_directory);
102 if (!std::filesystem::exists(log_dir))
103 {
104 std::filesystem::create_directories(log_dir);
105 }
106
107 std::string log_path = config_.log_directory + "/database.log";
108 log_file_.open(log_path, std::ios::app);
109 if (!log_file_.is_open())
110 {
111 return make_error("Failed to open log file: " + log_path);
112 }
113 }
114
115 initialized_ = true;
116 return common::ok();
117 }
118 catch (const std::exception& e)
119 {
120 return make_error(std::string("Logger initialization failed: ") + e.what());
121 }
122}
123
125{
126 if (!initialized_)
127 {
128 return common::ok();
129 }
130
131 try
132 {
133 std::lock_guard<std::mutex> lock(mutex_);
134 if (log_file_.is_open())
135 {
136 log_file_.flush();
137 log_file_.close();
138 }
139 initialized_ = false;
140 return common::ok();
141 }
142 catch (const std::exception& e)
143 {
144 return make_error(std::string("Logger shutdown failed: ") + e.what());
145 }
146}
147
149{
150 return initialized_;
151}
152
153void fallback_logger_backend::log(db_log_level level, const std::string& message)
154{
155 if (!initialized_)
156 {
157 return;
158 }
159
160 // Check if this level should be logged
161 if (level < config_.min_log_level)
162 {
163 return;
164 }
165
166 std::lock_guard<std::mutex> lock(mutex_);
167
168 // Format: [2025-01-03 14:30:45.123] [INFO ] message
169 std::string log_line
170 = "[" + format_timestamp() + "] [" + log_level_to_string(level) + "] " + message;
171
172 // Write to console
173 std::cout << log_line << std::endl;
174
175 // Write to file if enabled
176 if (config_.enable_file_logging && log_file_.is_open())
177 {
178 log_file_ << log_line << std::endl;
179 }
180}
181
183{
184 std::lock_guard<std::mutex> lock(mutex_);
185 std::cout.flush();
186 if (log_file_.is_open())
187 {
188 log_file_.flush();
189 }
190}
191
192} // namespace backends
193} // namespace adapters
194} // namespace integrated
195} // namespace database
common::VoidResult shutdown() override
Shutdown the logger backend gracefully.
common::VoidResult initialize() override
Initialize the logger backend.
void log(db_log_level level, const std::string &message) override
Log a message.
bool is_initialized() const override
Check if backend is initialized.
fallback_logger_backend(const db_logger_config &config)
Construct fallback logger backend.
Fallback logger backend using std::cout and std::ofstream.
VoidResult ok()
Result< std::monostate > VoidResult
db_log_level
Database logging level enumeration.
bool enable_file_logging
Enable logging to file (in addition to console)
std::string log_directory
Directory for log files.
db_log_level min_log_level
Minimum log level to output.