Skip to content

Commit 7c8e414

Browse files
committed
feat(log): Add tag level set and check
1 parent c496879 commit 7c8e414

File tree

3 files changed

+161
-6
lines changed

3 files changed

+161
-6
lines changed

components/log/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,10 @@ config LOG_COLORS
4444

4545
In order to view these, your terminal program must support ANSI color codes.
4646

47+
config LOG_SET_LEVEL
48+
bool "Enable log set level"
49+
default n
50+
help
51+
Enable this option, user can set tag level.
4752

4853
endmenu

components/log/include/esp_log.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,30 @@ typedef enum {
4141

4242
typedef int (*putchar_like_t)(int ch);
4343

44+
#ifdef CONFIG_LOG_SET_LEVEL
45+
/**
46+
* @brief Set log level for given tag
47+
*
48+
* If logging for given component has already been enabled, changes previous setting.
49+
*
50+
* Note that this function can not raise log level above the level set using
51+
* CONFIG_LOG_DEFAULT_LEVEL setting in menuconfig.
52+
*
53+
* To raise log level above the default one for a given file, define
54+
* LOG_LOCAL_LEVEL to one of the ESP_LOG_* values, before including
55+
* esp_log.h in this file.
56+
*
57+
* @param tag Tag of the log entries to enable. Must be a non-NULL zero terminated string.
58+
* Value "*" resets log level for all tags to the given value.
59+
*
60+
* @param level Selects log level to enable. Only logs at this and lower verbosity
61+
* levels will be shown.
62+
*/
63+
void esp_log_level_set(const char* tag, esp_log_level_t level);
64+
#else
65+
#define esp_log_level_set(tag, level)
66+
#endif /* CONFIG_LOG_SET_LEVEL */
67+
4468
/**
4569
* @brief Set function used to output log entries
4670
*

components/log/log.c

Lines changed: 132 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
#include <stdlib.h>
1717
#include <stdio.h>
1818
#include <time.h>
19+
#include <stdbool.h>
20+
#include <string.h>
21+
#include <sys/queue.h>
1922
#include <sys/lock.h>
2023

2124
#include "esp_libc.h"
@@ -55,9 +58,126 @@ static uint32_t IRAM_ATTR esp_log_early_timestamp()
5558
}
5659

5760
#ifndef BOOTLOADER_BUILD
61+
62+
#ifdef CONFIG_LOG_SET_LEVEL
63+
#define GLOBAL_TAG "*"
64+
65+
typedef struct uncached_tag_entry_{
66+
SLIST_ENTRY(uncached_tag_entry_) entries;
67+
uint8_t level; // esp_log_level_t as uint8_t
68+
char tag[0]; // beginning of a zero-terminated string
69+
} uncached_tag_entry_t;
70+
71+
static esp_log_level_t s_global_tag_level = ESP_LOG_VERBOSE;
72+
static SLIST_HEAD(log_tags_head , uncached_tag_entry_) s_log_uncached_tags = SLIST_HEAD_INITIALIZER(s_log_uncached_tags);
73+
static uncached_tag_entry_t *s_uncached_tag_entry_prev;
74+
#endif /* CONFIG_LOG_SET_LEVEL */
75+
5876
static _lock_t s_lock;
5977
static putchar_like_t s_putchar_func = &putchar;
6078

79+
#ifdef CONFIG_LOG_SET_LEVEL
80+
/**
81+
* @brief get entry by inputting tag
82+
*/
83+
static bool esp_log_get_tag_entry(const char *tag, uncached_tag_entry_t **entry)
84+
{
85+
uncached_tag_entry_t *it = NULL;
86+
87+
SLIST_FOREACH(it, &s_log_uncached_tags, entries) {
88+
if (!strcmp(it->tag, tag)) {
89+
//one tag in the linked list match, update the level
90+
*entry = it;
91+
//quit with it != NULL
92+
return true;
93+
}
94+
}
95+
96+
return false;
97+
}
98+
99+
static void clear_log_level_list(void)
100+
{
101+
uncached_tag_entry_t *it = NULL;
102+
103+
SLIST_FOREACH(it, &s_log_uncached_tags, entries) {
104+
SLIST_REMOVE(&s_log_uncached_tags, it, uncached_tag_entry_, entries);
105+
free(it);
106+
}
107+
}
108+
109+
/**
110+
* @brief get level by inputting tag
111+
*/
112+
static esp_log_level_t esp_log_get_level(const char *tag)
113+
{
114+
esp_log_level_t out_level;
115+
uncached_tag_entry_t *entry;
116+
117+
_lock_acquire_recursive(&s_lock);
118+
119+
if (s_uncached_tag_entry_prev && !strcmp(s_uncached_tag_entry_prev->tag, tag)) {
120+
out_level = (esp_log_level_t)s_uncached_tag_entry_prev->level;
121+
goto exit;
122+
}
123+
124+
if (esp_log_get_tag_entry(tag, &entry) == true) {
125+
out_level = (esp_log_level_t)entry->level;
126+
s_uncached_tag_entry_prev = entry;
127+
goto exit;
128+
} else
129+
out_level = s_global_tag_level;
130+
131+
exit:
132+
_lock_release_recursive(&s_lock);
133+
return out_level;
134+
}
135+
136+
/**
137+
* @brief check if system should output data
138+
*/
139+
static inline bool should_output(esp_log_level_t user_level, esp_log_level_t system_level)
140+
{
141+
return user_level <= system_level;
142+
}
143+
144+
/**
145+
* @brief set log level for given tag
146+
*/
147+
void esp_log_level_set(const char *tag, esp_log_level_t level)
148+
{
149+
size_t bytes;
150+
uncached_tag_entry_t *entry, *new_entry;
151+
152+
_lock_acquire_recursive(&s_lock);
153+
154+
if (!strcmp(tag, GLOBAL_TAG)) {
155+
s_global_tag_level = level;
156+
clear_log_level_list();
157+
goto exit;
158+
}
159+
160+
if (esp_log_get_tag_entry(tag, &entry) == true) {
161+
entry->level = level;
162+
goto exit;
163+
}
164+
165+
bytes = strlen(tag) + 1;
166+
167+
new_entry = malloc(sizeof(uncached_tag_entry_t) + bytes);
168+
if (!new_entry)
169+
goto exit;
170+
171+
new_entry->level = level;
172+
memcpy(new_entry->tag, tag, bytes);
173+
174+
SLIST_INSERT_HEAD(&s_log_uncached_tags, new_entry, entries);
175+
176+
exit:
177+
_lock_release_recursive(&s_lock);
178+
}
179+
#endif /* CONFIG_LOG_SET_LEVEL */
180+
61181
static int esp_log_write_str(const char *s)
62182
{
63183
int ret;
@@ -114,9 +234,15 @@ void esp_log_write(esp_log_level_t level, const char *tag, const char *fmt, ...
114234
int ret;
115235
va_list va;
116236
char *pbuf;
117-
char prefix = level >= ESP_LOG_MAX ? 'N' : s_log_prefix[level];
237+
char prefix;
238+
239+
_lock_acquire_recursive(&s_lock);
240+
241+
#ifdef CONFIG_LOG_SET_LEVEL
242+
if (!should_output(level, esp_log_get_level(tag)))
243+
goto exit;
244+
#endif
118245

119-
_lock_acquire(&s_lock);
120246
#ifdef CONFIG_LOG_COLORS
121247
static char buf[16];
122248
uint32_t color = level >= ESP_LOG_MAX ? 0 : s_log_color[level];
@@ -128,7 +254,7 @@ void esp_log_write(esp_log_level_t level, const char *tag, const char *fmt, ...
128254
goto exit;
129255
}
130256
#endif
131-
257+
prefix = level >= ESP_LOG_MAX ? 'N' : s_log_prefix[level];
132258
ret = asprintf(&pbuf, "%c (%d) %s: ", prefix, esp_log_timestamp(), tag);
133259
if (ret < 0)
134260
goto out;
@@ -159,7 +285,7 @@ void esp_log_write(esp_log_level_t level, const char *tag, const char *fmt, ...
159285
s_putchar_func('\n');
160286

161287
exit:
162-
_lock_release(&s_lock);
288+
_lock_release_recursive(&s_lock);
163289
}
164290

165291
/**
@@ -169,10 +295,10 @@ putchar_like_t esp_log_set_putchar(putchar_like_t func)
169295
{
170296
putchar_like_t tmp;
171297

172-
_lock_acquire(&s_lock);
298+
_lock_acquire_recursive(&s_lock);
173299
tmp = s_putchar_func;
174300
s_putchar_func = func;
175-
_lock_release(&s_lock);
301+
_lock_release_recursive(&s_lock);
176302

177303
return tmp;
178304
}

0 commit comments

Comments
 (0)