Arduino core for ESP32 Wiki content

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