This is well-timed.. I just started playing with this code on the flight
over here.
There are a couple pieces to what I've done so far:
- clearly segmented logging code into a new set of classes in src/log,
without dependencies on everything else
- set up config infrastructure to control 'log' and 'gather' levels for
different subsystems, where gather controls what messages are
generated, and log controls which of those reach disk (in non-crash
situation)
- made a relatively naive implementation that works (messages on heap,
separate thread to write out, dump recent history on crash).
- a lot of the weird interaction/bootstrapping stuff with contexts and
config now go away entirely if we just rely on cerr for errors during
config parsing, etc. (like that simple spinlock Greg was complaining
about).
> MY RECOMMENDATIONS [biased, as always ;-]
>
> - bundle the MessagePack library
I'm worried about requiring tools to read logs. And I think most of the
current overhead is the sync writes (which are easily addressed). But
string serialization is also a significant chunk, I think, so this may be
worth it... need to do some real tests.
> - in thread that calls log: serialize as MessagePack onto stack,
> allocate needed bytes from ringbuffer, copy event to ringbuffer
> - write to disk is now very simple, could even be done in a different
> process (mmap header+ringbuffer)
My naive implementation puts entries on heap and links them into a list:
can't easily extract from a core, but otherwise equivalent to a ring of
pointers. My limited tests showed std::string assignment had a huge
overhead, though, so I suspect writing a stringbuf implementation that
writes into cheaply preallocated buffers (maybe allocated off a large
preallocated ring buffer), optimized for common case (40-80 byte message).
But I need to read more of the Disruptor stuff to see what exactly they're
doing and why.
In any case, the new structure makes it easier to test implementations
given things are better contained.
> - let disk files be named after timestamp they were started at, start
> new ones based on time & size (no .0 -> .1 -> .2 renaming needed)
> - make it really simple to process+delete chunks of log, feeding them
> into Brisk or Graylog, then deleting from the node (perhaps after a
> delay, so last 24h is locally browseable)
> (and don't remove things that haven't been processed)
Currently that's done with rename, sighup, wait for new log to
appear, then process+delete. Are there problems there that make it worth
taking a non-standard approach to the log file naming?
Anyway, pushing what I have now to wip-log. The exposed interface is just
the macro in common/dout.h now. Alternative approaches will probably
change log/Entry.h and probably the allocation steps, but otherwise be
pretty simple to swap in/out.
The main piece that is sitll missing is an interface for logging
structured content. I suspect the way to do that is by putting stuff in
the ostream stream (ala std::setiosflags(foo) and their ilk) so that you
can easily stick key/value pairs in th code (... << log::kv("foo", "bar")
<< ... or something)? Hopefully that can reduce to something efficient,
at least, so we don't have to replace the current dout logging sites with
something completely different.
sage
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html