I just implemented something similar a few weeks ago that seems to work well, if it's useful for you.
I was using it so I could turn off logging at runtime so that I could leave Log()
calls in when serial wasn't connected and I wouldn't take a performance hit.
// log handler instance
StreamLogHandler* logHandler;
// store the previous one in case we want to go back to it
StreamLogHandler* previousLogHandler;
// Set logging to level, with filters for other categories
void setLogging(LogLevel level, LogCategoryFilters filters) {
auto logManager = LogManager::instance();
pushLogHandler(logHandler);
logManager->removeHandler(logHandler);
logHandler = new StreamLogHandler(Serial, level, filters);
logManager->addHandler(logHandler);
}
// Set logging to level with default filters
void setLogging(LogLevel level) {
LogCategoryFilters filters = {
{ "app", level }, // Logging level for application messages
// comm.coap logs are obnoxious and you don't want them (probably)
{ "comm.coap", (level==LOG_LEVEL_NONE?LOG_LEVEL_NONE:LOG_LEVEL_INFO) },
};
setLogging(level, filters);
}
// Save the current log handler
static void pushLogHandler(StreamLogHandler* handler) {
previousLogHandler = handler;
}
// Return the previous log handler
static StreamLogHandler* popLogHandler(void) {
return previousLogHandler;
}
// Restore the previously set log handler
void resetLoggingLevel(void) {
auto logManager = LogManager::instance();
logManager->removeHandler(logHandler);
logHandler = popLogHandler();
logManager->addHandler(logHandler);
}
In my application I can hop between logging levels by simply calling setLogging(LogLevel)
or I could add more explicit filters with setLogging(LogLevel, LogCategoryFilters)