Unbuffered output with Logger (newbie question)

I’m trying to use Ruby’s built-in Logger facility, and I’m not able to
make it output log messages in real-time. Instead, log messages are
only outputted when I call Logger#close.

The Logger is created with a line like this:

log = Logger.new(File.open(‘test.log’, File::WRONLY | File::APPEND
| File::CREAT))

Then I log things using lines like:

log.info(‘hello’)

tail -f test.log shows nothing.

It’s only when I call “l.close” that all the log messages get written
out.

My suspicion is I’m not instantiating File correctly. Perhaps there
is an option for unbuffered output?

Any help appreciated.

Eric

Eric LIn wrote:

My suspicion is I’m not instantiating File correctly. Perhaps there
is an option for unbuffered output?

File is a subclass of IO, and IO has a flush method, which File
inherits. So you can do file.flush after each write to bypass Ruby’s
buffering.

Pickaxe p. 509 says:

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

So you could try flushing the log file after each log.info call. I
suspect this means subclassing Logger or modifying something within
Logger; maybe someone more experienced could suggest how to do this.

You’re still at the mercy of the OS’s buffering, which is additional to
Ruby’s.

On 31.05.2008 13:21, Dave B. wrote:

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

So you could try flushing the log file after each log.info call. I
suspect this means subclassing Logger or modifying something within
Logger; maybe someone more experienced could suggest how to do this.

There is a much better option: create the File with File::SYNC. You
should check on your platform if io.sync returns true afterwards. If
not, you should try io.sync=true. That way all writes go directly to
the file.

You’re still at the mercy of the OS’s buffering, which is additional to
Ruby’s.

But this does not matter that much because if you read the log file and
the block was not yet written to disk you see the contents nevertheless.
OS buffering is only an issue if the OS crashes which is unlikely.

Kind regards

robert

There is a much better option: create the File with File::SYNC. You
should check on your platform if io.sync returns true afterwards. If
not, you should try io.sync=true. That way all writes go directly to
the file.
robert

Hi Robert,

It appears File::SYNC doesn’t exist (at least not in my copy of
Ruby). However, setting IO#sync to true explicitly does work.

Thanks,
Eric