#include "log.hpp" #include "zephyr/kernel.h" #include #include #include namespace rims { K_FIFO_DEFINE(klogFifoQueue); fifo_queue logEgressQueue{klogFifoQueue}; static std::size_t g_droppedLogs{0}; void Log::trace(const char *fmt, ...) const { va_list args; va_start(args, fmt); formatLog(Level::Trace, fmt, args); va_end(args); } void Log::debug(const char *fmt, ...) const { va_list args; va_start(args, fmt); formatLog(Level::Debug, fmt, args); va_end(args); } void Log::info(const char *fmt, ...) const { va_list args; va_start(args, fmt); formatLog(Level::Info, fmt, args); va_end(args); } void Log::warning(const char *fmt, ...) const { va_list args; va_start(args, fmt); formatLog(Level::Warning, fmt, args); va_end(args); } void Log::error(const char *fmt, ...) const { va_list args; va_start(args, fmt); formatLog(Level::Error, fmt, args); va_end(args); } void Log::critical(const char *fmt, ...) const { va_list args; va_start(args, fmt); formatLog(Level::Critical, fmt, args); va_end(args); } static constexpr log_LogLevel toPbLogLevel(Log::Level level) { return static_cast(level); } static void setBasename(char *destination, const char *path) { const char *basename = strrchr(path, '/'); // Find the last occurrence of '/' if (basename) { basename++; // Move past the '/' } else { basename = path; // No '/' found, use the whole string } strncpy(destination, basename, 31); // Copy basename, leaving space for null terminator destination[31] = '\0'; // Ensure null termination } void Log::formatLog(Level level, const char *fmt, va_list args) const { if (should_log(level)) { // handle case when queue if full and we are waitnig for free space bool ok{false}; do { ok = logEgressQueue.try_produce([this, &args, &fmt, level](log_EgressMessage &logmsg) { logmsg = log_EgressMessage_init_zero; logmsg.has_request_id = false; logmsg.which_data = log_EgressMessage_logEntry_tag; logmsg.data.logEntry.systick = k_uptime_ticks(); logmsg.data.logEntry.level = toPbLogLevel(level); logmsg.data.logEntry.lineNumber = this->_sl.line(); setBasename(logmsg.data.logEntry.sourceFile, this->_sl.file_name()); /// to long logs are trimmed, fuck them vsnprintf(logmsg.data.logEntry.logLine, sizeof(logmsg.data.logEntry.logLine), fmt, args); return true; }); // this is out of scope of try_produce, no spinlock will be invalidated if (not ok) { g_droppedLogs++; std::this_thread::sleep_for(std::chrono::microseconds{100}); } } while (not ok); } } } // namespace rims