patterncppMinor
Log file mechanism
Viewed 0 times
filemechanismlog
Problem
I want to create a generic log file which I can easily reuse in multiple files. Also, I want to be able to use the versatile
Definition
Implementation
Usage:
In reality, I have put the line
What if I want to create multiple log files for different purposes? Is there a way I can access
std::cout so I can easily write formatted text (as oppose to create my own write function which may write only strings and which can probably never be that versatile).Definition
#include
class logstream :
public std::ofstream
{
public:
logstream();
~logstream();
protected:
std::streambuf *psbuf, *backup;
std::ofstream filestr;
};Implementation
logstream::logstream()
{
filestr.open("test_streaming.txt", std::ofstream::app);
backup = std::clog.rdbuf(); // back up cout's streambuf
psbuf = filestr.rdbuf(); // get file's streambuf
std::clog.rdbuf(psbuf); // assign streambuf to cout
}
logstream::~logstream()
{
std::clog.rdbuf(backup); // restore cout's original streambuf
filestr.close();
}Usage:
void CExportDlg::OnBnClickedButtonLog()
{
logstream log; // redirects clog and restores it when it goes out of scope
std::clog << "hello this goes into log file" << std::endl;
std::clog << "And I can readily write intetgers like " << 5 << "this one" << std::endl;
}In reality, I have put the line
logstream log in the main application class so now I can use only std:clog() anywhere in the application and output goes to a log file. But can this be improved?What if I want to create multiple log files for different purposes? Is there a way I can access
clog() (or cout()) by the object so it goes into that object only, like log.clog()?Solution
I like how you use the existing stream API instead of rolling your own. Also I think that redirecting
However there are some problems.
Usage
The inheritance of from
but this is not the intended usage of the class. I also see no reason why this class must inherit from
Scoped design
While a scoped design is good in some/many cases I don't think this is one of them. Typically logging destinations is not something you configure per scope but rather once for the application. This is merely a personal opinion I'm sure it has its uses.
Usability
I'm missing some features. One particular that comes to mind is to write to file and console at the same time (as the example by @LokiAstari here).
Consider using an already existing library
Like for example log4cpp which provides log streams which you can redirect
std::clog is a good approach as this could then easily be retro fitted into an existing application that properly uses std::clog with ease. However there are some problems.
Usage
The inheritance of from
std::ofstream implies a usage such as this:logstream log("logfile.txt");
log<<"foobar\n";but this is not the intended usage of the class. I also see no reason why this class must inherit from
std::ofstream. I would remove this inheritance because in my opinion it breaks the Liskov Substitution Principle.Scoped design
While a scoped design is good in some/many cases I don't think this is one of them. Typically logging destinations is not something you configure per scope but rather once for the application. This is merely a personal opinion I'm sure it has its uses.
Usability
I'm missing some features. One particular that comes to mind is to write to file and console at the same time (as the example by @LokiAstari here).
Consider using an already existing library
Like for example log4cpp which provides log streams which you can redirect
std::clog to and use separately. It is configurable and has all the bells and whistles you usually want from a log system.Code Snippets
logstream log("logfile.txt");
log<<"foobar\n";Context
StackExchange Code Review Q#150433, answer score: 3
Revisions (0)
No revisions yet.