File Logging

Started by
3 comments, last by rip-off 13 years, 6 months ago
I wrote a general purpose logging class and looking for feedback on it.
free to use, redistribute, modify Et cetera

Header File
#ifndef LOG_H#define LOG_H#include <string>#include <fstream>#include <ctime>enum LogLevel {Fatal = 0, Error, Warning, Information, Debug};class LOG {public:	LOG(void);	void disable();	void enable();	void setloglevel(LogLevel Severity);	void setmaxloglevel(LogLevel Severity);	void out(char * Message);	void out(char * Message, LogLevel Severity);	void out(std::string Message);	void out(std::string Message, LogLevel Severity);private:	LogLevel CurrentLogLevel;	char * filename;	bool isEnabled;	LogLevel MaxLogLevel;};#endif /* LOG_H */


Source Code
#include "Log.h"LOG::LOG(void) {	CurrentLogLevel = Debug;	MaxLogLevel = Debug;	filename = "Log.txt";	isEnabled = true;}void LOG::disable() {	isEnabled = false;}void LOG::enable() {	isEnabled = true;}void LOG::setloglevel(LogLevel Severity){	CurrentLogLevel = Severity;}void LOG::setmaxloglevel(LogLevel Severity) {	MaxLogLevel = Severity;}/*Summary: Writes "Message" to a file using the DefaultLogLevel//*/void LOG::out(char * Message) {	if( (isEnabled) && (CurrentLogLevel >= MaxLogLevel) ) {		std::fstream File;		size_t writebufferlength;		File.open(filename, std::ios::out | std::ios::app);		if ( File.is_open() ) {			switch(CurrentLogLevel)			{			case Debug:				{				File.write("Debug\n",6);				break;				}			case Information:				{				File.write("Information\n",12);				break;				}			case Warning:				{				File.write("Warning!\n",9);				break;				}			case Error:				{				File.write("!!ERROR!!\n",10);				break;				}			case Fatal:				{				File.write("!!!FATAL ERROR!!!\n",27);				File.write("This is the Line You Are Looking for LOL!\n", 42);				break;				}			}			time_t ltime;			struct tm *Tm;		    ltime=time(NULL);		    Tm=localtime(&ltime);			char * timestamp = asctime(Tm);			writebufferlength = strlen(timestamp);			File.write(timestamp, writebufferlength);			writebufferlength = strlen(Message);			File.write(Message, writebufferlength);			File.write("\n\n",2);		}		File.flush();		File.close();	}}/*Summary: Writes "Message" to a file using the specified LogLevel//*/void LOG::out(char * Message, LogLevel Severity) {	if( (isEnabled) && (Severity <= MaxLogLevel) ) {		std::fstream File;		size_t writebufferlength;		File.open(filename, std::ios::out | std::ios::app);		if ( File.is_open() ) {			switch(Severity)			{			case Debug:				{				File.write("Debug\n",6);				break;				}			case Information:				{				File.write("Information\n",12);				break;				}			case Warning:				{				File.write("Warning!\n",9);				break;				}			case Error:				{				File.write("!!ERROR!!\n",10);				break;				}			case Fatal:				{				File.write("!!!FATAL ERROR!!!\n",27);				File.write("This is the Line You Are Looking for LOL!\n", 42);				break;				}			}			time_t ltime;			struct tm *Tm;		    ltime=time(NULL);		    Tm=localtime(&ltime);			char * timestamp = asctime(Tm);			writebufferlength = strlen(timestamp);			File.write(timestamp, writebufferlength);			writebufferlength = strlen(Message);			File.write(Message, writebufferlength);			File.write("\n\n",2);		}		File.flush();		File.close();	}}void LOG::out(std::string Message) {	char *sz;	sz = new char[Message.length() + 1];	strcpy(sz, Message.c_str());	// now work with sz, which is a copy of s	out(sz);	// clean up	delete [] sz;}void LOG::out(std::string Message, LogLevel Severity) {	char *sz;	sz = new char[Message.length() + 1];	strcpy(sz, Message.c_str());	// now work with sz, which is a copy of s	out(sz, Severity);	// clean up	delete [] sz;}
Advertisement
it would be a good idea to include categories, so you can turn on and off logging for parts in the code. (usually, you dont want to log mouse position, but sometimes it can be handy to turn that logging on)

edit:
you propably want to be able to log to stdout as well as to files.

its not thread safe, but maybe that is by design because you dont need it.

personally i would get rid of the "funny" messages. Its easy enough to search a log for "fatal error".

Also, consider that there are many log alternatives out there already that are well tested with great functionallity
www.ageofconan.com
Your std::string interfaces are overcomplicated, you should be able to use std::string::c_str(). You should probably allow the client to log a const c string. You could implement "void out(char * Message)" in terms of "void out(char * Message, LogLevel Severity)" by passing the CurrentLogLevel to the latter.

You should pass std::string instances by const reference to avoid unnecessary copies.
Quote:Original post by _Kami_
it would be a good idea to include categories, so you can turn on and off logging for parts in the code. (usually, you don't want to log mouse position, but sometimes it can be handy to turn that logging on)

edit:
you probably want to be able to log to stdout as well as to files.

its not thread safe, but maybe that is by design because you don't need it.

personally i would get rid of the "funny" messages. Its easy enough to search a log for "fatal error".

Also, consider that there are many log alternatives out there already that are well tested with great functionality


in regards to "funny messages" in my defense i was really stoned when i added that in.
Also if you use operator << rather than std::ofstream::write, you can avoid explicitly including the length of the various string literals (which is a very brittle approach).

If for some reason you had to do that, you should defined the string literal in advance and use the strlen() (or if you know what you are doing, the sizeof() operator) to help reduce the maintenance burden.

This topic is closed to new replies.

Advertisement