Hi,

I've recently made use of guile-lib's logging library, and was surprised
that by default the rotating-log logger, which logs to a file, would
write to a file using block buffering, which would means logs would only
be seen added to the file every now and then rather than in real time.

That breaks a common expectation of log files, which can typically be
tail'd -f to see a program output as it runs.

I've come up with this workaround:

--8<---------------cut here---------------start------------->8---
    ;; Ensure log messages are written in real time, not block
    ;; buffered.
    (setvbuf (slot-ref rotating 'port) 'line)))
--8<---------------cut here---------------end--------------->8---

But it was not easily discovered and still doesn't feel exactly 'real
time'.  The Python logging library, which is the inspiration for this
one, calls 'flush' after each log message is written in the base class
from which all handlers inherit (see Lib/logging/__init__.py):

--8<---------------cut here---------------start------------->8---
class StreamHandler(Handler):
    """
    A handler class which writes logging records, appropriately formatted,
    to a stream. Note that this class does not close the stream, as
    sys.stdout or sys.stderr may be used.
    """

    terminator = '\n'

    def __init__(self, stream=None):

[...]

    def flush(self):
        """
        Flushes the stream.
        """
        self.acquire()
        try:
            if self.stream and hasattr(self.stream, "flush"):
                self.stream.flush()
        finally:
            self.release()

    def emit(self, record):
        """
        Emit a record.

        If a formatter is specified, it is used to format the record.
        The record is then written to the stream with a trailing newline.  If
        exception information is present, it is formatted using
        traceback.print_exception and appended to the stream.  If the stream
        has an 'encoding' attribute, it is used to determine how to do the
        output to the stream.
        """
        try:
            msg = self.format(record)
            stream = self.stream
            # issue 35046: merged two stream.writes into one.
            stream.write(msg + self.terminator)
            self.flush()
        except RecursionError:  # See issue 36272
            raise
        except Exception:
            self.handleError(record)

[...]
--8<---------------cut here---------------end--------------->8---

This would be easy to do in our logger implementation (we'd call
'flush-log' at the end of 'emit-log'), if we agree it's a good idea.

Would anyone be opposed to that?  If not, I'll happily send a patch.

-- 
Thanks,
Maxim

Reply via email to