Alex2ESP/src/AlexaLog.cpp
David 6e15226ce0 Log: one line for whatever is dropped, a level the build lacks is reported, no false alarm for a 1.x handler
Audit of the paths that drop or refuse something. registerEvent() dropped an eleventh
handler and a second one for the same name without a word: the name now gets the new
handler, an eleventh name and a call without a name or a function print an error. A
device that cannot be announced printed two lines, one without its id; it prints one.
setLogLevel() above ALEX2ESP_LOG_MAX prints an error that names the build flag.
"the handler sent no answer" is an error for a handler of onDirective() only: a 1.x
handler may answer from a later loop(), its silence is a line at DEBUG.
getDevice() returning nullptr and printMemoryInfo() are documented; keywords.txt has
the 2.0 names and loses three that were removed.
basicLight: static RAM 30,520 B, flash 333,989 B (+600); ALEX2ESP_LOG_MAX=0 30,496 /
327,953, =3 30,520 / 334,477; five examples, log0 and log3 build with 0 warnings.
Host tests: 135 (dispatch 11 -> 16).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 21:10:19 +00:00

63 lines
1.8 KiB
C++

#include "AlexaLog.h"
#include <stdarg.h>
// This file names the levels. A build flag such as -DDEBUG defines its macro here as well (see AlexaLog.h).
#undef NONE
#undef ERROR
#undef INFO
#undef DEBUG
AlexaLogLevel AlexaLog::level = AlexaLogLevel::INFO;
Print *AlexaLog::output = &Serial;
void AlexaLog::setLevel(AlexaLogLevel newLevel)
{
level = newLevel;
// The lines above the ceiling are not in the program. Without this line a sketch that asks for them waits for
// output that cannot come.
if (static_cast<int>(newLevel) > ALEX2ESP_LOG_MAX)
{
ALEX2ESP_LOGE("log level %d asked for, the lines of this build end at level %d: build with -DALEX2ESP_LOG_MAX=%d",
static_cast<int>(newLevel), ALEX2ESP_LOG_MAX, static_cast<int>(newLevel));
}
}
AlexaLogLevel AlexaLog::getLevel()
{
return level;
}
void AlexaLog::setOutput(Print *newOutput)
{
output = newOutput;
}
bool AlexaLog::enabled(AlexaLogLevel lineLevel)
{
return output != nullptr && lineLevel != AlexaLogLevel::NONE && lineLevel <= level;
}
void AlexaLog::write(AlexaLogLevel lineLevel, PGM_P format, ...)
{
if (!enabled(lineLevel))
{
return;
}
// vsnprintf and not vsnprintf_P: on the ESP8266 vsnprintf reads a PROGMEM format itself (vsnprintf_P is a jump
// to it), and vsnprintf_P comes in one object with printf_P and sprintf_P, which link the FILE-based printf:
// 5.8 KB of flash.
char line[160];
va_list arguments;
va_start(arguments, format);
int written = vsnprintf(line, sizeof(line), format, arguments);
va_end(arguments);
if (written < 0)
{
return;
}
output->print(lineLevel == AlexaLogLevel::ERROR ? F("[Alex2ESP] error: ") : F("[Alex2ESP] "));
output->println(line);
}