Changing the SerialLogHandler logging level

Hi! I’m trying to change the logging level of a SerialLogHandler after its initial setup to enable/disable serial debugging. As far as I can tell, log handlers do not have set functions and simply replacing the log handler using

logHandler = SerialLogHandler(debug ? LOG_LEVEL_ALL : LOG_LEVEL_WARN);

does not compile and results in the following error:

use of deleted function 'spark::SerialLogHandler& spark::SerialLogHandler::operator=(const spark::SerialLogHandler&)'

I suspect there is a different workflow to this, but I’m having trouble figuring out where to start. Your help is much appreciated!

The logging level is set in the initialiser of the SerialLogHandler object. You cannot then change that AFAIK.

SerialLogHandler logHandler(LOG_LEVEL_ALL);
What you could do is call different Log levels in your code, for example;

if (warning_event)
{
    Log.warn("This is warning message");
}
else
{
    Log.error("This is error message");
}

Typically I would only switch on logging when developing and debugging - so clearly not yet following TDD!

1 Like

You can change the log level at runtime. For example, I have the default set to INFO here:

SerialLogHandler logHandler(LOG_LEVEL_INFO);

Then I use this function to enable trace logging:

void enableTraceLogging() {
	Log.info("enabling trace logging");

	// Get log manager's instance
	auto logManager = LogManager::instance();

	// Configure and register log handler dynamically
	auto handler = new StreamLogHandler(Serial, LOG_LEVEL_TRACE);
	logManager->addHandler(handler);
}
3 Likes

Amazing, would it be possible to include this as an example in the documentation?

Thank you both very much for your help and insights! The solution @rickkas7 proposes is along the lines of what I need, with the difference that I want to be able to switch both ways. To facilitate cases where a decrease in logging granularity is desired, the previously added handler needs to be removed. I have implemented a solution that works both ways, but I feel there might be a more elegant solution.

StreamLogHandler* logHandler;
boolean debugMode = true;

void setup() {
    setDebugState(debugMode);
}

void setDebugState(boolean targetState){
    Log.info("%s debugging mode", targetState ? "Enabling" : "Disabling");
    auto logManager = LogManager::instance();
    logManager->removeHandler(logHandler);
    logHandler = new StreamLogHandler(Serial, targetState ? LOG_LEVEL_ALL : LOG_LEVEL_WARN);
    logManager->addHandler(logHandler);
    debugMode = targetState;
}

I’d love to hear any thoughts on how to improve this function; I should be all set to implement the rest now.

@armor: The reason I would like to switch logging levels on runtime is the follow: I use the serial connection for general debugging as well as occasional calibration. While calibrating, I want to send a serial command to temporarily reduce serial logging as it limits the communication speed. Once the calibration routine is done, I send the serial command to switch back to more detailed logging.

I suspect I may not be the only one with this idea, so including an example in the documentation and/or including a StreamLogHanlder.setLevel() function may be worthwhile.

Thanks again!

My only concern here is potential memory leak.

auto handler = new StreamLogHandler(Serial, LOG_LEVEL_TRACE);

Who is going to delete this new object?