Open law-ko opened 8 months ago
There are two issues here:
2. Your spiffs_log_vprintf doesn't guard against re-entry, which may happen for example if SPIFFS or esp_flash layers call ESP_LOGE while handling an attempt to write to the log file. (This is not happening in your case yet, but is an issue still.)
@igrr Thank you for your insight, and how to guard against re-entry?
@igrr We also realized that the output from ESP_LOG is not UTF-8 encoded, as a limitation of our cloud services, it needs to be UTF-8 encoded. Is there any way to do so?
We tried to remove the non UTF-8 characters, but seems like a lot of information is missing.
For example:
read version: %d\u001b[0m\n %-
But it should be:
read version: 0
The %d
is not replaced with the actual value that was added in the ESP_LOG args. However, the logs printed out in console is correct.
and how to guard against re-entry?
Using a thread-local variable is one of the options:
int custom_vprintf(const char *format, va_list args)
{
static __thread bool logging = false;
if (logging) {
// We have re-entered custom_vprintf. Skip writing to a file.
return vprintf(format, args);
} else {
logging = true;
// save the log line to a file
...
logging = false;
return vprintf(format, args); // also log to UART, or alternatively just return the number of characters written.
}
}
... but it depends on what you want to achieve. If you want multiple tasks to have a mutually exclusive access to the log, then you can use a FreeRTOS mutex instead of the thread-local flag, and then use xSemaphoreTake(..., 0) to try taking the semaphore without blocking.
Regarding the issue, I'm sorry, I don't understand the issue. I understand each sentence you wrote separately, but they are not coming together to form a single picture. Could you please explain the issue in a more detailed way? Maybe if you can attache a piece of code which demonstrates the issue it will be better.
@igrr , here's an example of what I mean by it: What is seen on the txt file:
================================
HEAP in DRAM: 139688
====== Heap Trace: 3 records (100 capacity) ======
16 bytes (@ 0x3ffc10fc, Internal) allocated CPU 0 ccount 0x4b316714 caller 0x40152807:0x401528b6
[0;33m0x40152807: mem_malloc at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/mem.c:209
0x401528b6: do_memp_malloc_pool at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/memp.c:254
[0m
16 bytes (@ 0x3ffc1110, Internal) allocated CPU 0 ccount 0x4b3189cc caller 0x40152807:0x401528b6
[0;33m0x40152807: mem_malloc at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/mem.c:209
0x401528b6: do_memp_malloc_pool at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/memp.c:254
[0m
16 bytes (@ 0x3ffc1d8c, Internal) allocated CPU 0 ccount 0x4b31c008 caller 0x40152807:0x401528b6
[0;33m0x40152807: mem_malloc at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/mem.c:209
0x401528b6: do_memp_malloc_pool at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/memp.c:254
[0m
====== Heap Trace Summary ======
What is seen on the terminal output:
================================
HEAP in DRAM: 139688
====== Heap Trace: 3 records (100 capacity) ======
16 bytes (@ 0x3ffc10fc, Internal) allocated CPU 0 ccount 0x724300f4 caller 0x40152807:0x401528b6
0x40152807: mem_malloc at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/mem.c:209
0x401528b6: do_memp_malloc_pool at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/memp.c:254
16 bytes (@ 0x3ffc1110, Internal) allocated CPU 0 ccount 0x724328b4 caller 0x40152807:0x401528b6
0x40152807: mem_malloc at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/mem.c:209
0x401528b6: do_memp_malloc_pool at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/memp.c:254
16 bytes (@ 0x3ffc1d8c, Internal) allocated CPU 0 ccount 0x7243cee4 caller 0x40152807:0x401528b6
0x40152807: mem_malloc at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/mem.c:209
0x401528b6: do_memp_malloc_pool at /home/espuser/esp/esp-idf/components/lwip/lwip/src/core/memp.c:254
====== Heap Trace Summary ======
Those additional characters are ANSI color codes. They make the text you see in the terminal yellow. You can disable them in menuconfig (see CONFIG_LOG_COLORS).
Alternatively, you can post-process the formatted string to remove ANSI escape sequences. There are a bunch of implementations of that online, I hope you can find how to do this.
Hello. Did you resolve your issue?
@adokitkat No I have not, apparently there are more characters that are non UTF-8 that needs to be manually removed.
UTF-8 should be backwards compatible with all of ASCII though. Are you sure this is the real issue here? Maybe there are still some (non-escaped?) ANSI escape codes? Read the output with hex editor to see what characters you have there.
@igrr Another issue we had is that the %d
%s
will still remain as is and not replaced by the provided value by ESP_LOG:
xRingbufferSend() OK: I (%lu) %s: Ack packet deserialized with result: %s.
where it should be
I (10961) coreMQTT: Ack packet deserialized with result: MQTTSuccess.
Here is the vprintf_like_t
function:
int ringbuffer_log_vprintf(const char *fmt, va_list args)
{
// Write to ring buffer
UBaseType_t res = xRingbufferSend(buf_handle, fmt, strlen(fmt), pdMS_TO_TICKS(1000));
if (res != pdTRUE) {
printf("ABORT. xRingbufferSend() failed\n");
return -1;
} else {
printf("xRingbufferSend() OK: %s\n", fmt);
}
// ALSO Write to stdout!
return vprintf(fmt, args);
}
@law-ko: You're sending the pure format string to the ringbuffer. So no wonder that it doesn't work. First you have to evaluate the print function:
int ringbuffer_log_vprintf(const char *format, va_list paramList)
{
va_list copy;
va_copy(copy, paramList);
int size = vsnprintf(NULL, 0, format, copy);
va_end(copy);
if (!size)
{
// your error handling here
return 0;
}
char *ar = malloc(size + 2);
va_copy(copy, paramList);
size = vsnprintf(ar, size + 1, format, paramList);
va_end(copy);
// copy ar to the ringbuffer
[...]
free(ar);
// write to stdout
[...]
return size;
}
Answers checklist.
IDF version.
v5.1.1-577-g6b1f40b9bf-dirty
Espressif SoC revision.
ESP32
Operating System used.
Linux
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
None
Development Kit.
ESP32-PICO-MINI-02
Power Supply used.
USB
What is the expected behavior?
I expect all tasks to not overflow and work as it would like before adding the logging to spiffs.
What is the actual behavior?
Other tasks overflowed.
Steps to reproduce.
The code for initializing and start logging into SPIFFS:
Added
log_spiffs_init()
in app_main.c afternvs_flash_init()
Debug Logs.