27static consteval const char *sourceFileName(
const char *path) {
28 const char *
ret = path;
29 for(
const char *p = path; *p; ++p) {
30 if(*p ==
'/' || *p ==
'\\')
ret = p + 1;
36#define PROMEKI_SOURCE_FILE __FILE_NAME__
38#define PROMEKI_SOURCE_FILE promeki::sourceFileName(__FILE__)
43#define PROMEKI_DEBUG(name) \
45 [[maybe_unused]] static const char *_promeki_debug_name = PROMEKI_STRINGIFY(name); \
46 [[maybe_unused]] static bool _promeki_debug_enabled = \
47 promekiRegisterDebug(&_promeki_debug_enabled, PROMEKI_STRINGIFY(name), PROMEKI_SOURCE_FILE, __LINE__); \
50#define promekiLogImpl(_plevel, format, ...) \
51 do { if(!(_plevel) || (_plevel) >= Logger::defaultLogger().level()) \
52 Logger::defaultLogger().log(_plevel, PROMEKI_SOURCE_FILE, __LINE__, String::sprintf(format, ##__VA_ARGS__)); \
54#define promekiLog(level, format, ...) promekiLogImpl(level, format, ##__VA_ARGS__)
55#define promekiLogSync() Logger::defaultLogger().sync()
56#define promekiLogStackTrace(_plevel) \
57 do { if(!(_plevel) || (_plevel) >= Logger::defaultLogger().level()) \
58 Logger::defaultLogger().log(_plevel, PROMEKI_SOURCE_FILE, __LINE__, promekiStackTrace()); \
61#ifdef PROMEKI_DEBUG_ENABLE
62#define promekiDebug(format, ...) if(_promeki_debug_enabled) { promekiLog(Logger::LogLevel::Debug, format, ##__VA_ARGS__); }
64#define promekiDebug(format, ...)
67#define promekiInfo(format, ...) promekiLog(Logger::LogLevel::Info, format, ##__VA_ARGS__)
68#define promekiWarn(format, ...) promekiLog(Logger::LogLevel::Warn, format, ##__VA_ARGS__)
69#define promekiErr(format, ...) promekiLog(Logger::LogLevel::Err, format, ##__VA_ARGS__)
71bool promekiRegisterDebug(
bool *
enabler,
const char *name,
const char *file,
int line);
73#define PROMEKI_BENCHMARK_BEGIN(name) \
74 TimeStamp _promeki_debug_timestamp_##name; \
75 if(_promeki_debug_enabled) { _promeki_debug_timestamp_##name = TimeStamp::now(); }
77#define PROMEKI_BENCHMARK_END(name) \
78 if(_promeki_debug_enabled) { \
79 Logger::defaultLogger().log(Logger::LogLevel::Debug, __FILE__, __LINE__, String::sprintf("[%s] %s took %.9lf sec", \
80 _promeki_debug_name, PROMEKI_STRINGIFY(name), _promeki_debug_timestamp_##name.elapsedSeconds())); \
182 _queue.
emplace(CmdTerminate{});
191 return _level.
value();
225 _queue.
emplace(CmdSetFile{filename});
252 return _fileFormatter;
260 return _consoleFormatter;
273 _queue.
emplace(CmdSetFormatter{std::move(formatter),
false});
286 _queue.
emplace(CmdSetFormatter{std::move(formatter),
true});
297 auto p = std::make_shared<Promise<void>>();
299 _queue.
emplace(CmdSync{std::move(p)});
309 struct CmdSetThreadName {
318 struct CmdSetFormatter {
324 std::shared_ptr<Promise<void>> promise;
327 struct CmdTerminate {};
329 using Command = std::variant<LogEntry, CmdSetThreadName, CmdSetFile, CmdSetFormatter, CmdSync, CmdTerminate>;
335 mutable Mutex _formatterMutex;
void setValue(T val)
Stores a new value with release semantics.
Definition atomic.h:54
T value() const
Loads the current value with acquire semantics.
Definition atomic.h:46
Wall-clock date and time based on std::chrono::system_clock.
Definition datetime.h:39
Lightweight error code wrapper for the promeki library.
Definition error.h:39
@ Ok
No error.
Definition error.h:51
IODevice wrapping a C stdio FILE pointer.
Definition fileiodevice.h:47
Dynamic array container wrapping std::vector.
Definition list.h:40
Asynchronous thread-safe logging facility.
Definition logger.h:102
void setLogLevel(LogLevel level)
Changes the minimum log level.
Definition logger.h:232
void setConsoleLoggingEnabled(bool val)
Enables or disables console (stderr) log output.
Definition logger.h:242
void log(LogLevel loglevel, const char *file, int line, const StringList &lines)
Enqueues multiple log messages with the same timestamp.
void setLogFile(const String &filename)
Sets the log output file.
Definition logger.h:224
static Logger & defaultLogger()
Returns the singleton default Logger instance.
int level() const
Returns the current minimum log level.
Definition logger.h:190
static LogFormatter defaultFileFormatter()
Returns the default file log formatter.
static char levelToChar(LogLevel level)
Converts a LogLevel to its single character representation.
static void setThreadName(const String &name)
Updates the cached thread name used in log output.
void setFileFormatter(LogFormatter formatter)
Sets a custom formatter for file log output.
Definition logger.h:268
Error sync(unsigned int timeoutMs=0)
Blocks until all queued log commands have been processed.
Definition logger.h:296
void setConsoleFormatter(LogFormatter formatter)
Sets a custom formatter for console log output.
Definition logger.h:281
Logger()
Constructs a Logger and starts the worker thread.
LogLevel
Severity levels for log messages.
Definition logger.h:105
@ Force
Forced messages are always logged.
Definition logger.h:106
@ Err
Error messages.
Definition logger.h:110
@ Debug
Debug-level messages.
Definition logger.h:107
@ Info
Informational messages.
Definition logger.h:108
@ Warn
Warning messages.
Definition logger.h:109
~Logger()
Destructor. Signals the worker thread to terminate and waits for it to finish.
Definition logger.h:181
static LogFormatter defaultConsoleFormatter()
Returns the default console log formatter.
LogFormatter fileFormatter() const
Returns the current file log formatter.
Definition logger.h:250
void log(LogLevel loglevel, const char *file, int line, const String &msg)
Enqueues a single log message.
std::function< String(const LogFormat &fmt)> LogFormatter
Function type for formatting log messages.
Definition logger.h:135
LogFormatter consoleFormatter() const
Returns the current console log formatter.
Definition logger.h:258
RAII scoped locker for Mutex.
Definition mutex.h:41
Mutual exclusion lock wrapping std::mutex.
Definition mutex.h:33
void emplace(Args &&... args)
Constructs an element in-place at the back of the queue.
Definition queue.h:78
Manages a list of strings.
Definition stringlist.h:21
Encoding-aware string class with copy-on-write semantics.
Definition string.h:35
static String sprintf(const char *fmt,...)
Creates a formatted string using printf-style syntax.
#define PROMEKI_NAMESPACE_BEGIN
Starts a promeki namespace block.
Definition namespace.h:14
#define PROMEKI_NAMESPACE_END
Ends a promeki namespace block.
Definition namespace.h:19
A single log entry.
Definition logger.h:114