How to properly change log level at runtime?

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)

4 Likes