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
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
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 ===
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.