ESP32 application log output in the same format as the core log output
I love the ESP32 core level log output. It is easy to configure and gives me the file name and line number where the log output was created:
[D][BLEAdvertising.cpp:189] start(): - advertising service: 0000aaaa-ead2-11e7-80c1-9a214cf093
But when I want to use the same log functions for log output from my application, I have the problem that all output is mixed up and it is difficult to see the logs from my application between all the lines of the core log output:
[main.cpp:24] setup(): =====================================
[V][main.cpp:25] setup(): SX126x ESP32 collector test
[V][main.cpp:26] setup(): =====================================
[V][main.cpp:28] setup(): Version: 1.00
[V][main.cpp:29] setup(): Compiled: Aug 4 2019 19:45:04
[V][main.cpp:30] setup(): SDK version: v3.2.2-44-ga8916daeb
[D][wifi.cpp:86] getPreferences(): Preferences: primary SSID: private pw: unknown secondary SSID: private pw: unknown
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
[D][wifi.cpp:111] createName(): Device name: PPGcoll-240AC40535E0
[D][wifi.cpp:168] scanWiFi(): Start scanning for networks
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 1 - SCAN_DONE
[D][wifi.cpp:188] scanWiFi(): Found AP: private RSSI: -44
[D][wifi.cpp:188] scanWiFi(): Found AP: private RSSI: -70
[D][wifi.cpp:191] scanWiFi(): Found primary AP
[D][wifi.cpp:198] scanWiFi(): Found secondary AP
[D][wifi.cpp:222] scanWiFi(): RSSI Prim: -70 Sec: -70
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
What I want is
[V][main.cpp:24] setup(): =====================================
[V][main.cpp:25] setup(): SX126x ESP32 collector test
[V][main.cpp:26] setup(): =====================================
[V][main.cpp:28] setup(): Version: 1.00
[V][main.cpp:29] setup(): Compiled: Aug 4 2019 18:13:55
[V][main.cpp:30] setup(): SDK version: v3.2.2-44-ga8916daeb
[D][wifi.cpp:86] getPreferences(): Preferences: primary SSID: private pw: unknown secondary SSID: private pw: unknown
[D][wifi.cpp:111] createName(): Device name: PPGcoll-240AC40535E0
[D][wifi.cpp:168] scanWiFi(): Start scanning for networks
[D][wifi.cpp:188] scanWiFi(): Found AP: MHC2 RSSI: -40
[D][wifi.cpp:188] scanWiFi(): Found AP: MyLTE RSSI: -67
[D][wifi.cpp:191] scanWiFi(): Found primary AP
[D][wifi.cpp:198] scanWiFi(): Found secondary AP
[D][wifi.cpp:222] scanWiFi(): RSSI Prim: -67 Sec: -67
So I looked how the core level log output works and created a similar output that gives me the option to mix application log output of any level I want with core log output of any level I want. E.g. I want only ERROR level logs from the core, but I want to have DEBUG level logs from my application.
The file I created duplicates the core log defines as my application log defines. Inside my application code I use myLog_x() functions instead of the log_x() functions to create log output.
Example:
Serial.println("Next line will be logged only if log level ERROR is set!");
myLog_e("Log level is MYLOG_LOG_LEVEL_ERROR");
Serial.println("Next line will be logged only if log level WARN is set!");
myLog_w("Log level is MYLOG_LOG_LEVEL_WARN");
Serial.println("Next line will be logged only if log level INFO is set!");
myLog_i("Log level is MYLOG_LOG_LEVEL_INFO");
Serial.println("Next line will be logged only if log level DEBUG is set!");
myLog_d("Log level is MYLOG_LOG_LEVEL_DEBUG");
Serial.println("Next line will be logged only if log level VERBOSE is set!");
myLog_v("Log level is MYLOG_LOG_LEVEL_VERBOSE");
And all is done with a simple header file.
Source code and more explanation is in my >>> Github repo <<<.
Here is the simple header file I created:
#ifndef
__MY_LOG_H__
#define __MY_LOG_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include "sdkconfig.h"
#define MYLOG_LOG_LEVEL_NONE (0)
#define MYLOG_LOG_LEVEL_ERROR (1)
#define MYLOG_LOG_LEVEL_WARN (2)
#define MYLOG_LOG_LEVEL_INFO (3)
#define MYLOG_LOG_LEVEL_DEBUG (4)
#define MYLOG_LOG_LEVEL_VERBOSE (5)
#ifndef CONFIG_MYLOG_LOG_DEFAULT_LEVEL
#define CONFIG_MYLOG_LOG_DEFAULT_LEVEL MYLOG_LOG_LEVEL_NONE
#endif
#ifndef MYLOG_LOG_LEVEL
#define MYLOG_LOG_LEVEL MYLOG_LOG_LEVEL_NONE
#endif
#define MYLOG_LOG_COLOR_E
#define MYLOG_LOG_COLOR_W
#define MYLOG_LOG_COLOR_I
#define MYLOG_LOG_COLOR_D
#define MYLOG_LOG_COLOR_V
#define MYLOG_LOG_RESET_COLOR
const char *pathToFileName(const char *path);
int log_printf(const char *fmt, ...);
#define MYLOG_SHORT_LOG_FORMAT(letter, format) MYLOG_LOG_COLOR_##letter
format MYLOG_LOG_RESET_COLOR "\r\n"
#define MYLOG_LOG_FORMAT(letter, format) MYLOG_LOG_COLOR_##letter "["
#letter "][%s:%u] %s(): " format MYLOG_LOG_RESET_COLOR "\r\n",
pathToFileName(__FILE__), __LINE__, __FUNCTION__
#if MYLOG_LOG_LEVEL >= MYLOG_LOG_LEVEL_VERBOSE
#define myLog_v(format, ...) log_printf(MYLOG_LOG_FORMAT(V, format),
##__VA_ARGS__)
#define myIsr_log_v(format, ...) ets_printf(MYLOG_LOG_FORMAT(V, format),
##__VA_ARGS__)
#else
#define myLog_v(format, ...)
#define myIsr_log_v(format, ...)
#endif
#if MYLOG_LOG_LEVEL >= MYLOG_LOG_LEVEL_DEBUG
#define myLog_d(format, ...) log_printf(MYLOG_LOG_FORMAT(D, format),
##__VA_ARGS__)
#define myIsr_log_d(format, ...) ets_printf(MYLOG_LOG_FORMAT(D, format),
##__VA_ARGS__)
#else
#define myLog_d(format, ...)
#define myIsr_log_d(format, ...)
#endif
#if MYLOG_LOG_LEVEL >= MYLOG_LOG_LEVEL_INFO
#define myLog_i(format, ...) log_printf(MYLOG_LOG_FORMAT(I, format),
##__VA_ARGS__)
#define myIsr_log_i(format, ...) ets_printf(MYLOG_LOG_FORMAT(I, format),
##__VA_ARGS__)
#else
#define myLog_i(format, ...)
#define myIsr_log_i(format, ...)
#endif
#if MYLOG_LOG_LEVEL >= MYLOG_LOG_LEVEL_WARN
#define myLog_w(format, ...) log_printf(MYLOG_LOG_FORMAT(W, format),
##__VA_ARGS__)
#define myIsr_log_w(format, ...) ets_printf(MYLOG_LOG_FORMAT(W, format),
##__VA_ARGS__)
#else
#define myLog_w(format, ...)
#define myIsr_log_w(format, ...)
#endif
#if MYLOG_LOG_LEVEL >= MYLOG_LOG_LEVEL_ERROR
#define myLog_e(format, ...) log_printf(MYLOG_LOG_FORMAT(E, format),
##__VA_ARGS__)
#define myIsr_log_e(format, ...) ets_printf(MYLOG_LOG_FORMAT(E, format),
##__VA_ARGS__)
#else
#define myLog_e(format, ...)
#define myIsr_log_e(format, ...)
#endif
#if MYLOG_LOG_LEVEL >= MYLOG_LOG_LEVEL_NONE
#define myLog_n(format, ...) log_printf(MYLOG_LOG_FORMAT(E, format),
##__VA_ARGS__)
#define myIsr_log_n(format, ...) ets_printf(MYLOG_LOG_FORMAT(E, format),
##__VA_ARGS__)
#else
#define myLog_n(format, ...)
#define myIsr_log_n(format, ...)
#endif
#include "esp_log.h"
#ifdef CONFIG_MYLOG_ESP_LOG
#undef ESP_LOGE
#undef ESP_LOGW
#undef ESP_LOGI
#undef ESP_LOGD
#undef ESP_LOGV
#undef ESP_EARLY_LOGE
#undef ESP_EARLY_LOGW
#undef ESP_EARLY_LOGI
#undef ESP_EARLY_LOGD
#undef ESP_EARLY_LOGV
#define ESP_LOGE(tag, ...) log_e(__VA_ARGS__)
#define ESP_LOGW(tag, ...) log_w(__VA_ARGS__)
#define ESP_LOGI(tag, ...) log_i(__VA_ARGS__)
#define ESP_LOGD(tag, ...) log_d(__VA_ARGS__)
#define ESP_LOGV(tag, ...) log_v(__VA_ARGS__)
#define ESP_EARLY_LOGE(tag, ...) isr_log_e(__VA_ARGS__)
#define ESP_EARLY_LOGW(tag, ...) isr_log_w(__VA_ARGS__)
#define ESP_EARLY_LOGI(tag, ...) isr_log_i(__VA_ARGS__)
#define ESP_EARLY_LOGD(tag, ...) isr_log_d(__VA_ARGS__)
#define ESP_EARLY_LOGV(tag, ...) isr_log_v(__VA_ARGS__)
#endif
#ifdef __cplusplus
}
#endif
#endif /* __MY_LOG_H__ */
Hope it helps someone to get better log output from his application