diff --git a/src/damaris/backend/logging_helper.h b/src/damaris/backend/logging_helper.h new file mode 100644 index 0000000..2c8765a --- /dev/null +++ b/src/damaris/backend/logging_helper.h @@ -0,0 +1,134 @@ +// -*- C++ -*- +/** + * @file logging_helper.h + * @brief Lightweight logging helper for the DAMARIS C++ backend. + * + * Writes structured log messages to stdout in a format parseable by the + * Python FileTailerHandler: + * + * [LEVEL] message + * + * Levels: DEBUG, INFO, WARNING, ERROR, CRITICAL + * + * Usage in C++ code: + * #include "logging_helper.h" + * log_info("Starting backend, spool=%s", spool_dir.c_str()); + * log_error("Failed to open device: %s", strerror(errno)); + */ + +#ifndef DAMARIS_LOGGING_HELPER_H +#define DAMARIS_LOGGING_HELPER_H + +#include +#include +#include +#include +#include + +namespace damaris { +namespace logging { + +// --------------------------------------------------------------------------- +// Internal helpers +// --------------------------------------------------------------------------- + +inline std::string timestamp() { + char buf[32]; + time_t now = time(nullptr); + struct tm tm_buf; +#ifdef _WIN32 + localtime_s(&tm_buf, &now); +#else + localtime_r(&now, &tm_buf); +#endif + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm_buf); + return std::string(buf); +} + +inline void log_message(int level, const char* fmt, ...) { + const char* level_str = "INFO"; + switch (level) { + case 0: level_str = "DEBUG"; break; + case 1: level_str = "INFO"; break; + case 2: level_str = "WARNING"; break; + case 3: level_str = "ERROR"; break; + case 4: level_str = "CRITICAL"; break; + } + + char msg[4096]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + + fprintf(stdout, "[%s] %s\n", level_str, msg); + fflush(stdout); +} + +// --------------------------------------------------------------------------- +// Convenience macros / inline functions +// --------------------------------------------------------------------------- + +inline void log_debug(const char* fmt, ...) { + char msg[4096]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + fprintf(stdout, "[DEBUG] %s\n", msg); + fflush(stdout); +} + +inline void log_info(const char* fmt, ...) { + char msg[4096]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + fprintf(stdout, "[INFO] %s\n", msg); + fflush(stdout); +} + +inline void log_warning(const char* fmt, ...) { + char msg[4096]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + fprintf(stdout, "[WARNING] %s\n", msg); + fflush(stdout); +} + +inline void log_error(const char* fmt, ...) { + char msg[4096]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + fprintf(stdout, "[ERROR] %s\n", msg); + fflush(stdout); +} + +inline void log_critical(const char* fmt, ...) { + char msg[4096]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + fprintf(stdout, "[CRITICAL] %s\n", msg); + fflush(stdout); +} + +} // namespace logging +} // namespace damaris + +// --------------------------------------------------------------------------- +// Optional C-style macros for convenience +// --------------------------------------------------------------------------- +#define DAMARIS_LOG_DEBUG(fmt, ...) damaris::logging::log_debug(fmt, ##__VA_ARGS__) +#define DAMARIS_LOG_INFO(fmt, ...) damaris::logging::log_info(fmt, ##__VA_ARGS__) +#define DAMARIS_LOG_WARNING(fmt, ...) damaris::logging::log_warning(fmt, ##__VA_ARGS__) +#define DAMARIS_LOG_ERROR(fmt, ...) damaris::logging::log_error(fmt, ##__VA_ARGS__) +#define DAMARIS_LOG_CRITICAL(fmt, ...) damaris::logging::log_critical(fmt, ##__VA_ARGS__) + +#endif // DAMARIS_LOGGING_HELPER_H