Re: adding timestamps to std::cerr messages?
Denise Kleingeist wrote:
So given this code:
std::cerr << "User error: " << iError << ". Quitting." << std::endl;
Id like the output to be
"timestamp: 87287234. User error: 6. Quitting."
or possibly
"User error: 6. Quitting. timestamp: 87287234."
How is this best done?
By creating a filtering stream buffers which use std::cout's
and std::cerr's original stream buffers for the actual writing
and replace those in their respective objects. You would
overwrite the overflow() method to detect a newline and upon
reception of the next character injects the time stamp. This
way, you would obviously take the time when the first
character is written rather than when a lines completed. On
the other hand, you don't rely on users of your class to
explicitly flush the stream.
In this particular case, the exact code he needs is available at
my site (http://kanze.james.neuf.fr/code-en.html); this is one
of my examples for a filtering streambuf in output. (The actual
example is the class TimeStampInserter, in the examples
FilteringOutputStream component of the IO subsystem; this class
could probably be easily modified to be used by
boost::filtering_streambuf (probably by just changing the name
of the function to put).
Since the above approach basically means that your stream
buffer becomes unbuffered, it may be relatively slow. If you
can rely on users of your stream facilities to flush the
buffer at appropriate places, e.g. by always using std::endl,
you can create a buffering stream buffer and hook the timing
facilities into the sync() method instead of into overflow():
Into both, in one way or another, since both can cause data to
be output from the buffer. (In practice, I generally have
overflow() call sync() if the streambuf is buffered, and put all
of the buffer handling code there.) Given the overhead of
having to actually look at each character anyway, I'm not sure
that buffering will buy him that much, however. (It depends on
the system, of course. On some systems, virtual function calls
are significantly expensive, and avoiding them can make a
difference.)
this function is called whenever the stream is flushed, e.g.
when the user uses std::endl or std::flush. Note, that even if
you choose the unbuffered version you most likely want to tap
into sync() anyway to flush the underlying stream buffer.
My templates (and I suppose those of Boost as well) do this
automatically.
I could try and create a wrapper object with an ostream
interface and just redirected every call to the std::cerr
object.
Peril lays this way: don't go there! Go the way foreseen for
extending IOStreams instead; create a stream buffer. It is the
more robust solution which has, among others, the obvious
advantage that you neither have to tinker with the stream
objects nor their types.
I need a way to determine the beginning or the end of a message.
If you really need to determine the beginning of the message,
use an unbuffered stream buffer and check for newlines in
overflow(). Its quite simple and I'm almost certain there has
been code posted for this by James Kanze and/or Dieter Kuehl.
If by "message" he means "line". For logging and such, I
usually use a short lived wrapper class, rather than ostream; a
"message" corresponds to the life of this class. The user can
thus write something like:
log() << "something or other:\nmore junk" << andAVariable ;
And get:
1. a timestamp (or other information) on the first line,
2. all following lines indented,
3. an automatic flush (and a new line, if he doesn't provide
one) at the end, and
4. the ouput of the entire message protected by a lock.
Unlike the filtering streambuf's, the code at my site for
supporting this (OutputStreamWrapper) is very primitive, only
represents a very early version, and would probably need some
work to make it work in an actual application. (In practice,
the OutputStreamWrapper works with a custom filtering streambuf;
it manages the lock, and informs the streambuf when it is
created and destroyed, and the streambuf does the rest.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientie objet/
Beratung in objektorientierter Datenverarbeitung
9 place Simard, 78210 St.-Cyr-l'Icole, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]