Esp_log_set_vprintf() function is not overriding the logs to spiffs files

hello,
I was working on storing the logs of my esp32,
So i came across the function esp_log_set_vprintf, which can override the destination of log messages.
like i wanted to store all the log messages in a .txt file of spiffs
But the function is not overriding

#include "driver/rmt.h"
#include <IRRecv.h>
#include "esp_log.h"
#include <FS.h>
#include <SPIFFS.h>

#define LOG_FILE "/log.txt"

IRRecv backReceiver(RMT_CHANNEL_4);
const byte backRxPin = 17;
String receivedvalue;
int counter = 0;
char log_buffer[256];  // Buffer for logs

// Function to write logs to SPIFFS
void writeLogToFile(const char* message) {
  File file = SPIFFS.open(LOG_FILE, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open log file for writing");
    return;
  }
  file.println(message);
  file.close();
}

// Custom log function to store logs
int customLogFunction(const char *fmt, va_list args) {
  vsnprintf(log_buffer, sizeof(log_buffer), fmt, args);  // Format log message
  Serial.println(log_buffer);  // Print to Serial Monitor
  writeLogToFile(log_buffer);  // Save log to SPIFFS
  return vprintf(fmt, args);   // Pass log to default ESP32 handler
}

void printLogFile() {
    File file = SPIFFS.open(LOG_FILE, FILE_READ);
    if (!file) {
        Serial.println("Failed to open log file");
        return;
    }
    Serial.println("=== Log File Contents ===");
    while (file.available()) {
        Serial.write(file.read());
    }
    file.close();
}


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

  // Initialize SPIFFS
  if (!SPIFFS.begin(true)) {
    Serial.println("SPIFFS initialization failed!");
    return;
  }
  printLogFile();
  // Set custom log function
  esp_log_set_vprintf(customLogFunction);

  backReceiver.start(backRxPin);
}

void loop() {
  if (backReceiver.available()) {
    char* rcvGroup;
    uint32_t result = backReceiver.read(rcvGroup);
    if (result) {
      receivedvalue = String(result, HEX);
      receivedvalue.toUpperCase();
      counter++;
      String logMessage = "Received value: " + receivedvalue + ", Counter: " + String(counter);
      ESP_LOGI("IR_RECEIVER", "%s", logMessage.c_str());  // Log to file
      Serial.println(receivedvalue);
    }
//    backReceiver.clearBuffer();
  }
  delay(100);
}

in my code i am not able to get anything stored in my log file

NEED HELP!!!!!!

Are you seeing output on the Serial monitor?

16:58:45.790 -> [   121][V][esp32-hal-uart.c:330] uartBegin(): UART0 baud(115200) Mode(800001c) rxPin(44) txPin(43)
16:58:45.790 -> [   130][V][esp32-hal-uart.c:416] uartBegin(): UART0 not installed. Starting installation
16:58:45.790 -> [   138][V][esp32-hal-uart.c:463] uartBegin(): UART0 initialization done.
16:58:45.790 -> Initializing SPIFFS...
16:58:45.886 -> ✅ SPIFFS Initialized. Total: 1438481 bytes, Used: 214103 bytes
16:58:45.934 -> ✅ Log file initialized.
16:58:45.934 -> [   262][I][debug-log.ino:92] setup(): [SYSTEM] Logging initialized.
16:58:45.934 -> [   269][W][debug-log.ino:93] setup(): [WARNING] This is a warning log.
16:58:45.934 -> [   275][E][debug-log.ino:94] setup(): [ERROR] This is an error log.
16:58:45.934 -> Reading log file...
16:58:45.934 -> === Log File Contents ===
16:58:45.934 -> === ESP32 Boot Log ===
16:58:45.934 -> 
16:58:45.934 -> === End of Log File ===

i am getting this on serial and my debug level is set to VERBOSE

This seems to be related:
https://github.com/espressif/arduino-esp32/issues/9814

ok thanks, i found something there which worked for me!!

Please post a short, complete code with the solution.

Below code worked for me to store internal logs of library to a txt file in esp32's spiffs

#define CORE_DEBUG_LEVEL 5
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#define USE_ESP_IDF_LOG
#define TAG "MyApp"
#include <Arduino.h>
#include <FS.h>
#include <SPIFFS.h>
#include "esp_log.h"
File logFile;
// Custom log function
int my_log_printf(const char* fmt, va_list args) {
    int result = vprintf(fmt, args);

    if (logFile) {
        char buf[256];
        int len = vsnprintf(buf, sizeof(buf), fmt, args);
        if (len > 0) {
            logFile.write((uint8_t*)buf, len);
            logFile.flush();
        }
    }

    return result;
}
void setup() {
    Serial.begin(115200);
    while (!Serial) delay(10);
    esp_log_level_set("*", ESP_LOG_VERBOSE);
    Serial.printf("CORE_DEBUG_LEVEL: %d\n", CORE_DEBUG_LEVEL);
    Serial.printf("LOG_LOCAL_LEVEL: %d\n", LOG_LOCAL_LEVEL);
    Serial.printf("ESP_LOG_VERBOSE: %d\n", ESP_LOG_VERBOSE);

    // Initialize SPIFFS and open log file
    if (!SPIFFS.begin(true)) {
        Serial.println("SPIFFS mount failed");
        return;
    }

    if (SPIFFS.exists("/log.txt")) {
        SPIFFS.remove("/log.txt");
    }

    logFile = SPIFFS.open("/log.txt", FILE_WRITE);
    if (!logFile) {
        Serial.println("Failed to create log file");
        return;
    }

    // Redirect logging
    esp_log_set_vprintf(my_log_printf);

    Serial.println("\n--- Starting Log Test ---");

    // Test direct ESP-IDF logs first to confirm level filtering
    Serial.println("Testing direct ESP-IDF logs:");
    ESP_LOGV(TAG, "Direct ESP verbose log");
    ESP_LOGD(TAG, "Direct ESP debug log");
    ESP_LOGI(TAG, "Direct ESP info log");
    ESP_LOGW(TAG, "Direct ESP warning log");
    ESP_LOGE(TAG, "Direct ESP error log");

    // Test Arduino-style logs
    Serial.println("\nTesting Arduino logs:");
    log_v("Arduino verbose log");
    log_d("Arduino debug log");
    log_i("Arduino info log");
    log_w("Arduino warning log");
    log_e("Arduino error log");

    // Display log file contents
    logFile.close();

    Serial.println("\n--- Log File Contents ---");
    logFile = SPIFFS.open("/log.txt", FILE_READ);
    if (logFile) {
        while (logFile.available()) {
            Serial.write(logFile.read());
        }
        logFile.close();
    }

    Serial.println("\n--- End of Log File ---");    
    logFile = SPIFFS.open("/log.txt", FILE_APPEND);
}
void loop() {
    delay(5000);
}

But now arises a new problem, even after using above approach i am not able to store some error messages in my log file, and when i went to some particular library i found that these messages are written using some different syntax

ESP_DRAM_LOGE(TAG, "RMT RX BUFFER FULL");

Here DRAM is used for low level debugging

I am trying the same thing using LittleFS. I am also finding that esp_log_set_vprint does not direct ESP_LOG to the designated function.
Here is my code with lots of diagnostics. What I see is that I can write directly to the log file and print out what I write directly but that the function designated by esp_log_set_vprint is never executed.

Any idea why this is not working (note: platform = espressif32@6.5.0 and framework = arduino)

#include <Arduino.h>
#include <LittleFS.h>
#include <esp_log.h>

bool logToSerial = true;
bool logToFile = true;

const char *log_file = "/log.txt";

// Custom vprintf function to write to LittleFS
int my_vprintf(const char *format, va_list args)
{
  static File logFile;
  Serial.println("**** in my_vprintf"); // NEVER REACHES THIS
  // Open or create the log file
  if (!logFile || !logFile.size())
  {
    logFile = LittleFS.open(log_file, "a");
    if (!logFile)
    {
      logFile = LittleFS.open(log_file, "w"); // Create if not exists
      if (!logFile)
      {
        Serial.println("Failed to open/create log file");
        return 0; // Indicate failure
      }
    }
  }

  // Write to the log file
  char buffer[512];
  int len = vsnprintf(buffer, sizeof(buffer), format, args);
  if (len > 0)
  {
    if (logToSerial)
    {
      Serial.println(buffer); // NEVER REACHES THIS
    }

    if (logToFile)
    {
      logFile.print(buffer);
      logFile.flush(); // Ensure data is written to the disk
    }
  }
  return len;
}

void displayLogFile()
{
  if (!LittleFS.exists(log_file))
  {
    Serial.println("No log file exists!");
    return;
  }

  File readFile = LittleFS.open(log_file, "r");
  if (!readFile)
  {
    Serial.println("Failed to open log file for reading!");
    return;
  }

  Serial.printf("Log file size: %d bytes\n", readFile.size());
  Serial.println("\n=== Log File Contents ===");
  while (readFile.available())
  {
    Serial.write(readFile.read());
  }
  Serial.println("\n=== End of Log File ===");

  readFile.close();
}

void initializeLittleFS()
{
  if (!LittleFS.begin(true)) // true parameter formats the filesystem if mount fails
  {
    Serial.println("LittleFS mount failed! Formatting...");
    if (!LittleFS.format())
    {
      Serial.println("LittleFS format failed!");
      return;
    }
    if (!LittleFS.begin())
    {
      Serial.println("LittleFS mount failed after formatting!");
      return;
    }
  }
  Serial.println("LittleFS mounted successfully");

  // Create an empty log file if it doesn't exist
  if (!LittleFS.exists(log_file))
  {
    File f = LittleFS.open(log_file, "w");
    if (!f)
    {
      Serial.println("Failed to create log file!");
      return;
    }
    f.close();
    Serial.println("Created new log file");
  }
}

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

  initializeLittleFS();
  // Register the custom logging handler
  esp_log_set_vprintf(my_vprintf);

  esp_log_level_set("*", ESP_LOG_VERBOSE);

  // Test direct file writing first
  Serial.println("Testing direct file write...");
  File testFile = LittleFS.open(log_file, "w");
  if (testFile)
  {
    testFile.println("Test direct write");
    testFile.close();
    Serial.println("Direct write test completed");
  }
  else
  {
    Serial.println("Direct write test failed!");
  }

  // Test logging with both methods enabled
  logToSerial = true;
  logToFile = true;
  Serial.println("Testing logging with both methods enabled:");

  // Test with different log levels
  ESP_LOGE("MYAPP", "Error log test");
  ESP_LOGW("MYAPP", "Warning log test");
  ESP_LOGI("MYAPP", "Info log test: Value: %d", 42);
  ESP_LOGD("MYAPP", "Debug log test");
  ESP_LOGV("MYAPP", "Verbose log test");

  // Display the log file contents after disabling logging
  Serial.println("\nDisplaying log file contents");
  displayLogFile();
}

void loop()
{
}

Here is the output:

LittleFS mounted successfully
Testing direct file write...
Direct write test completed
Testing logging with both methods enabled:
[   349][E][main.cpp:137] setup(): [MYAPP] Error log test
[   349][W][main.cpp:138] setup(): [MYAPP] Warning log test
[   355][I][main.cpp:139] setup(): [MYAPP] Info log test: Value: 42
[   361][D][main.cpp:140] setup(): [MYAPP] Debug log test
[   366][V][main.cpp:141] setup(): [MYAPP] Verbose log test

Displaying log file contents
Log file size: 19 bytes

=== Log File Contents ===
Test direct write

=== End of Log File ===

and my platformio.ini

[env]
platform = espressif32@6.5.0
board_build.partitions = default_partitions.csv
framework = arduino
board_build.filesystem = littlefs
lib_ldf_mode = deep
lib_extra_dirs = ~/Documents/Arduino/libraries
monitor_speed = 115200
build_unflags = -std=gnu++11
build_flags = 
	-std=gnu++17
	-fmax-errors=5
	-I./src/
	-DCORE_DEBUG_LEVEL=5
	-mfix-esp32-psram-cache-issue
lib_deps = 


[env:ESP32-S3-N8R8-GENUINE]
board = ESP32-S3-N8R8-GENUINE

[env:ESP32-S3-N8R2-PURPLE-AI]
board = ESP32-S3-N8R2-PURPLE-AI

I picked this up from the ever useful platformio forum...

https://community.platformio.org/t/redirect-esp32-log-messages-to-sd-card/33734/15

add these three build_flags and the code works.

-DUSE_ESP_IDF_LOG
-DCORE_DEBUG_LEVEL=5
-DTAG="\"ARDUINO\""

I was so darn happy to get this working that I created a library...
This will allow you to log all ESP_LOG output to a file either on LittleFS or on an SD card while also getting Serial output of the ESP_LOG messages.
You can turn the logging to the file or to Serial on and off independently anywhere in your code. Supporting functions include outputting the log file.

This is my first public library, so be kind.

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