A small, header-only leveled logger for ESP8266 / ESP32. Logs to Serial and/or the internal filesystem (SPIFFS or LittleFS), with level filtering, dated log files, rotation/cleanup and free-space management. Optional async (FreeRTOS) logging on ESP32.
#include <Logger.h>
MyLogger Logger(ILogger::SerialPort | ILogger::Spiffs, ILogger::LvlDebug);
void setup() {
Serial.begin(115200);
Logger.Setup();
Logger.Log_P(ILogger::LvlInfo, PSTR("Booted, heap=%u"), (unsigned)ESP.getFreeHeap());
}Output: I 12:34:56 Booted, heap=41234
- ESP8266 / ESP32 only. The header
#errors on any other target (no AVR, no SD card). - One global instance named
Logger. The library declares itextern; you define it once (as above).MyLoggeris non-copyable. - Targets (
ILogger::LogTarget, bitmask):SerialPort | Spiffs(Spiffs= the internal filesystem, SPIFFS or LittleFS). - Levels (
ILogger::Level):LvlDebug < LvlInfo < LvlWarning < LvlError < LvlFatal < LvlNone. Messages below the configured level are dropped. - Timestamps come from the system clock (
time()/localtime()); set it via NTP (configTime(...)) for real dates. Without it, time counts from boot and logs land in dateless files (e.g.01-01-70.log). - Line buffering: each line is sized exactly — a small stack buffer
(
LIONLOG_SMALL_BUFFER, default 96 B) for short lines, with an exact-size heap fallback for longer ones (sync) or an exactStringreserve (async). No big always-on buffer. - ESP32 + log clearing:
ClearOldLogs()and the filesystem sweep requireASYNC_LOGon ESP32 — a synchronous sweep deadlocked on the FS semaphore in testing, so the header emits a compile#errorin that configuration. Either enableASYNC_LOG, or defineNO_LOG_CLEARINGto drop clearing entirely.
PlatformIO (platformio.ini):
lib_deps = leva/LionLoggerThis pulls its dependencies, leva/LionArray
and leva/LionRtosTask, automatically.
(LionRtosTask is only compiled on ESP32 when ASYNC_LOG is enabled.)
Arduino IDE: Library Manager → search "LionLogger".
MyLogger Logger(ILogger::SerialPort | ILogger::Spiffs, ILogger::LvlInfo);
Logger.Setup();
Logger.Log(ILogger::LvlInfo, "plain message");
Logger.Log_P(ILogger::LvlError, PSTR("code=%d, name=%s"), code, name);Build with -D ASYNC_LOG (and optionally -D TASK_NAME, -D CORE_LOG=1, ...).
Filesystem writes are batched on a dedicated FreeRTOS task; your Log*() calls
just enqueue and return.
build_flags = -D FS_LOW_SPACE_AUTOCLEAN -D MAX_LOG_BYTES=20000Logger.ClearOldLogs(7); // delete dated logs older than 7 days
Logger.EnsureFreeSpace(8000, 16000); // warn/clean below 8 KB, target 16 KB
if (Logger.IsLowSpace()) { /* light a LED */ }To disable all clearing (and let ESP32 build without ASYNC_LOG):
build_flags = -D NO_LOG_CLEARING.
| Flag | Effect |
|---|---|
LFS |
Use LittleFS instead of SPIFFS. |
ASYNC_LOG (ESP32) |
Offload FS writes to a FreeRTOS task (needs LionRtosTask). |
TASK_NAME (ESP32) |
Tag each line with the FreeRTOS task name + core. |
TASK_NAME_LIMIT |
Truncate the task name to N chars. |
MAX_LOG_ENTRIES_NUMBER |
Async queue cap (default 16). |
CORE_LOG |
Core the async log task is pinned to (default 0). |
FS_LOW_SPACE_AUTOCLEAN / MAX_LOG_BYTES |
Auto-clean policy for EnsureFreeSpace. |
KILL_STARTUP_LOGS |
Delete dateless "no-NTP" logs on boot. |
NO_LOG_CLEARING |
Compile out all clearing/rotation. |
LIONLOG_SMALL_BUFFER |
Short-line stack buffer size (default 96). |
| Member | Description |
|---|---|
MyLogger(targets, level) |
Construct (define the global Logger). |
void Setup() |
Mount the filesystem and report configuration. Call once. |
void Log(Level, const char*) |
Log a plain string. |
void Log_P(Level, const char* fmt, ...) |
Log a printf-style line (fmt in PROGMEM). |
void ClearOldLogs(int days = 7) |
Delete dated logs older than days. |
bool EnsureFreeSpace(low, target) |
Warn/clean when free space drops below low. |
size_t FreeSpaceBytes() / bool IsLowSpace() |
Free-space query / latched flag. |
uint16_t GetErrorNo() / void ResetErrorNo() |
FS write-error counter. |
0BSD — see LICENSE.