Creating Thread Safe Logger
Hi everyone,
Again, I'm just trying stuff out to try and learn a bit more but here goes...
I created a small Logger util - I included the pthread library and added a mutex lock in each of the "write*" functions, tested it by running a few instances of a test program, each printing "hello world" 100,000 times to the same file the it seems to work - no lines were cut off or anything, and each instance seemed to wait it's turn... thing is, is it really this easy to make a thread safe logger?
How I plan on using it was say in the main () of my program, create a logger like
Log* myLogger = new Log ();
Then for each object/whatnot that needs logging, pass that pointer into it so it's all logging to the same place and so on.
Also, I'm sure someone has asked this a thousand times so sorry in advance! but how would you go about making the logger work like the stringstream class i.e.
myLogger->writeInfo () << "Log messages " << count << " Times";
Any help or comments would be much appreciated :)
SCass2010
Junior Poster in Training
78 posts since Mar 2010
Reputation Points: 10
Solved Threads: 0
Log.h
#ifndef LOG_H
#define LOG_H
#include <fstream>
#include <stdarg.h>
#include <iostream>
#include <pthread.h>
#define INFO "Info :"
#define WARNING "Warn :"
#define ERROR "Error:"
#define DEBUG "Debug:"
using namespace std;
class Log
{
public:
Log (char* logFilename, bool debugOn = false);
virtual ~Log ();
void writeInfo (const char* logline, ...);
void writeWarn (const char* logline, ...);
void writeError (const char* logline, ...);
void writeDebug (const char* logline, ...);
private:
pthread_mutex_t mLock;
char* getTimeStamp ();
ofstream mStream;
bool mDebugOn;
};
#endif
Log.cpp
#include "Log.h"
#include <stdarg.h>
Log::Log (char* logFilename, bool debugOn)
: mDebugOn (debugOn)
{
pthread_mutex_init (&mLock, NULL);
mStream.open (logFilename, fstream::app);
}
Log::~Log ()
{
mStream.close ();
pthread_mutex_destroy (&mLock);
}
void Log::writeInfo (const char* logline, ...)
{
pthread_mutex_lock (&mLock);
va_list argList;
char buffer [1024];
va_start (argList,
logline);
vsnprintf (buffer,
1024,
logline,
argList);
va_end (argList);
mStream << getTimeStamp () << " Info : " << buffer << endl;
cout << getTimeStamp () << " Info : " << buffer << endl;
pthread_mutex_unlock (&mLock);
}
void Log::writeError (const char* logline, ...)
{
pthread_mutex_lock (&mLock);
va_list argList;
char buffer [1024];
va_start (argList,
logline);
vsnprintf (buffer,
1024,
logline,
argList);
va_end (argList);
mStream << getTimeStamp() << " Error : " << buffer << endl;
cout << getTimeStamp() << " Error : " << buffer << endl;
pthread_mutex_unlock (&mLock);
}
char* Log::getTimeStamp ()
{
char* tString = new char [80];
time_t t = time (0);
struct tm* today = localtime (&t);
strftime (tString,
80,
"%d/%m/%Y %H:%M:%S",
today);
return tString;
}
SCass2010
Junior Poster in Training
78 posts since Mar 2010
Reputation Points: 10
Solved Threads: 0
Hi,
Thanks for the reply - I guess I was expecting it too be alot more complicated! I see what you mean about the getTimeStamp, I thought since it was called at the same as the write* function it would need to be included in it, but I see now I was probably making pointless calls to it when I could get it in one go lol :P
SCass2010
Junior Poster in Training
78 posts since Mar 2010
Reputation Points: 10
Solved Threads: 0