pythonloggingrabbitmqpika

Python custom logging handler tries to log itself during emit()


I am trying to implement a custom logging handler, which should post to a rabbitmq server1.

A basic setup of this would look something like this:

class RabbitMQHandler(logging.Handler):

    def __init__(self, host: str, port: int, queue: str,  level: int = 0) -> None:
        self.host = host
        self.port = port
        self.queue = queue

        super().__init__(level)


    def emit(self, record: logging.LogRecord) -> None:
        try:
            msg = self.format(record)
            with pika.BlockingConnection(pika.ConnectionParameters(
                host=self.host,
                port=self.port
            )) as connection:
                channel = connection.channel()
                channel.queue_declare(queue=self.queue)
                channel.basic_publish(
                    exchange='',
                    routing_key=self.queue,
                    body=msg
                )
            self.flush()
        except (KeyboardInterrupt, SystemExit):
            raise
        except Exception:
            self.handleError(record)

The issue here seems to be, that the pika module tries to log itself as soon as a connection is established, thus calling the emit() function recursively forever.

My question is whether should simply disable logging (how?) during the emit function, or if this is the wrong approach altogether?

EDIT: Putting the above handler into a separate logger would be one way to go, however I am wondering about a general solution to this question.


1 I know there are pip packages for this, but for this project I have to avoid dependencies as much as possible.


Solution

  • This is because you added your custom logging handler to the root logger, and logging messages propagate to ancestor loggers by default, so messages logged by pika get propagated to the root logger and invokes your custom logging handler recursively.

    The best practice in this case would be to add the custom logging handler to a non-root logger instance, and use that logger instead for the logging needs of your application.