Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 69 additions & 10 deletions lib/furi/core/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,33 @@
#include "mutex.h"
#include <furi_hal.h>
#include <m-list.h>

LIST_DEF(FuriLogHandlersList, FuriLogHandler, M_POD_OPLIST)
#include <m-dict.h>

LIST_DEF(FuriLogHandlersList, FuriLogHandler, M_POD_OPLIST);

#define CSTR_ALLOC_INIT_SET(a, b) ((a) = strdup(b))
#define CSTR_ALLOC_CLEAR(a) (free((void*)(a)))
#define CSTR_ALLOC_OPLIST \
(INIT(M_INIT_DEFAULT), \
INIT_SET(CSTR_ALLOC_INIT_SET), \
CLEAR(CSTR_ALLOC_CLEAR), \
HASH(m_core_cstr_hash), \
EQUAL(M_CSTR_EQUAL), \
CMP(strcmp), \
TYPE(const char*), \
OUT_STR(M_CSTR_OUT_STR))
DICT_SET_DEF(FuriLogExceptions, const char*, CSTR_ALLOC_OPLIST);

#define FURI_LOG_LEVEL_DEFAULT FuriLogLevelInfo

typedef struct {
FuriLogLevel log_level;
FuriLogLevel default_level;
FuriMutex* mutex;
FuriLogHandlersList_t tx_handlers;

FuriLogLevel exception_level;
FuriLogExceptionMode exception_mode;
FuriLogExceptions_t exception_list;
} FuriLogParams;

static FuriLogParams furi_log = {0};
Expand All @@ -33,9 +51,10 @@ static const FuriLogLevelDescription FURI_LOG_LEVEL_DESCRIPTIONS[] = {

void furi_log_init(void) {
// Set default logging parameters
furi_log.log_level = FURI_LOG_LEVEL_DEFAULT;
furi_log.default_level = FURI_LOG_LEVEL_DEFAULT;
furi_log.mutex = furi_mutex_alloc(FuriMutexTypeRecursive);
FuriLogHandlersList_init(furi_log.tx_handlers);
FuriLogExceptions_init(furi_log.exception_list);
}

bool furi_log_add_handler(FuriLogHandler handler) {
Expand Down Expand Up @@ -119,11 +138,37 @@ void furi_log_puthex32(uint32_t data) {
furi_log_puts(tmp_str);
}

static bool furi_log_is_enabled(FuriLogLevel level, const char* tag) {
bool in_exception_list = !!FuriLogExceptions_get(furi_log.exception_list, tag);
bool include_mode = furi_log.exception_mode == FuriLogExceptionModeInclude;

/* default = [I]nfo
* exception = [D]ebug
* tags = A, B, C, D, E
* exceptions = C, E
*
* tag | A | B | C | D | E |
* ----------------------+---+---+---+---+---+
* level in include mode | I | I | D | I | D |
* level in exclude mode | D | D | I | D | I |
*
* use exception level:
* include | V | X |
* --------+---+---+
* in list | | |
* V | V | X |
* X | X | V |
*/
bool use_exception_level = in_exception_list ^ !include_mode;
FuriLogLevel effective_level = use_exception_level ? furi_log.exception_level :
furi_log.default_level;

return effective_level >= level;
}

void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) {
do {
if(level > furi_log.log_level) {
break;
}
if(!furi_log_is_enabled(level, tag)) return;

if(furi_mutex_acquire(furi_log.mutex, furi_kernel_is_running() ? FuriWaitForever : 0) !=
FuriStatusOk) {
Expand Down Expand Up @@ -179,7 +224,7 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form
}

void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) {
if(level <= furi_log.log_level &&
if(level <= furi_log.default_level &&
furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk) {
FuriString* string;
string = furi_string_alloc();
Expand All @@ -201,11 +246,25 @@ void furi_log_set_level(FuriLogLevel level) {
if(level == FuriLogLevelDefault) {
level = FURI_LOG_LEVEL_DEFAULT;
}
furi_log.log_level = level;
furi_log.default_level = level;
}

FuriLogLevel furi_log_get_level(void) {
return furi_log.log_level;
return furi_log.default_level;
}

void furi_log_begin_level_exceptions(FuriLogLevel level, FuriLogExceptionMode mode) {
furi_check(level < FuriLogLevelMAX);
furi_check(mode < FuriLogExceptionModeMAX);

furi_log.exception_level = level;
furi_log.exception_mode = mode;
FuriLogExceptions_reset(furi_log.exception_list);
}

void furi_log_add_level_exception(const char* tag) {
furi_check(tag);
FuriLogExceptions_push(furi_log.exception_list, tag);
}

bool furi_log_level_to_string(FuriLogLevel level, const char** str) {
Expand Down
29 changes: 29 additions & 0 deletions lib/furi/core/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,15 @@ typedef enum {
FuriLogLevelInfo = 4,
FuriLogLevelDebug = 5,
FuriLogLevelTrace = 6,
FuriLogLevelMAX,
} FuriLogLevel;

typedef enum {
FuriLogExceptionModeInclude,
FuriLogExceptionModeExclude,
FuriLogExceptionModeMAX,
} FuriLogExceptionMode;

#define _FURI_LOG_CLR(clr) "\033[0;" clr "m"
#define _FURI_LOG_CLR_RESET "\033[0m"

Expand Down Expand Up @@ -121,6 +128,28 @@ void furi_log_set_level(FuriLogLevel level);
*/
FuriLogLevel furi_log_get_level(void);

/** Begin recording the list of log level exceptions.
*
* This function clears the list. Subsequent calls to
* `furi_log_add_level_exception` will add items to the list.
*
* @param[in] level Log level to apply as an exception
* @param[in] mode `Include` means that the specified log level will be applied
* to tags in the list. `Exclude` means that the specified log
* level will be applied to all tags _except_ ones specified in
* the list.
*
*/
void furi_log_begin_level_exceptions(FuriLogLevel level, FuriLogExceptionMode mode);

/** Add an item to the list of log level exceptions.
*
* For more information, read documentation for `furi_log_begin_level_exceptions`.
*
* @param[in] tag Tag string to add to the list
*/
void furi_log_add_level_exception(const char* tag);

/** Log level to string
*
* @param[in] level The level
Expand Down
6 changes: 6 additions & 0 deletions lib/furi/core/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ void furi_string_right(FuriString* v, size_t index) {
string_right(v->string, index);
}

bool furi_string_consume_left(FuriString* string, const char* expected) {
if(!furi_string_start_with_str(string, expected)) return false;
furi_string_right(string, strlen(expected));
return true;
}

void furi_string_mid(FuriString* v, size_t index, size_t size) {
string_mid(v->string, index, size);
}
Expand Down
7 changes: 7 additions & 0 deletions lib/furi/core/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,13 @@ void furi_string_left(FuriString* string, size_t index);
*/
void furi_string_right(FuriString* string, size_t index);

/** If `string` starts with `expected`, trim off `expected` and return `true`.
*
* @param string The FuriString instance
* @param expected The expected beginning of the string
*/
bool furi_string_consume_left(FuriString* string, const char* expected);

/** Trim the string from position index to size bytes.
*
* See also furi_string_set_n.
Expand Down