diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 6cfd93f61bc..04a1e5bbcd7 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -944,6 +944,7 @@ Loggers have the following attributes and methods. Note that Loggers are never instantiated directly, but always through the module-level function ``logging.getLogger(name)``. +.. class:: Logger .. attribute:: Logger.propagate @@ -2661,7 +2662,20 @@ supports sending logging messages to a queue, such as those implemented in the .. method:: emit(record) - Sends the record to the handler's queue. + Enqueues the result of preparing the LogRecord. + + .. method:: prepare(record) + + Prepares a record for queuing. The object returned by this + method is enqueued. + + The base implementation formats the record to merge the message + and arguments, and removes unpickleable items from the record + in-place. + + You might want to override this method if you want to convert + the record to a dict or JSON string, or send a modified copy + of the record while leaving the original intact. .. method:: enqueue(record) diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index ce0673d9a17..3d7a6786a9f 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -1176,24 +1176,39 @@ class QueueHandler(logging.Handler): """ self.queue.put_nowait(record) + def prepare(self, record): + """ + Prepares a record for queuing. The object returned by this + method is enqueued. + + The base implementation formats the record to merge the message + and arguments, and removes unpickleable items from the record + in-place. + + You might want to override this method if you want to convert + the record to a dict or JSON string, or send a modified copy + of the record while leaving the original intact. + """ + # The format operation gets traceback text into record.exc_text + # (if there's exception data), and also puts the message into + # record.message. We can then use this to replace the original + # msg + args, as these might be unpickleable. We also zap the + # exc_info attribute, as it's no longer needed and, if not None, + # will typically not be pickleable. + self.format(record) + record.msg = record.message + record.args = None + record.exc_info = None + return record + def emit(self, record): """ Emit a record. - Writes the LogRecord to the queue, preparing it for pickling first. + Writes the LogRecord to the queue, preparing it first. """ try: - # The format operation gets traceback text into record.exc_text - # (if there's exception data), and also puts the message into - # record.message. We can then use this to replace the original - # msg + args, as these might be unpickleable. We also zap the - # exc_info attribute, as it's no longer needed and, if not None, - # will typically not be pickleable. - self.format(record) - record.msg = record.message - record.args = None - record.exc_info = None - self.enqueue(record) + self.enqueue(self.prepare(record)) except (KeyboardInterrupt, SystemExit): raise except: