Code review / suggestions - Log / Instrumentation class

M

ma740988

Faced with the need to instrument/log data I've decided to create an
instrumentation/log class. My initial thoughts (baby steps) on this
instrumentation/log class is as follows:
1. Time Stamping capability
2. A member function that'll take std::eek:stream as an argument and
print all accumulated logs.

# include <iostream>
# include <ctime>
# include <iomanip>
# include <vector>
# include <algorithm>
# include <functional>
# include <iterator>
# include <sstream>

using namespace std; // revisit this

struct PlainPrintPolicy
{
static string print(const string& str) { return str; }
};

struct TimestampPrintPolicy
{
static string print(const string& str);
};

string TimestampPrintPolicy::print(const string& str)
{
ostringstream ostr;
time_t now;
time(&now);
tm *current = localtime(&now);
ostr.fill('0');
ostr << "["
<< current->tm_year+1900 << "-"
<< setw(2) << current->tm_mon+1 << "-"
<< current->tm_mday << " "
<< setw(2) << current->tm_hour << "."
<< setw(2) << current->tm_min << "."
<< setw(2) << current->tm_sec << "]: "
<< str;
return ostr.str();
}

template <typename PrintPolicy>
class Logger
{
public:
void addEntry(const string& str)
{
store_.push_back(PrintPolicy::print(str));
}

void dumpLog(ostream& os)
{
copy(store_.begin(), store_.end(),
ostream_iterator<string>(os, "\n"));
}

private:
vector<string> store_;
};

int main()
{
Logger<PlainPrintPolicy> logger;
logger.addEntry("System booted");
logger.addEntry("FaultFaultFault");
logger.addEntry("Shutdown");
logger.dumpLog(cout);

Logger<TimestampPrintPolicy> logger2;
logger2.addEntry("System booted");
logger2.addEntry("FaultFaultFault");
logger2.addEntry("Shutdown");
logger2.dumpLog(cout);

return 0;
}

After investigating I thought - for completeness - I could modify the
existing class to:

3. Add - I'll call it - object registration. The intent here is to
have visibility into member data IRRESPECTIVE of 'class'. One thought
involved a static array of class pointer as a member in any private
class. The constructor registers any new object and the destructor
'de-registers' objects. A monitor utility would have access to the
array and provide information on request.
4. File stream, cout and stringstream log capabilities.

Additional capabilities include:
(1) Log file maximum size, or rollover to new log file at certain
size.
(2) Compress repeated messages.
(3) Prevent runaway repeated forever error messages.

I'm interested in advise primarily with regard to item 3. Item 3 seem
to approach 'policy designs' and I'm not there yet in text I'm reading
(modern C++ design). In addition - based on the requirements - I'm
curious to know if I'm on the right track.
Finally, I'm of the impression that a streambuf-based (deriving from
streambuf) solution would be appealing but 'playing' with streams is -
for now - too advanced for me and falls in the two hard pile.

Note: I suspect this is request for a review/suggestions might be
more of a design question and might be better suited for some other
group but if I've violated any rule, forgive me.

Thanks in advance.
 
R

Ron Natalie

ma740988 said:
using namespace std; // revisit this

Absolutely. Using declarations don't belong in headers you expect others to have
to use.

But to answer your questions, I suggest you use something derived from a regular
ostream. This will make things far less painful.

For timestamping, you can either define your own streambuf that starts each line with a
time stamp or something similar, or you can add an explicit timestamping manipulator
which would let you do something like:
log << timestamp << "My log report\n";

The advantage of using an ostream is you can use all it's formatting features, plus to
get classes to be able to print out info on themselves the stream, all they need to do
have an operator<< or other method that writes to a stream.

You can fix the streambuffer to roll the log file, collapse errors, etc...
 
M

ma740988

Ron Natalie said:
Absolutely. Using declarations don't belong in headers you expect others to have
to use.

But to answer your questions, I suggest you use something derived from a regular
ostream. This will make things far less painful.

For timestamping, you can either define your own streambuf that starts each line with a
time stamp or something similar, or you can add an explicit timestamping manipulator
which would let you do something like:
log << timestamp << "My log report\n";

The mere mention of the word streambuf at times makes my head spin, so
pardon my ignorance. When you say 'define your own streambuf'. Are
you saying derive from teh 'streambuf' class? Could you provide an
example.
The advantage of using an ostream is you can use all it's formatting features, plus to
get classes to be able to print out info on themselves the stream, all they need to do
have an operator<< or other method that writes to a stream.

With regard to the advantage you allueded to. That's an excellent
point. My initial apprehension - which led me down a 'revised' path -
to such approach is the need to add an operator << for EVERY class.
So I thought about a log class with object registeration (have objects
register with the log class)
You can fix the streambuffer to roll the log file, collapse errors, etc...
Pardon my ignorance here again but for instance?
 
M

Mike Wahler

ma740988 said:
"Ron Natalie" <[email protected]> wrote in message

The mere mention of the word streambuf at times makes my head spin, so
pardon my ignorance. When you say 'define your own streambuf'. Are
you saying derive from teh 'streambuf' class? Could you provide an
example.


With regard to the advantage you allueded to. That's an excellent
point. My initial apprehension - which led me down a 'revised' path -
to such approach is the need to add an operator << for EVERY class.
So I thought about a log class with object registeration (have objects
register with the log class)
etc...
Pardon my ignorance here again but for instance?

For more detailed knowledge and good insight into the C++
IOStreams library:

http://www.langer.camelot.de/iostreams.html

IMO a *very* good book.

-Mike
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top