Esp_log_level_set() is not working?

Hello,

Trying to understand how logging works on ESP32

I have set "Core debug level" in Arduino IDE to "Verbose"

It results in huge amounts of debug strings in my serial monitor.

Then I call esp_log_level_set("*", LOG_LEVEL_ERROR) and trying to call log_i(), log_w(), log_v() and get all the messages although all of them should be suppressed except for log_e() messages.

What I want is to set "Core debug level" to "Error" but be able to change it to "Verbose" in runtime. Is it possible? Tried ESP_LOGX macros as well with no success. Tried to use "*" instead of TAG when calling esp_log_level_set().

Code below prints 6 lines :

static const char *TAG = "tag"; 

esp_log_level_set(TAG, ESP_LOG_ERROR);

ESP_LOGV(TAG,"LOG_V");
ESP_LOGD(TAG,"LOG_D");
ESP_LOGE(TAG,"LOG_E");

esp_log_level_set(TAG, ESP_LOG_DEBUG);

ESP_LOGV(TAG,"LOG_V");
ESP_LOGD(TAG,"LOG_D");
ESP_LOGE(TAG,"LOG_E");

Internet search shows that many people have the same problem.

Looks like esp_log_level_set() does nothing. The debug level is defined solely by Arduino IDE option

Due to the rat's nest of macros, including in the hidden <Arduino.h>, it has no effect in the .ino, but it does work if you use "raw" ESP IDF in a separate module. For example, create a separate file "foo.cpp" in the sketch (use New Tab in meatball menu to the right of the tabs)

// separate non-.ino module
// Core Debug Level has no effect; defaults to ESP_LOG_ERROR
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#include <esp_log.h>  // have to include this manually

void foo() {
  static const char *TAG = "foo";

  esp_log_level_set(TAG, ESP_LOG_ERROR);

  ESP_LOGV(TAG, "LOG_V");
  ESP_LOGD(TAG, "LOG_D");
  ESP_LOGW(TAG, "LOG_W");
  ESP_LOGE(TAG, "LOG_E");

  esp_log_level_set(TAG, ESP_LOG_VERBOSE);

  ESP_LOGV(TAG, "LOG_V");
  ESP_LOGD(TAG, "LOG_D");
  ESP_LOGW(TAG, "LOG_W");
  ESP_LOGE(TAG, "LOG_E");
}

Then in the sketch .ino

#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG  // too late; doesn't work in .ino

void setup() {
  Serial.begin(115200);
}

void foo();  // simple forward declaration; no separate header needed

void loop() {
  static const char *TAG = "ino";

  esp_log_level_set(TAG, ESP_LOG_ERROR);

  ESP_LOGV(TAG, "LOG_V");
  ESP_LOGD(TAG, "LOG_D");
  ESP_LOGW(TAG, "LOG_W");
  ESP_LOGE(TAG, "LOG_E");

  esp_log_level_set(TAG, ESP_LOG_VERBOSE);

  ESP_LOGV(TAG, "LOG_V");
  ESP_LOGD(TAG, "LOG_D");
  ESP_LOGW(TAG, "LOG_W");
  ESP_LOGE(TAG, "LOG_E");

  foo();
  delay(5000);
}

Then Upload with Core Debug Level: Info. The repeated output is like

[ 10093][W][sketch_sep4a.ino:17] loop(): [ino] LOG_W
[ 10098][E][sketch_sep4a.ino:18] loop(): [ino] LOG_E
[ 10103][W][sketch_sep4a.ino:24] loop(): [ino] LOG_W
[ 10107][E][sketch_sep4a.ino:25] loop(): [ino] LOG_E
E (10091) foo: LOG_E
D (10091) foo: LOG_D
W (10091) foo: LOG_W
E (10091) foo: LOG_E

The formatted message from the .ino includes the filename and line number. Compiled at Info, they do not include the Debug messages.

esp_log_level_set does take effect in the plain .cpp

1 Like

Thanks for explanation!

I was able to make esp_log_level_set() work for me in Arduino code. The solution is as follows:
I created mylog.h with the following content:

#ifndef MYLOG_H
#define MYLOG_H

// Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-632e0c2a/esp32/include/log/include/
#include <esp_log.h>
// Library/Arduino15/packages/esp32/hardware/esp32/3.0.7/cores/esp32/esp32-hal-log.h
#include <esp32-hal-log.h>


#undef CONFIG_LOG_MAXIMUM_LEVEL
#define CONFIG_LOG_MAXIMUM_LEVEL CORE_DEBUG_LEVEL

#undef ESP_LOGE
#undef ESP_LOGW
#undef ESP_LOGI
#undef ESP_LOGD
#undef ESP_LOGV

#define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR,   tag, ARDUHAL_LOG_FORMAT(E, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGW( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN,    tag, ARDUHAL_LOG_FORMAT(W, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGI( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO,    tag, ARDUHAL_LOG_FORMAT(I, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGD( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG,   tag, ARDUHAL_LOG_FORMAT(D, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGV( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, ARDUHAL_LOG_FORMAT(V, format) __VA_OPT__(,) __VA_ARGS__)

#undef ARDUHAL_LOG_FORMAT
#define ARDUHAL_LOG_FORMAT(letter, format)				\
  ARDUHAL_LOG_COLOR_##letter "[%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR,  \
    pathToFileName(__FILE__), __LINE__, __FUNCTION__

#endif // MYLOG_H

Then include the file in my code in place of including esp_log.h:

#include <mylog.h>

This replaces the macros for ESP_LOGx as defined in esp_log.h with macros that work with esp_log_level_set().

4 Likes

Great job. Thanks.

Here is a slightly improved and more unambiguous piece of test code and my fully documented version of your code.

also note the following:

  1. I often use multiple serial ports so I always name the port that I use for logging and monitoring "SerialMon" and that is reflected in my code below. You do not necessarilly need to do that. You can eliminate the "#define SerialMon Serial" line and just use "Serial" if you like in each place where I used "SerialMon"

  2. Some esp32 processors, such ESP32-S2 Mini, still have issues with esp-log. See the setDebugOutput(true) statement in the code below.

  3. This must be included in platformio.ini if using platformio

build_flags = 
	-DCORE_DEBUG_LEVEL=5

Here is the test code.

#include "myesp_log.h"
#define SerialMon Serial
void setup(void)
{
  SerialMon.begin(115200);
  while (!Serial)
      ;
  SerialMon.setDebugOutput(true);  // this is important for some esp processors such as S2-mini


  // Set global log level to to some level initially
  esp_log_level_set("*", MY_GLOBAL_DEBUG_LEVEL);

  static const char *TAG = "tag";
  static const char *TAG2 = "OTHERtag";

   esp_log_level_set(TAG, ESP_LOG_ERROR);

   ESP_LOGV(TAG,"LOG_V");
   ESP_LOGD(TAG,"LOG_D");
   ESP_LOGE(TAG,"LOG_E");
   ESP_LOGV(TAG2,"LOG_V");
   ESP_LOGD(TAG2,"LOG_D");
   ESP_LOGE(TAG2,"LOG_E");
   

  esp_log_level_set(TAG, ESP_LOG_DEBUG);

  ESP_LOGV(TAG,"LOG_V2");
  ESP_LOGD(TAG,"LOG_D2");
  ESP_LOGE(TAG,"LOG_E2");
  ESP_LOGV(TAG2,"LOG_V");
  ESP_LOGD(TAG2,"LOG_D");
  ESP_LOGE(TAG2,"LOG_E");

  for(;;)
}

fully documented version of myesp_log.h

#ifndef MYESP_LOG_H
#define MYESP_LOG_H

//** NOTES:  
//***
//**   USE myesp_log.h IN PLACE OF esp_log.h
//**
//**   1) this must be included in platformio.ini
//**       build_flags = 
//**         -DCORE_DEBUG_LEVEL=5 */
//**
//**   2) in main.cpp, before setup(), include the following:
//**
//**           #include "myesp_log.h"
//**           #define MY_GLOBAL_DEBUG_LEVEL ESP_LOG_DEBUG  // for example
//**
//**   3) in setup(), include the following after setting up Serial port
//**           Serial.setDebugOutput(true);  // this is important for some esp processors such as S2-mini 
//**
//**           // Set global log level to to some level initially
//**           esp_log_level_set("*", MY_GLOBAL_DEBUG_LEVEL);
//**
//**      then in subsequent code, you can use lines like the following to change the log level for each function, such as...
//**
//**           esp_log_level_set(TAG, ESP_LOG_ERROR);


// Library/Arduino15/packages/esp32/tools/esp32-arduino-libs/idf-release_v5.1-632e0c2a/esp32/include/log/include/
#include <esp_log.h>
// Library/Arduino15/packages/esp32/hardware/esp32/3.0.7/cores/esp32/esp32-hal-log.h
#include <esp32-hal-log.h>


#undef CONFIG_LOG_MAXIMUM_LEVEL
#define CONFIG_LOG_MAXIMUM_LEVEL CORE_DEBUG_LEVEL

#undef ESP_LOGE
#undef ESP_LOGW
#undef ESP_LOGI
#undef ESP_LOGD
#undef ESP_LOGV

#define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR,   tag, ARDUHAL_LOG_FORMAT(E, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGW( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN,    tag, ARDUHAL_LOG_FORMAT(W, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGI( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO,    tag, ARDUHAL_LOG_FORMAT(I, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGD( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG,   tag, ARDUHAL_LOG_FORMAT(D, format) __VA_OPT__(,) __VA_ARGS__)
#define ESP_LOGV( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, ARDUHAL_LOG_FORMAT(V, format) __VA_OPT__(,) __VA_ARGS__)

#undef ARDUHAL_LOG_FORMAT
#define ARDUHAL_LOG_FORMAT(letter, format)				\
  ARDUHAL_LOG_COLOR_##letter "[%s:%u] %s(): " format ARDUHAL_LOG_RESET_COLOR,  \
    pathToFileName(__FILE__), __LINE__, __FUNCTION__

#endif // MYESP_LOG_H

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.