Feature suggestion: log selection logic on contents change

Quite often I find myself needing to only log some piece of information selectively where the selection/throttle logic depends on what’s getting logged. Some example use cases for this:

  • You catch an exception superclass and you want to log the exception only once per exception class (e.g. one TimeOut and one RetryError from the python requests library, both RequestExceptions)
  • You’re doing multi-robot SLAM and have a single callback to process sensor data from multiple topics, want to throttle any logs depending on the robot it comes from. If you have a persistent error coming from one robot, you don’t want to be dropping logs about another robot that is experiencing the same error.
  • You want to be able to reset a ‘skip_first’ flag when the message has changed

AFAIK this is not possible today with the current logging machinery.

A simple toy example in rclpy to illustrate functionality:

import rclpy

def log_once(logger, msg):
    logger.info(msg, once=True)

def main():
    rclpy.init()
    node = rclpy.create_node('logging_demo')
    logger = node.get_logger()

    log_once(logger, 'foo')
    log_once(logger, 'foo')
    log_once(logger, 'bar')
    log_once(logger, 'bar')

    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

desired outcome:

INFO] [logging_demo]: foo
INFO] [logging_demo]: bar

actual outcome:

INFO] [logging_demo]: foo

‘bar’ doesn’t get printed.

The most straightforward solution in my mind would be to add a new optional argument to the logging methods that allows you to specify the behavior of the logging, whether it should ‘reset’ when the message has changed. The default behavior would be the same as the current behavior.