2

I have to extend the ofstream class to write a logging stream service.

The goal is to intercept each line, adding at the head of each one a customized text (date/time, severity, and so on).

Now, it's clear that I'm not a C++ guru, so I read a lot of documentation about this task, e.g.

http://www.angelikalanger.com/Articles/Topics.html#CPP http://asmodehn.wordpress.com/2010/06/20/busy-c-coding-and-testing
http://gabisoft.free.fr/articles-en.html

The above articles suggest to write a custom stream buffer, but during porting of this concept on file streams I encountered a lot of difficulties.

Is there a simpler method to achieve this goal?

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Antonio Petricca
  • 8,891
  • 5
  • 36
  • 74
  • 1
    I would suggest simply wrapping around std::ofstream. That means you would make a class with a std::ofstream member. – Aleph Dec 20 '12 at 17:10
  • In a previous reading of this topic I've found an answer now removed : http://stackoverflow.com/questions/4366904/custom-stream-to-method-in-c/4372966#4372966 !!! – Antonio Petricca Dec 28 '12 at 08:51

1 Answers1

1

You don't need to write a custom stream buffer; the simplest and most straightforward way is to make a class you can send output to by giving it a templatized single argument operator<<():

template <typename T>
std::ostream& operator<<(const T& data_)
{
    m_outstream << m_severity << "\t" << getTimeStamp() << "\t" << data_;

    return m_outstream;
}

Where m_outstream is some type of std::ostream (std::ofstream, etc). m_severity and getTimeStamp() are examples of what you can insert (and you can create a bog standard two argument operator<<() to format and output the severity type to an ostream).

This then allows you to do things like:

myLogger << "failingFunction(" << argument <<
            "): Could not do something." << std::endl;

and you will get output on m_outstream that looks like:

WARNING 2012-01-03 19:32 failingFunction("argument value"): Could not do something.

Beyond this, you will want a way to set the severity, which can be as simple as a method called on the logger class you added the templatized operator<<() to. If you want to get really fancy, you can write your own manipulator that acts much like setw() would on a std::ostream. See http://www.math.hkbu.edu.hk/parallel/pgi/doc/pgC++_lib/stdlibug/man_6665.htm for a primer on writing manipulators.

Nathan Paul Simons
  • 1,784
  • 1
  • 11
  • 9
  • Hi, I'm extending myy logger class using your template, but I get several errors like this when I link the application : `"error LNK2001: unresolved external symbol "public: class std::basic_ostream > & __thiscall Logger::operator<<(char const (&)[35])" (??$?6$$BY0CD@$$CBD@Logger@@QAEAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAY0CD@$$CBD@Z) ...\DependencyResource.obj"`Could you help me again? Thank you! – Antonio Petricca Jan 15 '13 at 13:41