rubylogginglog4r

How to make log4r output messages syncronous?


I wonder why do I have raised exception between the logger debug output?

  DEBUG: asdjoasjd
  DEBUG: asdjoasjd 
  DEBUG: asdjoasjd
  **RuntimeError: something**
  DEBUG: continued debug message
  DEBUG: continued debug message
  DEBUG: continued debug message

While this debug message were composed before the exception?

$stdout.sync = true not helped.

i'm using log4r


Solution

  • From the IO#sync documentation:

    When sync mode is true, all output is immediately flushed to the underlying operating system and is not buffered internally.

    This means that Ruby won't buffer the data internally. Unfortunately this doesn't imply anything about any OS buffering and the OS might buffer the data as well.

    Also note that Log4r uses IO#flush to flush data which guarantees that the data will be flushed to the underlying OS but nothing more as well.

    Flushes any buffered data within ios to the underlying operating system (note that this is Ruby internal buffering only; the OS may buffer the data as well).

    What you need is IO#fsync which immediatelly writes (flushes) all buffered data.

    Immediately writes all buffered data in ios to disk. Note that fsync differs from using IO#sync=. The latter ensures that data is flushed from Ruby’s buffers, but does not guarantee that the underlying operating system actually writes it to disk.

    You could subclass Log4r::StdoutOutputter and provide your own #write implementation.

    Example:

    module Log4r
      class SyncedStdoutOutputter < StdoutOutputter
        def write(data)
          super(data)
          @out.fsync
        rescue NotImplementedError
          # fsync not supported by this OS
        end
      end
    end
    

    Buffering is good and highly recommended for performance reasons, especially in production systems. Otherwise you run the risk of consuming unnecessary resources, such as putting unnecessary strain on your disks.

    On a personal note, I think Log4r is outdated and a bit inactive. I try to stick with either the native Logger or at least ActiveSupport::Logger (which basically provides a formatter). Have a look at more modern alternatives such as logging. Most of the loggers are interchangeable.