LogIt++
Loading...
Searching...
No Matches
Logger.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef _LOGIT_LOGGER_HPP_INCLUDED
3#define _LOGIT_LOGGER_HPP_INCLUDED
4
7
8#include "loggers/ILogger.hpp"
9#include "formatter.hpp"
11#include <memory>
12#include <mutex>
13#include <sstream>
14#include <atomic>
15
16namespace logit {
17
24 class Logger {
25 public:
26
29 static Logger& get_instance() {
30 static Logger* instance = new Logger();
31 return *instance;
32 }
33
41 std::unique_ptr<ILogger> logger,
42 std::unique_ptr<ILogFormatter> formatter,
43 bool single_mode = false) {
44 if (m_shutdown) return;
45 std::lock_guard<std::mutex> lock(m_mutex);
46 m_loggers.push_back(
47 LoggerStrategy{std::move(logger),
48 std::move(formatter),
49 single_mode,
50 true // Loggers are enabled by default
51 });
52 }
53
57 void set_logger_enabled(int logger_index, bool enabled) {
58 if (m_shutdown) return;
59 std::lock_guard<std::mutex> lock(m_mutex);
60 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
61 m_loggers[logger_index].enabled = enabled;
62 }
63 }
64
68 bool is_logger_enabled(int logger_index) const {
69 std::lock_guard<std::mutex> lock(m_mutex);
70 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
71 return m_loggers[logger_index].enabled;
72 }
73 return false;
74 }
75
79 void set_logger_single_mode(int logger_index, bool single_mode) {
80 if (m_shutdown) return;
81 std::lock_guard<std::mutex> lock(m_mutex);
82 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
83 m_loggers[logger_index].single_mode = single_mode;
84 }
85 }
86
90 void set_timestamp_offset(int logger_index, int64_t offset_ms) {
91 if (m_shutdown) return;
92 std::lock_guard<std::mutex> lock(m_mutex);
93 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
94 m_loggers[logger_index].formatter->set_timestamp_offset(offset_ms);
95 }
96 }
97
101 if (m_shutdown) return;
102 std::lock_guard<std::mutex> lock(m_mutex);
103 for (auto& strategy : m_loggers) {
104 strategy.logger->set_log_level(level);
105 }
106 }
107
111 void set_log_level(int logger_index, LogLevel level) {
112 if (m_shutdown) return;
113 std::lock_guard<std::mutex> lock(m_mutex);
114 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
115 m_loggers[logger_index].logger->set_log_level(level);
116 }
117 }
118
122 bool is_logger_single_mode(int logger_index) const {
123 if (m_shutdown) return false;
124 std::lock_guard<std::mutex> lock(m_mutex);
125 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
126 return m_loggers[logger_index].single_mode;
127 }
128 return false;
129 }
130
136 void log(const LogRecord& record) {
137 if (m_shutdown) return;
138 std::lock_guard<std::mutex> lock(m_mutex);
139 // Log to the specific logger if the index is valid
140 if (record.logger_index >= 0 && record.logger_index < static_cast<int>(m_loggers.size())) {
141 const auto& strategy = m_loggers[record.logger_index];
142 if (!strategy.enabled) return;
143 if (static_cast<int>(record.log_level) < static_cast<int>(strategy.logger->get_log_level())) return;
144 strategy.logger->log(record, strategy.formatter->format(record));
145 return;
146 }
147 for (const auto& strategy : m_loggers) {
148 if (strategy.single_mode) continue;
149 if (!strategy.enabled) continue;
150 if (static_cast<int>(record.log_level) < static_cast<int>(strategy.logger->get_log_level())) continue;
151 strategy.logger->log(record, strategy.formatter->format(record));
152 }
153 }
154
159 std::string get_string_param(int logger_index, const LoggerParam& param) const {
160 if (m_shutdown) return std::string();
161 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
162 const auto& strategy = m_loggers[logger_index];
163 return strategy.logger->get_string_param(param);
164 }
165 return std::string();
166 }
167
172 int64_t get_int_param(int logger_index, const LoggerParam& param) const {
173 if (m_shutdown) return 0;
174 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
175 const auto& strategy = m_loggers[logger_index];
176 return strategy.logger->get_int_param(param);
177 }
178 return 0;
179 }
180
185 double get_float_param(int logger_index, const LoggerParam& param) const {
186 if (m_shutdown) return 0.0;
187 if (logger_index >= 0 && logger_index < static_cast<int>(m_loggers.size())) {
188 const auto& strategy = m_loggers[logger_index];
189 return strategy.logger->get_float_param(param);
190 }
191 return 0.0;
192 }
193
199 template <typename... Ts>
200 auto log_and_return(const LogRecord& record, Ts&&... args) -> decltype(std::forward_as_tuple(std::forward<Ts>(args)...)) {
201 this->print(record, args...);
202 return std::forward_as_tuple(std::forward<Ts>(args)...);
203 }
204
212 template <typename T>
213 auto log_and_return(const LogRecord& record, T&& args) -> decltype(args) {
214 this->print(record, args);
215 return std::forward<decltype(args)>(args);
216 }
217
221 auto log_and_return(const LogRecord& record) -> std::tuple<> {
222 this->print(record);
223 return {};
224 }
225
229 void wait() {
230 for (const auto& strategy : m_loggers) {
231 strategy.logger->wait();
232 }
233 }
234
239 void shutdown() {
240 if (m_shutdown) return;
241 m_shutdown = true;
242 wait();
244 }
245
246 private:
247
251 std::unique_ptr<ILogger> logger;
252 std::unique_ptr<ILogFormatter> formatter;
254 bool enabled;
255 };
256
257 std::vector<LoggerStrategy> m_loggers;
258 mutable std::mutex m_mutex;
259 std::atomic<bool> m_shutdown = ATOMIC_VAR_INIT(false);
260
261 void print(const LogRecord& record) {
262 log(record);
263 }
264
265#ifdef _MSC_VER
266# pragma warning(push)
267# pragma warning(disable: 4127) // conditional expression is constant
268#endif
269
274 template <typename... Ts>
275 void print(const LogRecord& record, Ts const&... args) {
276 if (sizeof...(Ts) == 0) {
277 log(record);
278 return;
279 }
280 LogRecord mutable_record = record;
281 auto var_names = split_arguments(mutable_record.arg_names);
282 mutable_record.args_array = args_to_array(var_names.begin(), args...);
283 log(mutable_record);
284 }
285
286#ifdef _MSC_VER
287# pragma warning(pop)
288#endif
289
291 std::atexit(Logger::on_exit_handler);
292 }
293
295 shutdown();
296 }
297
298 // Deleting copy and move constructors and assignment operators to enforce singleton.
299 Logger(const Logger&) = delete;
300 Logger& operator=(const Logger&) = delete;
301 Logger(Logger&&) = delete;
302 Logger& operator=(Logger&&) = delete;
303
306 static void on_exit_handler() {
308 }
309 };
310
311}; // namespace logit
312
313#endif // _LOGIT_LOGGER_HPP_INCLUDED
Defines the interface for loggers used in the logging system.
Defines the TaskExecutor class, which manages task execution in a separate thread.
auto log_and_return(const LogRecord &record) -> std::tuple<>
Logs message without arguments and returns empty tuple.
Definition Logger.hpp:221
auto log_and_return(const LogRecord &record, T &&args) -> decltype(args)
Logs message and returns argument.
Definition Logger.hpp:213
void set_logger_enabled(int logger_index, bool enabled)
Enables or disables a logger by index.
Definition Logger.hpp:57
void wait()
Waits for all asynchronous loggers to finish processing.
Definition Logger.hpp:229
void log(const LogRecord &record)
Logs a LogRecord using added loggers and formatters.
Definition Logger.hpp:136
void set_logger_single_mode(int logger_index, bool single_mode)
Sets single-mode flag for a logger.
Definition Logger.hpp:79
void set_timestamp_offset(int logger_index, int64_t offset_ms)
Sets timestamp offset for a specific logger.
Definition Logger.hpp:90
void add_logger(std::unique_ptr< ILogger > logger, std::unique_ptr< ILogFormatter > formatter, bool single_mode=false)
Adds a logger and its corresponding formatter.
Definition Logger.hpp:40
Logger & operator=(const Logger &)=delete
Logger(const Logger &)=delete
void shutdown()
Shuts down logger system.
Definition Logger.hpp:239
void set_log_level(int logger_index, LogLevel level)
Sets minimal log level for a specific logger.
Definition Logger.hpp:111
std::vector< LoggerStrategy > m_loggers
Container for logger-formatter pairs.
Definition Logger.hpp:257
void set_log_level(LogLevel level)
Sets minimal log level for all loggers.
Definition Logger.hpp:100
std::mutex m_mutex
Mutex for thread safety during logging operations.
Definition Logger.hpp:258
void print(const LogRecord &record)
Definition Logger.hpp:261
bool is_logger_single_mode(int logger_index) const
Checks whether a logger is in single mode.
Definition Logger.hpp:122
std::atomic< bool > m_shutdown
Flag indicating if shutdown was requested.
Definition Logger.hpp:259
double get_float_param(int logger_index, const LoggerParam &param) const
Retrieves a floating-point parameter from a logger.
Definition Logger.hpp:185
std::string get_string_param(int logger_index, const LoggerParam &param) const
Retrieves a string parameter from a logger.
Definition Logger.hpp:159
auto log_and_return(const LogRecord &record, Ts &&... args) -> decltype(std::forward_as_tuple(std::forward< Ts >(args)...))
Logs message and returns tuple of arguments.
Definition Logger.hpp:200
int64_t get_int_param(int logger_index, const LoggerParam &param) const
Retrieves an integer parameter from a logger.
Definition Logger.hpp:172
static void on_exit_handler()
Atexit shutdown handler for Logger and TaskExecutor.
Definition Logger.hpp:306
bool is_logger_enabled(int logger_index) const
Checks if a logger is enabled.
Definition Logger.hpp:68
static Logger & get_instance()
Retrieves singleton instance of Logger.
Definition Logger.hpp:29
Logger & operator=(Logger &&)=delete
Logger(Logger &&)=delete
void print(const LogRecord &record, Ts const &... args)
Logs a record with given arguments.
Definition Logger.hpp:275
void shutdown()
Shuts down the TaskExecutor by stopping the worker thread.
static TaskExecutor & get_instance()
Get the singleton instance of the TaskExecutor.
Aggregates all formatter components for convenient inclusion.
The primary namespace for the LogIt++ library.
std::vector< VariableValue > args_to_array(std::vector< std::string >::const_iterator)
Base case of recursion for argument conversion — when there are no more arguments.
std::vector< std::string > split_arguments(const std::string &all_names)
Splits a string of argument names into individual names, ignoring nested templates,...
LogLevel
Logging levels.
Definition enums.hpp:15
LoggerParam
Enumeration for different logger parameters that can be retrieved.
Definition enums.hpp:47
Stores log metadata and content.
Definition LogRecord.hpp:17
const int logger_index
Logger index (-1 to log to all).
Definition LogRecord.hpp:27
const LogLevel log_level
Log level (severity).
Definition LogRecord.hpp:18
const std::string format
Format string for the message.
Definition LogRecord.hpp:23
std::vector< VariableValue > args_array
Argument values for the log.
Definition LogRecord.hpp:25
const std::string arg_names
Argument names for the log.
Definition LogRecord.hpp:24
Structure to hold a logger-formatter pair.
Definition Logger.hpp:250
std::unique_ptr< ILogger > logger
The logger instance.
Definition Logger.hpp:251
bool single_mode
Flag indicating if the logger is in single mode.
Definition Logger.hpp:253
std::unique_ptr< ILogFormatter > formatter
The formatter instance.
Definition Logger.hpp:252
bool enabled
Flag indicating if the logger is enabled.
Definition Logger.hpp:254