Using C++ STL filebuf/ostream to create a time-stamped logging class

In a previous post, I have presented a class that would append a timestamp to each line of text before outputting it to stdout. This is an evolvedversion of that class which is abel to simultaneously write to stdout and to a text file.

First, the credits: the code is heavily based on this example by Nicolai M. Josuttis and on this post by Cay S. Horstmann.

You’ll find all the needed background information here:
http://www.angelikalanger.com/IOStreams/Excerpt/excerpt.htm (book excerpt)
http://www.cplusplus.com/reference/iostream/streambuf/
http://www.cplusplus.com/reference/iostream/ostream/

And here’s the code:

#include
#include
#include
#include
using namespace std;

// This is the streambuffer/filebuffer; its function is to store formatted data and send
// it to a character output when solicited (sync/overflow methods) . One does not
// instantiate it on its own in an application; it will be automatically used
// by an actual output stream (like the TimestampLoggerOstream class defined ahead)
class TimestampLoggerFilebuf : public filebuf
{
	string LineHeader() {
		time_t secondsSinceEpoch = time(NULL);
		tm* brokenTime = localtime(&secondsSinceEpoch);
		char buf[80];
		strftime(buf, sizeof(buf), "[%d/%m/%y,%T] ", brokenTime);
		return string(buf);
	}

public:
	TimestampLoggerFilebuf() { filebuf::open("log", ios::out); }
	void open(const char fname[]) {
		close();
		filebuf::open(fname ? fname : "log",  ios::out | ios::app | ios::trunc);
	}
    void close() { filebuf::close();}
    virtual int sync() {
    	// número de caracteres no buffer esperando para serem escritos
    	int out_waiting = pptr() - pbase();
    	// retira todos os caracteres do buffer e guarda localmente
    	char buf[200];	///< ToDo: seguro???
    	for (int i=0; i<=out_waiting; i++) {
    		buf[out_waiting - i] = *pptr();
    	    if (i < out_waiting) pbump(-1);
    	}
    	// coloca timestamp no buffer de saída
    	string header = LineHeader();
    	for (int i=0; i<20; i++)
    		sputc(header[i]);
    	// recoloca linha de texto original no buffer de saída
    	for (int i=0; i<< char(c);
//		return filebuf::overflow(c);
//	}
};

// This is the output stream; its function is to format data (using mainly the <<
// operator) and send it to a streambuf to be stored and written to the output.
class TimestampLoggerOstream : public ostream
{
public:
	TimestampLoggerOstream() : ostream(new TimestampLoggerFilebuf()), ios(0) {}
	~TimestampLoggerOstream() { delete rdbuf(); }
};

// Demo main() function, simply write a few lines to standard output. The endl
// manipulator indicates the end of a text line and requests a flush. This will
// trigger a call to TimestampLoggerFilebuf::sync() which will output the
// timestamp header followed by the line of text.
int main(int argc, char *argv[])
{
	cout << "Application started." << endl;

	TimestampLoggerOstream ls;

	ls << "abc";
	ls << "def" << endl;
	ls << "123" << endl;

	return 0;
}

This is it for this topic. If this blog helps you save a little time,please leave a comment and I’ll log it in for an estimate of time savedx time spent maintaining this blog.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: