From 1c3f5a3a9b5e99d5fa64147251aa25cab7f8ed8a Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 29 Sep 2025 23:32:33 +0200 Subject: [PATCH] Fix file flushing issue on ESP32 - implement configurable smart flushing policy (#22) * Initial plan * Implement smart file flushing policy for issue #21 Co-authored-by: jibrilsharafi <83494924+jibrilsharafi@users.noreply.github.com> * Make flush log level configurable and add README documentation Co-authored-by: jibrilsharafi <83494924+jibrilsharafi@users.noreply.github.com> * Simplify flush configuration by removing FLUSH_ON_ERROR define Co-authored-by: jibrilsharafi <83494924+jibrilsharafi@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jibrilsharafi <83494924+jibrilsharafi@users.noreply.github.com> --- README.md | 12 ++++++++++++ src/AdvancedLogger.cpp | 29 +++++++++++++++++++++++++++-- src/AdvancedLogger.h | 10 ++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 04b7322..773c2dd 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,18 @@ build_flags = -DADVANCED_LOGGER_MAX_MESSAGE_LENGTH=512 ``` +### File Flushing +Configure when log files are flushed to ensure data persistence: + +```cpp +#define ADVANCED_LOGGER_FLUSH_INTERVAL_MS 5000 // Flush every 5 seconds (default) +#define ADVANCED_LOGGER_FLUSH_LOG_LEVEL LogLevel::ERROR // Log level that triggers immediate flush (default) + +#include "AdvancedLogger.h" +``` + +The library automatically flushes files periodically and on the specified log level to prevent data loss during power cycles or crashes. + ### Callbacks Register a function to handle log entries: diff --git a/src/AdvancedLogger.cpp b/src/AdvancedLogger.cpp index 797b5fb..f7a19ba 100644 --- a/src/AdvancedLogger.cpp +++ b/src/AdvancedLogger.cpp @@ -38,6 +38,9 @@ namespace AdvancedLogger static TaskHandle_t _logTaskHandle = nullptr; static bool _queueInitialized = false; + // File flushing control + static unsigned long _lastFlushTime = 0; + // Forward declarations of private functions static void _log(const char *message, const char *file, const char *function, int line, LogLevel logLevel); static void _internalLog(const char* level, const char* format, ...); @@ -142,6 +145,9 @@ namespace AdvancedLogger _logLines = getLogLines(); + // Initialize flush timestamp + _lastFlushTime = millis(); + _initLogQueue(); _internalLog("DEBUG", "AdvancedLogger initialized"); @@ -331,7 +337,11 @@ namespace AdvancedLogger #endif #ifndef ADVANCED_LOGGER_DISABLE_FILE_LOGGING - if (entry.level >= _saveLevel) _save(messageFormatted); + if (entry.level >= _saveLevel) { + // Determine if immediate flush is needed based on log level + bool forceFlush = (entry.level >= ADVANCED_LOGGER_FLUSH_LOG_LEVEL); + _save(messageFormatted, forceFlush); + } #endif } @@ -657,7 +667,21 @@ namespace AdvancedLogger if (!_checkAndOpenLogFile(FileMode::APPEND)) return; _logFile.println(messageFormatted); - if (flush) _logFile.flush(); + + // Smart flushing logic + unsigned long currentTime = millis(); + bool shouldFlush = flush; + + // Check if periodic flush interval has elapsed + if (!shouldFlush && (currentTime - _lastFlushTime >= ADVANCED_LOGGER_FLUSH_INTERVAL_MS)) { + shouldFlush = true; + } + + if (shouldFlush) { + _logFile.flush(); + _lastFlushTime = currentTime; + } + _logLines++; if (_logLines >= _maxLogLines) { @@ -830,6 +854,7 @@ namespace AdvancedLogger void _closeLogFile() { if (_logFile) { + _logFile.flush(); // Ensure all data is written before closing _logFile.close(); _currentFileMode = FileMode::APPEND; // Reset to default } diff --git a/src/AdvancedLogger.h b/src/AdvancedLogger.h index 605c629..3823a1d 100644 --- a/src/AdvancedLogger.h +++ b/src/AdvancedLogger.h @@ -33,6 +33,8 @@ * - ADVANCED_LOGGER_TASK_PRIORITY: Priority for the log processing task. * - ADVANCED_LOGGER_TASK_CORE: Core ID for the log processing task. * - ADVANCED_LOGGER_MAX_MESSAGE_LENGTH: Maximum length of log messages. + * - ADVANCED_LOGGER_FLUSH_INTERVAL_MS: Interval in milliseconds for periodic file flushing (default: 5000ms). + * - ADVANCED_LOGGER_FLUSH_LOG_LEVEL: Log level that triggers immediate flush (default: ERROR). * * Usage: * In platformio.ini: build_flags = -DADVANCED_LOGGER_ALLOCABLE_HEAP_SIZE=10240 @@ -63,6 +65,14 @@ #define ADVANCED_LOGGER_MAX_MESSAGE_LENGTH 512 #endif +#ifndef ADVANCED_LOGGER_FLUSH_INTERVAL_MS + #define ADVANCED_LOGGER_FLUSH_INTERVAL_MS 5000 // Flush every 5 seconds +#endif + +#ifndef ADVANCED_LOGGER_FLUSH_LOG_LEVEL + #define ADVANCED_LOGGER_FLUSH_LOG_LEVEL LogLevel::ERROR // Default to ERROR level +#endif + /* * Compilation flags to conditionally disable logging: