Inheriting from std::ostream to override formatting.

Discussion in 'C++' started by AJG, Jun 29, 2008.

  1. AJG

    AJG Guest

    Hi there. I am using a library called SOCI that has a method to set a
    stream which it uses to log SQL queries. The signature is as follows:

    void setLogStream(std::eek:stream *s);

    This works great when used with something like
    setLogStream(&std::cerr). However, I would like to add more context to
    the query logged. Specifically, I'd like to add the thread ID. So,
    instead of the query logged looking like:

    select * from foo;

    it would look like:

    <thread-id>| select * from foo;

    I already have the function to get the thread id
    (boost::this_thread::get_id()), but I need to find a way to pass an
    object to setLogStream that will do the formatting for me. As far as I
    can tell, the only way to do this is inheriting from std::eek:stream and
    somehow overriding the default formatting. Except I'm not sure which
    of its methods are virtual and meant to be overridden. Any clues?

    Basically, I figure what I need might look something like:

    struct ThreadLogger : public std::eek:stream {
    // ...
    virtual void someOverridenFunction(const char *const buffer) {
    std::cerr << boost::this_thread::get_id() << "| " << buffer;
    }
    // ...
    };

    and then:

    ThreadLogger logger;
    setLogStream(&logger);

    Is what I'm looking to do possible? Should I look into IO manipulators
    instead? Any help greatly appreciated :).

    Thanks!
     
    AJG, Jun 29, 2008
    #1
    1. Advertising

  2. AJG

    James Kanze Guest

    On Jun 29, 4:37 am, AJG <> wrote:
    > Hi there. I am using a library called SOCI that has a method
    > to set a stream which it uses to log SQL queries. The
    > signature is as follows:


    > void setLogStream(std::eek:stream *s);


    > This works great when used with something like
    > setLogStream(&std::cerr). However, I would like to add more
    > context to the query logged. Specifically, I'd like to add the
    > thread ID. So, instead of the query logged looking like:


    > select * from foo;


    > it would look like:


    > <thread-id>| select * from foo;


    > I already have the function to get the thread id
    > (boost::this_thread::get_id()), but I need to find a way to
    > pass an object to setLogStream that will do the formatting for
    > me.


    You also need a way of ensuring correct locking on the output
    stream object.

    > As far as I can tell, the only way to do this is inheriting
    > from std::eek:stream and somehow overriding the default
    > formatting. Except I'm not sure which of its methods are
    > virtual and meant to be overridden.


    None of the functions (except the destructor) are virtual and
    are meant to be overridden. That's not how ostream works.

    > Any clues?


    You could use a filtering streambuf to insert the thread id at
    the start of each line, but that still leaves the issue of
    locking. The usual solution is to combine a filtering streambuf
    (to "decorate" the output, i.e. adding timestamp, thread id,
    line and filename...) and an output stream wrapper (to manage
    the lock, and more generally the notion of a "record", and to
    ensure that each record ends with a new line, is immediately
    flushed, and is atomic, e.g. when the output stream sends emails
    or writes to syslog).

    For more information on filtering streambufs, see
    http://kanze.james.neuf.fr/articles-en.html; an implementation
    is also available there, or you can use boost::iostream (if e.g.
    you're already using Boost). I'm not aware of any good article
    on output stream wrappers, but the concept is simple enough that
    it might not be necessary. Again, an implementation is
    available at my site, but if you don't feel like installing the
    entire library (and I've made no effort to date to make it
    fractionable), it's small enough and simple enough that you
    should be able to just copy the relevant code and manage it as
    your own.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 29, 2008
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. enzo

    inheriting ostream

    enzo, Jan 16, 2004, in forum: C++
    Replies:
    3
    Views:
    391
    Andrey Tarasevich
    Jan 17, 2004
  2. Johannes Barop
    Replies:
    1
    Views:
    437
    JH Trauntvein
    Dec 29, 2005
  3. Replies:
    2
    Views:
    1,908
  4. Pallav singh
    Replies:
    3
    Views:
    4,050
    Saeed Amrollahi
    Oct 21, 2009
  5. , India
    Replies:
    3
    Views:
    2,862
    James Kanze
    Nov 13, 2010
Loading...

Share This Page