/** * @file log.h * @brief Logger header * @author Lorenz C. * * This logging library provides a simple logging interface with different verbosity levels. * Each tag can have its own log level. * Only messages with a log level greater or equal to the log level of the tag and the global log level will be printed. */ #ifndef LOG_H #define LOG_H #include /** * @brief Log levels */ typedef enum { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARN, LOG_LEVEL_ERROR, } log_level_t; /* For internal use only. * Use the LOG_* macros instead e.g., LOG_DEBUG(TAG, "Debug message"); */ uint32_t logger_get_timestamp(void); void logger_write(const char* format, ...); /** * @brief Set the log level for a tag * If the tag is not already in the list, it will be added. * * @param[in] tag The tag to set the log level for * @param[in] level The log level to set (member of @ref log_level_t) */ void logger_set_log_level(const char* tag, log_level_t level); /** * @brief Get the log level for a tag * * @param[in] tag The tag to get the log level for * @return The log level for the tag (member of @ref log_level_t) */ log_level_t logger_get_log_level(const char* tag); /** * @brief The global minimum log level. * Messages with a log level lower than this will not be logged. * And log statements with a log level lower than this will optimized away by the compiler. */ #define LOGGER_MIN_LOG_LEVEL LOG_LEVEL_DEBUG /** * @brief The maximum number of tags that can be used. */ #define LOGGER_MAX_TAG_ENTRIES 20 /** * @brief Whether to use color in the log output. * This is only supported in terminals that support ANSI escape codes. */ #define LOGGER_USE_COLOR 0 #if LOGGER_USE_COLOR #define LOG_RESET_COLOR "\033[0m" #define LOG_COLOR_E "\033[0;31m" // Red #define LOG_COLOR_W "\033[0;33m" // Brown #define LOG_COLOR_I "\033[0;32m" // Green #define LOG_COLOR_D #else #define LOG_RESET_COLOR #define LOG_COLOR_E #define LOG_COLOR_W #define LOG_COLOR_I #define LOG_COLOR_D #endif #define LOG_FORMAT(letter, format) LOG_COLOR_##letter #letter " (%lu) %s: " format LOG_RESET_COLOR "\r\n" #define LOGGER_LOG(level, tag, format, ...) \ do { \ if (level >= LOGGER_MIN_LOG_LEVEL && level >= logger_get_log_level(tag)) { \ if (level == LOG_LEVEL_DEBUG) { \ logger_write(LOG_FORMAT(D, format), logger_get_timestamp(), tag, ##__VA_ARGS__); \ } else if (level == LOG_LEVEL_INFO) { \ logger_write(LOG_FORMAT(I, format), logger_get_timestamp(), tag, ##__VA_ARGS__); \ } else if (level == LOG_LEVEL_WARN) { \ logger_write(LOG_FORMAT(W, format), logger_get_timestamp(), tag, ##__VA_ARGS__); \ } else if (level == LOG_LEVEL_ERROR) { \ logger_write(LOG_FORMAT(E, format), logger_get_timestamp(), tag, ##__VA_ARGS__); \ } \ } \ } while (0) /** * @brief Macro to log a debug message (LOG_LEVEL_DEBUG) */ #define LOG_DEBUG(tag, format, ...) LOGGER_LOG(LOG_LEVEL_DEBUG, tag, format, ##__VA_ARGS__) /** * @brief Macro to log an info message (LOG_LEVEL_INFO) */ #define LOG_INFO(tag, format, ...) LOGGER_LOG(LOG_LEVEL_INFO, tag, format, ##__VA_ARGS__) /** * @brief Macro to log a warning message (LOG_LEVEL_WARN) */ #define LOG_WARN(tag, format, ...) LOGGER_LOG(LOG_LEVEL_WARN, tag, format, ##__VA_ARGS__) /** * @brief Macro to log an error message (LOG_LEVEL_ERROR) */ #define LOG_ERROR(tag, format, ...) LOGGER_LOG(LOG_LEVEL_ERROR, tag, format, ##__VA_ARGS__) #endif // LOG_H