From 0c3cc549b66d47a568f7c9c18a6665db46ae63bf Mon Sep 17 00:00:00 2001 From: Mateusz Grzegorzek Date: Fri, 4 Dec 2020 09:58:11 +0100 Subject: [PATCH] [EGD-4706] Change log for RT1051 and Linux platform Unify log for RT1051 and linux platform. Add Logger class where common functions for RT1051 and Linux are stored. --- module-utils/CMakeLists.txt | 2 + module-utils/board/cross/log.cpp | 351 ------------------------ module-utils/board/cross/log_rt1051.cpp | 120 ++++++++ module-utils/board/linux/log.cpp | 137 --------- module-utils/board/linux/log_linux.cpp | 55 ++++ module-utils/log/Logger.cpp | 95 +++++++ module-utils/log/Logger.hpp | 69 +++++ module-utils/log/log.cpp | 35 +++ module-utils/log/log.hpp | 4 +- module-utils/targets/Target_Cross.cmake | 2 +- module-utils/targets/Target_Linux.cmake | 2 +- 11 files changed, 380 insertions(+), 492 deletions(-) delete mode 100644 module-utils/board/cross/log.cpp create mode 100644 module-utils/board/cross/log_rt1051.cpp delete mode 100644 module-utils/board/linux/log.cpp create mode 100644 module-utils/board/linux/log_linux.cpp create mode 100644 module-utils/log/Logger.cpp create mode 100644 module-utils/log/Logger.hpp create mode 100644 module-utils/log/log.cpp diff --git a/module-utils/CMakeLists.txt b/module-utils/CMakeLists.txt index 60c5c3f09708c720620193cc2ea1ab4a5126648f..092a226bf4885975798ee2849ba9ad2880ea4036 100644 --- a/module-utils/CMakeLists.txt +++ b/module-utils/CMakeLists.txt @@ -36,6 +36,8 @@ set (SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/ical/ParserICS.cpp ${CMAKE_CURRENT_SOURCE_DIR}/time/TimeRangeParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Utils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/log/Logger.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/log/log.cpp ) add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES}) diff --git a/module-utils/board/cross/log.cpp b/module-utils/board/cross/log.cpp deleted file mode 100644 index 9e7f1162925d2c4278aa24c6452743b812d95670..0000000000000000000000000000000000000000 --- a/module-utils/board/cross/log.cpp +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include "../../log/log.hpp" -#include "../../segger/rtt/SEGGER_RTT.h" -#include -extern "C" -{ -#include "FreeRTOS.h" -} -#include "semphr.h" -#include -#include -#include - -/* - * TODO: M.P - * Redictering log output to serial console in this form need be considered as quick&dirty solution. - * It should be refactored i.e serial terminal BSP created and used here instead of using RT1051's low-level routines - * directly. - */ - -#define LOGGER_BUFFER_SIZE 4096 - -#if LOG_USE_COLOR == 1 -#define CONSOLE_ESCAPE_COLOR_BLACK "\x1b[30m" -#define CONSOLE_ESCAPE_COLOR_RED "\x1b[31m" -#define CONSOLE_ESCAPE_COLOR_GREEN "\x1b[32m" -#define CONSOLE_ESCAPE_COLOR_YELLOW "\x1b[33m" -#define CONSOLE_ESCAPE_COLOR_BLUE "\x1b[34m" -#define CONSOLE_ESCAPE_COLOR_MAGENTA "\x1b[35m" -#define CONSOLE_ESCAPE_COLOR_CYAN "\x1b[36m" -#define CONSOLE_ESCAPE_COLOR_WHITE "\x1b[37m" -#define CONSOLE_ESCAPE_COLOR_RESET "\x1b[0m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_BLACK "\x1b[40m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_RED "\x1b[41m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_GREEN "\x1b[42m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_YELLOW "\x1b[43m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_BLUE "\x1b[44m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_MAGENTA "\x1b[45m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_CYAN "\x1b[46m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_WHITE "\x1b[47m" -#else -#define CONSOLE_ESCAPE_COLOR_BLACK -#define CONSOLE_ESCAPE_COLOR_RED -#define CONSOLE_ESCAPE_COLOR_GREEN -#define CONSOLE_ESCAPE_COLOR_YELLOW -#define CONSOLE_ESCAPE_COLOR_BLUE -#define CONSOLE_ESCAPE_COLOR_MAGENTA -#define CONSOLE_ESCAPE_COLOR_CYAN -#define CONSOLE_ESCAPE_COLOR_WHITE -#define CONSOLE_ESCAPE_COLOR_RESET -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_BLACK -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_RED -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_GREEN -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_YELLOW -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_BLUE -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_MAGENTA -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_CYAN -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_WHITE -#endif - -const char *level_names[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; - -#if LOG_USE_COLOR == 1 -static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"}; -#else -static const char *level_colors[] = {"", "", "", "", "", ""}; -#endif - -#include -#include - -namespace -{ - const char *critStr = "CRIT"; - const char *irqStr = "IRQ"; -} // namespace - -struct Logger -{ - Logger(logger_level level = LOGTRACE) : level{level} - { - - lock = xSemaphoreCreateMutex(); - - assert(lock != NULL); - - /* Acquire lock */ - if (xSemaphoreTake(lock, 100) != pdPASS) { - return; - } - - level = level; - - /* Release lock */ - xSemaphoreGive(lock); - } - - bool logLock() - { - // if called from the ISR use DI/EI. In all other cases use semaphore. - if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) { - bt = cpp_freertos::CriticalSection::EnterFromISR(); - } - else if (xSemaphoreTake(lock, 100) != pdPASS) { - return false; - } - return true; - } - - void logUnlock() - { - // if called from the ISR use DI/EI. In all other cases use semaphore. - if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) { - cpp_freertos::CriticalSection::ExitFromISR(bt); - } - else { - xSemaphoreGive(lock); - } - } - - std::map filtered = { - // {"ServiceDB", logger_level::LOGFATAL}, - {"ApplicationManager", logger_level::LOGINFO}, - {"TS0710Worker", logger_level::LOGINFO}, - {"ServiceCellular", logger_level::LOGINFO}, - {"ServiceAntenna", logger_level::LOGINFO}, - {"ServiceFota", logger_level::LOGINFO}, - {"ServiceEink", logger_level::LOGINFO}, - {"ServiceDB", logger_level::LOGINFO}, - // make sure that we got defined map entries for at least crit and irq - // make sure that we got defined map entries for at least crit and irq - {critStr, logger_level::LOGTRACE}, - {irqStr, logger_level::LOGTRACE}}; - - /// Filter out not interesting logs via thread Name - /// its' using fact that: - /// - TRACE is level 0, for unedfined lookups it will be alvways trace - /// - it will be one time init for apps which doesn't tell what level they should have - /// - for others it will be o1 lookup so it's fine - logger_level filterThreadName(const std::string &name) - { - return filtered[name]; - } - - xSemaphoreHandle lock; - logger_level level; - BaseType_t bt; -}; - -static Logger logger; -static char loggerBuffer[LOGGER_BUFFER_SIZE] = {0}; - -static inline size_t loggerBufferSizeLeft(char *ptr) -{ - assert(&loggerBuffer[LOGGER_BUFFER_SIZE] - ptr > 0); - return &loggerBuffer[LOGGER_BUFFER_SIZE] - ptr; -} - -void log_Printf(const char *fmt, ...) -{ - if (!logger.logLock()) { - return; - } - - char *ptr = loggerBuffer; - va_list args; - - va_start(args, fmt); - ptr += vsnprintf(ptr, loggerBufferSizeLeft(ptr), fmt, args); - va_end(args); - - log_WriteToDevice((uint8_t *)loggerBuffer, ptr - loggerBuffer); - - logger.logUnlock(); -} - -/// get string description: -/// - in critical seciton - return CRIT -/// - in interrupt return - IRQ -/// - else return thread name -static inline const char *getTaskDesc() -{ - return xTaskGetCurrentTaskHandle() == NULL - ? critStr - : xPortIsInsideInterrupt() ? irqStr : pcTaskGetName(xTaskGetCurrentTaskHandle()); -} - -static void _log_Log( - logger_level level, const char *file, int line, const char *function, const char *fmt, va_list args) -{ - if (!logger.logLock()) { - return; - } - - char *ptr = loggerBuffer; - - // filter out not interesing logs - if (logger.filterThreadName(getTaskDesc()) >= level) { - logger.logUnlock(); - return; - } - - ptr += snprintf( - ptr, loggerBufferSizeLeft(ptr), "%lu ms ", cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks())); - -#if LOG_USE_COLOR == 1 - - ptr += snprintf(ptr, - loggerBufferSizeLeft(ptr), - "%s%-5s " CONSOLE_ESCAPE_COLOR_MAGENTA "[%-10s] \x1b[90m%s:%d:" CONSOLE_ESCAPE_COLOR_RESET, - level_colors[level], - level_names[level], - getTaskDesc(), - file, - line); -#else - ptr += snprintf(ptr, - loggerBufferSizeLeft(ptr), - "%-5s [%s] %s:%s:%d: ", - level_names[level], - getTaskDesc(), - file, - function, - line); -#endif - ptr += vsnprintf(ptr, loggerBufferSizeLeft(ptr), fmt, args); - ptr += snprintf(ptr, loggerBufferSizeLeft(ptr), "\n"); - - log_WriteToDevice((uint8_t *)loggerBuffer, ptr - loggerBuffer); - - /* Release lock */ - logger.logUnlock(); -} - -void log_Log(logger_level level, const char *file, int line, const char *function, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - _log_Log(level, file, line, function, fmt, args); - va_end(args); -} - -/** - * Update log level - * @param level [in] - new log level - */ -void log_SetLevel(logger_level level) -{ - logger.level = level; -} - -extern "C" -{ - - void bt_log_custom(const char *file, int line, const char *foo, const char *fmt, ...) - { - va_list args; - va_start(args, fmt); - _log_Log(LOGTRACE, file, line, foo, fmt, args); - va_end(args); - } - - int printf(__const char *__restrict __format, ...) - { - /* Acquire lock */ - if (!logger.logLock()) { - return -1; - } - - char *ptr = loggerBuffer; - va_list args; - - va_start(args, __format); - ptr += vsnprintf(ptr, loggerBufferSizeLeft(ptr), __format, args); - va_end(args); - - unsigned int numBytes = ptr - loggerBuffer; - SEGGER_RTT_Write(0, (uint8_t *)loggerBuffer, numBytes); - - /* Release lock */ - logger.logUnlock(); - - return numBytes; - } - - int vprintf(const char *__restrict __format, va_list __arg) - { - /* Acquire lock */ - if (!logger.logLock()) { - return -1; - } - char *ptr = loggerBuffer; - ptr += vsnprintf(ptr, loggerBufferSizeLeft(ptr), __format, __arg); - - unsigned int numBytes = ptr - loggerBuffer; - SEGGER_RTT_Write(0, (uint8_t *)loggerBuffer, numBytes); - - /* Release lock */ - logger.logUnlock(); - - return numBytes; - } - - int log_assert(__const char *__restrict __format, ...) - { - /* Acquire lock */ - if (!logger.logLock()) { - return -1; - } - - char *ptr = loggerBuffer; - ptr += snprintf( - ptr, loggerBufferSizeLeft(ptr), "%lu ms ", cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks())); - logger_level level = LOGFATAL; - ptr += snprintf(ptr, - loggerBufferSizeLeft(ptr), - "%s%-5s " CONSOLE_ESCAPE_COLOR_MAGENTA "[%-10s] \x1b[31mASSERTION " CONSOLE_ESCAPE_COLOR_RESET, - level_colors[level], - level_names[level], - getTaskDesc()); - - va_list args; - va_start(args, __format); - ptr += vsnprintf(ptr, loggerBufferSizeLeft(ptr), __format, args); - va_end(args); - - unsigned int numBytes = ptr - loggerBuffer; - - log_WriteToDevice((uint8_t *)loggerBuffer, ptr - loggerBuffer); - - /* Release lock */ - logger.logUnlock(); - - return numBytes; - } - - void __assert_func(const char *file, int line, const char *func, const char *failedexpr) - { - log_assert("\"%s\" failed: file \"%s\", line %d%s%s\n", - failedexpr, - file, - line, - func ? ", function: " : "", - func ? func : ""); - - abort(); - /* NOTREACHED */ - } -}; diff --git a/module-utils/board/cross/log_rt1051.cpp b/module-utils/board/cross/log_rt1051.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3f00ffa733e812c9598332d159ab0b704631ca0 --- /dev/null +++ b/module-utils/board/cross/log_rt1051.cpp @@ -0,0 +1,120 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include +#include +#include +#include +#include "log/log.hpp" +#include "log/Logger.hpp" +#include "segger/rtt/SEGGER_RTT.h" +#include + +/// get string description: +/// - in critical seciton - return CRIT +/// - in interrupt return - IRQ +/// - else return thread name +static inline const char *getTaskDesc() +{ + return xTaskGetCurrentTaskHandle() == nullptr + ? Log::Logger::CRIT_STR + : xPortIsInsideInterrupt() ? Log::Logger::IRQ_STR : pcTaskGetName(xTaskGetCurrentTaskHandle()); +} + +namespace Log +{ + void Logger::addLogHeader(logger_level level, const char *file, int line, const char *function) + { + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], + loggerBufferSizeLeft(), + "%lu ms ", + cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks())); + + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], + loggerBufferSizeLeft(), + "%-5s [%s] %s:%s:%d: ", + level_names[level], + getTaskDesc(), + file, + function, + line); + } + + bool Logger::filterLogs(logger_level level) + { + return GetLogLevel(getTaskDesc()) < level; + } + + void Logger::logToDevice(const char *fmt, va_list args) + { + loggerBufferCurrentPos = 0; + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], + loggerBufferSizeLeft(), + "%lu ms ", + cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks())); + + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], + loggerBufferSizeLeft(), + "%-5s [%-10s] \x1b[31mASSERTION ", + level_names[LOGFATAL], + getTaskDesc()); + + loggerBufferCurrentPos += vsnprintf(&loggerBuffer[loggerBufferCurrentPos], loggerBufferSizeLeft(), fmt, args); + logToDevice(Device::DEFAULT, loggerBuffer, loggerBufferCurrentPos); + } + + void Logger::logToDevice(Device device, std::string_view log, size_t length) + { + switch (device) { + case Device::DEFAULT: + log_WriteToDevice(reinterpret_cast(log.data()), length); + break; + case Device::SEGGER_RTT: + SEGGER_RTT_Write(0, reinterpret_cast(log.data()), length); + break; + default: + break; + } + } +} // namespace Log + +using Log::Logger; + +extern "C" +{ + int printf(__const char *__restrict __format, ...) + { + va_list args; + va_start(args, __format); + const auto result = Logger::get().log(Log::Device::SEGGER_RTT, __format, args); + va_end(args); + return result; + } + + int vprintf(const char *__restrict __format, va_list __arg) + { + return Logger::get().log(Log::Device::SEGGER_RTT, __format, __arg); + } + + int log_assert(__const char *__restrict __format, ...) + { + va_list args; + va_start(args, __format); + const auto result = Logger::get().logAssert(__format, args); + va_end(args); + return result; + } + + void __assert_func(const char *file, int line, const char *func, const char *failedexpr) + { + log_assert("\"%s\" failed: file \"%s\", line %d%s%s\n", + failedexpr, + file, + line, + func ? ", function: " : "", + func ? func : ""); + + abort(); + /* NOTREACHED */ + } +}; diff --git a/module-utils/board/linux/log.cpp b/module-utils/board/linux/log.cpp deleted file mode 100644 index da9e99eaab65230308f2e8c5617301a916b32ff3..0000000000000000000000000000000000000000 --- a/module-utils/board/linux/log.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include "../../log/log.hpp" -#include -#include -#include -#include -#include -#include - -#define LOGGER_BUFFER_SIZE 4096 - -#define CONSOLE_ESCAPE_COLOR_BLACK "\x1b[30m" -#define CONSOLE_ESCAPE_COLOR_RED "\x1b[31m" -#define CONSOLE_ESCAPE_COLOR_GREEN "\x1b[32m" -#define CONSOLE_ESCAPE_COLOR_YELLOW "\x1b[33m" -#define CONSOLE_ESCAPE_COLOR_BLUE "\x1b[34m" -#define CONSOLE_ESCAPE_COLOR_MAGENTA "\x1b[35m" -#define CONSOLE_ESCAPE_COLOR_CYAN "\x1b[36m" -#define CONSOLE_ESCAPE_COLOR_WHITE "\x1b[37m" -#define CONSOLE_ESCAPE_COLOR_RESET "\x1b[0m" - -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_BLACK "\x1b[40m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_RED "\x1b[41m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_GREEN "\x1b[42m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_YELLOW "\x1b[43m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_BLUE "\x1b[44m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_MAGENTA "\x1b[45m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_CYAN "\x1b[46m" -#define CONSOLE_ESCAPE_COLOR_BACKGROUND_WHITE "\x1b[47m" - -const char *level_names[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; - -#if LOG_USE_COLOR == 1 -static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"}; -#endif - -struct Logger -{ - Logger(logger_level level = LOGTRACE) : level{level} - {} - - std::mutex lock; - logger_level level; -}; - -static Logger logger; -static char loggerBuffer[LOGGER_BUFFER_SIZE] = {0}; - -void dumpToFile(std::string_view log, size_t length) -{ - static std::fstream logFile(logFileName, std::fstream::out); - logFile.write(log.data(), length); - logFile.flush(); -} - -void log_Printf(const char *fmt, ...) -{ - /* Acquire lock */ - std::lock_guard guard(logger.lock); - char *ptr = loggerBuffer; - ptr[0] = 0; - va_list args; - - va_start(args, fmt); - ptr += vsnprintf(ptr, LOGGER_BUFFER_SIZE - 1, fmt, args); - va_end(args); - - std::cout << loggerBuffer; - dumpToFile(loggerBuffer, ptr - loggerBuffer); -} - -static void _log_Log( - logger_level level, const char *file, int line, const char *function, const char *fmt, va_list args) -{ - if (level < logger.level) { - return; - } - - std::lock_guard guard(logger.lock); - - char *ptr = loggerBuffer; - - ptr += snprintf(ptr, - &loggerBuffer[LOGGER_BUFFER_SIZE] - ptr, - "%d ms ", - cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks())); - -#if LOG_USE_COLOR == 1 - ptr += snprintf(ptr, - &loggerBuffer[LOGGER_BUFFER_SIZE] - ptr, - "%s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", - level_colors[level], - level_names[level], - file, - line); -#else - ptr += snprintf( - ptr, &loggerBuffer[LOGGER_BUFFER_SIZE] - ptr, "%-5s %s:%s:%d: ", level_names[level], file, function, line); -#endif - ptr += vsnprintf(ptr, &loggerBuffer[LOGGER_BUFFER_SIZE] - ptr, fmt, args); - ptr += snprintf(ptr, &loggerBuffer[LOGGER_BUFFER_SIZE] - ptr, "\n"); - - std::cout << loggerBuffer; - dumpToFile(loggerBuffer, ptr - loggerBuffer); -} - -__attribute__((weak)) void log_Log( - logger_level level, const char *file, int line, const char *function, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - _log_Log(level, file, line, function, fmt, args); - va_end(args); -} - -/** - * Update log level - * @param level [in] - new log level - */ -void log_SetLevel(logger_level level) -{ - logger.level = level; -} - -extern "C" -{ - - void bt_log_custom(const char *file, int line, const char *foo, const char *fmt, ...) - { - va_list args; - va_start(args, fmt); - _log_Log(LOGTRACE, file, line, foo, fmt, args); - va_end(args); - } -}; diff --git a/module-utils/board/linux/log_linux.cpp b/module-utils/board/linux/log_linux.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1dc3bc56a6119ff04faf88abe0080521aec887c --- /dev/null +++ b/module-utils/board/linux/log_linux.cpp @@ -0,0 +1,55 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "log/log.hpp" +#include "log/Logger.hpp" +#include +#include +#include + +#if LOG_USE_COLOR == 1 +static const char *level_colors[] = {"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"}; +#endif + +namespace Log +{ + void Logger::addLogHeader(logger_level level, const char *file, int line, const char *function) + { + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], + LOGGER_BUFFER_SIZE - loggerBufferCurrentPos, + "%d ms ", + cpp_freertos::Ticks::TicksToMs(cpp_freertos::Ticks::GetTicks())); +#if LOG_USE_COLOR == 1 + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], + LOGGER_BUFFER_SIZE - loggerBufferCurrentPos, + "%s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", + level_colors[level], + level_names[level], + file, + line); +#else + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], + LOGGER_BUFFER_SIZE - loggerBufferCurrentPos, + "%-5s %s:%s:%d: ", + level_names[level], + file, + function, + line); +#endif + } + + bool Logger::filterLogs(logger_level _level) + { + return _level >= level; + } + + void Logger::logToDevice(const char *, va_list) + { + assert(false && "Not implemented"); + } + + void Logger::logToDevice(Device, std::string_view log, size_t) + { + std::cout << log; + } +} // namespace Log diff --git a/module-utils/log/Logger.cpp b/module-utils/log/Logger.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e20d32ac4b30224fb94978a7d0c8bfa22e9db0c --- /dev/null +++ b/module-utils/log/Logger.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "critical.hpp" +#include +#include +#include "Logger.hpp" +#include "macros.h" + +namespace Log +{ + std::map Logger::filtered = {{"ApplicationManager", logger_level::LOGINFO}, + {"TS0710Worker", logger_level::LOGINFO}, + {"ServiceCellular", logger_level::LOGINFO}, + {"ServiceAntenna", logger_level::LOGINFO}, + {"ServiceFota", logger_level::LOGINFO}, + {"ServiceEink", logger_level::LOGINFO}, + {"ServiceDB", logger_level::LOGINFO}, + {CRIT_STR, logger_level::LOGTRACE}, + {IRQ_STR, logger_level::LOGTRACE}}; + const char *Logger::level_names[] = {"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"}; + + auto Logger::GetLogLevel(const std::string &name) -> logger_level + { + return filtered[name]; + } + + bool Logger::lock() + { + if (isIRQ()) { + bt = cpp_freertos::CriticalSection::EnterFromISR(); + } + else { + return mutex.Lock(); + } + return true; + } + + auto Logger::log(Device device, const char *fmt, va_list args) -> int + { + if (!lock()) { + return -1; + } + auto _ = gsl::finally([this] { unlock(); }); + + loggerBufferCurrentPos = 0; + loggerBufferCurrentPos += vsnprintf(&loggerBuffer[loggerBufferCurrentPos], loggerBufferSizeLeft(), fmt, args); + logToDevice(device, loggerBuffer, loggerBufferCurrentPos); + + return loggerBufferCurrentPos; + } + + void Logger::log( + logger_level level, const char *file, int line, const char *function, const char *fmt, va_list args) + { + if (!filterLogs(level)) { + return; + } + + if (!lock()) { + return; + } + auto _ = gsl::finally([this] { unlock(); }); + + loggerBufferCurrentPos = 0; + addLogHeader(level, file, line, function); + + loggerBufferCurrentPos += vsnprintf(&loggerBuffer[loggerBufferCurrentPos], loggerBufferSizeLeft(), fmt, args); + loggerBufferCurrentPos += snprintf(&loggerBuffer[loggerBufferCurrentPos], loggerBufferSizeLeft(), "\n"); + + logToDevice(Device::DEFAULT, loggerBuffer, loggerBufferCurrentPos); + } + + auto Logger::logAssert(const char *fmt, va_list args) -> int + { + if (!lock()) { + return -1; + } + auto _ = gsl::finally([this] { unlock(); }); + + logToDevice(fmt, args); + + return loggerBufferCurrentPos; + } + + void Logger::unlock() + { + if (isIRQ()) { + cpp_freertos::CriticalSection::ExitFromISR(bt); + } + else { + mutex.Unlock(); + } + } +}; // namespace Log diff --git a/module-utils/log/Logger.hpp b/module-utils/log/Logger.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5b2306431e462af2d7c8b7aaaa308f400d17badd --- /dev/null +++ b/module-utils/log/Logger.hpp @@ -0,0 +1,69 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include +#include "log.hpp" +#include +#include + +namespace Log +{ + enum class Device + { + DEFAULT, + SEGGER_RTT + }; + + class Logger + { + public: + [[nodiscard]] static Logger &get() + { + static Logger logger; + return logger; + } + auto log(Device device, const char *fmt, va_list args) -> int; + void log(logger_level level, const char *file, int line, const char *function, const char *fmt, va_list args); + auto logAssert(const char *fmt, va_list args) -> int; + + static constexpr auto CRIT_STR = "CRIT"; + static constexpr auto IRQ_STR = "IRQ"; + + private: + Logger() = default; + + void addLogHeader(logger_level level, + const char *file = nullptr, + int line = -1, + const char *function = nullptr); + [[nodiscard]] bool filterLogs(logger_level level); + /// Filter out not interesting logs via thread Name + /// its' using fact that: + /// - TRACE is level 0, for unedfined lookups it will be alvways trace + /// - it will be one time init for apps which doesn't tell what level they should have + /// - for others it will be o1 lookup so it's fine + [[nodiscard]] auto GetLogLevel(const std::string &name) -> logger_level; + bool lock(); + void logToDevice(const char *fmt, va_list args); + void logToDevice(Device device, std::string_view log, size_t length); + [[nodiscard]] size_t loggerBufferSizeLeft() const noexcept + { + const auto sizeLeft = LOGGER_BUFFER_SIZE - loggerBufferCurrentPos; + assert(sizeLeft > 0); + return sizeLeft; + } + void unlock(); + + BaseType_t bt; + cpp_freertos::MutexStandard mutex; + logger_level level{LOGTRACE}; + char loggerBuffer[LOGGER_BUFFER_SIZE] = {0}; + size_t loggerBufferCurrentPos = 0; + + static const char *level_names[]; + static std::map filtered; + }; +} // namespace Log diff --git a/module-utils/log/log.cpp b/module-utils/log/log.cpp new file mode 100644 index 0000000000000000000000000000000000000000..96f7aff34a9613d565ffddafdb4841d2b656c816 --- /dev/null +++ b/module-utils/log/log.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "log.hpp" +#include "Logger.hpp" +#include + +using Log::Logger; + +void log_Printf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Logger::get().log(Log::Device::DEFAULT, fmt, args); + va_end(args); +} + +void log_Log(logger_level level, const char *file, int line, const char *function, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Logger::get().log(level, file, line, function, fmt, args); + va_end(args); +} + +extern "C" +{ + void bt_log_custom(const char *file, int line, const char *foo, const char *fmt, ...) + { + va_list args; + va_start(args, fmt); + Logger::get().log(LOGTRACE, file, line, foo, fmt, args); + va_end(args); + } +} diff --git a/module-utils/log/log.hpp b/module-utils/log/log.hpp index 2551d5459314fda3a97059825ff841288dd1867f..1640088312670b523584898437cdd7a2b97a9330 100644 --- a/module-utils/log/log.hpp +++ b/module-utils/log/log.hpp @@ -62,7 +62,6 @@ extern "C" */ void log_Log(logger_level level, const char *file, int line, const char *function, const char *fmt, ...) __attribute__((format(printf, 5, 6))); - void log_SetLevel(logger_level level); void log_Printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void log_WriteToDevice(const uint8_t *pBuffer, unsigned NumBytes); @@ -84,7 +83,8 @@ extern "C" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" -static const char *logFileName = "MuditaOS.log"; +static const size_t LOGGER_BUFFER_SIZE = 8192; +static const double MAX_BUFFER_UTIL_MEM = 0.8 * LOGGER_BUFFER_SIZE; #pragma GCC diagnostic pop #endif /* LOG_LOG_H_ */ diff --git a/module-utils/targets/Target_Cross.cmake b/module-utils/targets/Target_Cross.cmake index 9e324ea696804beef54a7f29674eb5b62cbc5cef..e0f38e494fb868c5707376b324d18916e38ea831 100644 --- a/module-utils/targets/Target_Cross.cmake +++ b/module-utils/targets/Target_Cross.cmake @@ -1,6 +1,6 @@ set(BOARD_SOURCES ${BOARD_SOURCES} - ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/log.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/log_rt1051.cpp CACHE INTERNAL "" ) diff --git a/module-utils/targets/Target_Linux.cmake b/module-utils/targets/Target_Linux.cmake index a241fdef46753da78db7df535170436670d45a50..dcd9c4b770cde5b5895ae8a3d77aa9bfc561a304 100644 --- a/module-utils/targets/Target_Linux.cmake +++ b/module-utils/targets/Target_Linux.cmake @@ -1,6 +1,6 @@ set(BOARD_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/log.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/log_linux.cpp CACHE INTERNAL "")