# Message Log class

This topic is 4852 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Okay, here's what I've got so far:
#ifndef _CLOG_H_
#define _CLOG_H_

#include <string>
#include <iostream>
#include <fstream>
using namespace std;
#include <time.h>

#define DEFAULT_STREAM_FILE "default_stream.txt"
#define TIME_BUFFER_SIZE 100

/**
* This is a singleton class that will allow objects to output debug and other messages
*/
class CLog
{
private:
static ofstream streams[10];	///< Output file stream

public:

/// Enumeration representing the different message (to different streams)
enum StreamType{
STREAM_DEBUG=0,	///< debug stream
STREAM_2,
STREAM_3,
STREAM_4,
STREAM_5,
STREAM_6,
STREAM_7,
STREAM_8,
STREAM_9,
STREAM_10,

NUM_OF_STREAMS	///< Implicit number of streams
};

/// Enumeration representing the different write modes
enum WriteMode{

WRITE=0,		///< truncates file and starts writing
APPEND,			///< append to existing file

NUM_OF_MODES	///< Implicit number of write modes
};

/**
* Function that opens the specified file for the specified stream in the specified
* write mode.
* \param file The file name of the file into which will be written the messages logged for this stream.
* \param type The stream you want to associate with this file.
* \param mode The write mode you wish to open this file in.
*/
static void openStream(string file = DEFAULT_STREAM_FILE, StreamType type = STREAM_DEBUG, WriteMode mode = WRITE )
{
// Check if it is a valid write mode
if( mode < WRITE || mode >= NUM_OF_MODES ){
cout << "CLog::openStream: Error: Invalid WriteMode: not opening file." << endl;
return;
}

if( type < STREAM_DEBUG || type >= NUM_OF_STREAMS ){
cout << "CLog::openStream: Error: Invalid StreamType: not opening file." << endl;
return;
}

// Open file in mode specified
if( mode == APPEND )
// Open file stream in append mode
streams[(int)type].open(file.c_str(), ios::app);
else if( mode == WRITE )
// Open file stream in write mode
streams[(int)type].open(file.c_str() );

}

/**
* Flush and close the selected file stream.
* \param type The stream to close.
*/
static void closeStream(StreamType type)
{
streams[(int)type].flush();
streams[(int)type].close();
}

/**
* Function that will write a message to the open specified stream.
* \param type A StreamType variable indicating which stream you want to write the message to.
* \param s A string object containing the message you want to log.
*/
static void write(StreamType type, string s)
{
// If file is open then write the string to file
if( streams[(int)type].is_open() ){
writeTime(streams[(int)type]);
streams[(int)type] << s;
}
else
// Else file is not open -> object has not been created
cout << "CLog::write: Warning: attempted writing to stream " << (int)type <<
" when stream is not open." << endl;
}

/**
* Function that will write the time and date in the form of
* day/month/year hour:minute:second into the stream passed.
* \param s A reference to the stream to write the date and time into.
*/
static void writeTime(ofstream& s)
{
// get time and print it to file before message
time_t t = time(NULL);
struct tm* now = localtime( &t );
char buf[TIME_BUFFER_SIZE];
strftime(buf, TIME_BUFFER_SIZE, "%d/%m/%y %I:%M:%S\t ", now);

s << buf;
}

};

/** Out of class scope initialization for the streams */
ofstream CLog::streams[10];

#endif


I just re-wrote it from some wierd singleton mash that seemed to make sense about half-way through last year, fairly close to the start of my C++ experience. I haven't tested it yet, because even for something this small, it would take some time, and well, I feel a little more like sleeping. But I wanted to ask some advice about this class. Nothing specific, anything you felt like giving that might be useful, but, since a question is usually asked, which do you think is better for a message logging class? An actual object? A singleton? Or just a bunch of related functions?

##### Share on other sites
I personally think a singleton is fine, but others may disagree.

Generally, you should check these things before using a singleton:

* Will every portion of the program use the class exactly the same way?

* Will every program using the class use it exactly the same way?

* Will every program never need more than one instance of the class?

* Can clients use the class without knowledge of what application they're in?

If you answer yes to all those, you pretty much OK to use a singleton.

EDIT: Whether you go with a singleton or not, one thing is sure: don't just make a bunch of global functions with 'Log_' prefixed to them. If you're going to do that, the least you can do is put them into a 'Log' namespace or something.

[Edited by - nilkn on July 4, 2005 10:55:12 AM]

##### Share on other sites
Personally, I would [and do] use an interface. That is have a pure virtual class which has virtual members for all the stuff you require a logger class to have. [for me it's merely write(const char *)] Then you can make various loggers to see what works best [or change what works best depending on the scenario] and just have your classes write to the base interface. Let inheritance do the rest.

##### Share on other sites
Instead of having many anonymous streams, I have found it very useful and easier just to give a couple pre-built names streams. This way you can control what the output is according to the type of message, etc.

It's not the most flexible, but I don't need it to be any more. I could change how it logs each type of message if I want (right now it logs all of them the same way).

Here it is if you want to take a look.

.h
/* --------------------------------------------------------------	File:			AXLogger.h	Description:	This file defines a class that logs messages.  Depending on the type of message,					it logs it to the appropriate output.					For now, it logs everything to both the console and the file.  I think it's important					to separate the types of messages, however, so later I can come back and change the type of					outputs for each type of message.					You specify the type of message by passing in MESSAGE_USER, MESSAGE_APP, or MESSAGE_SYSTEM					when you write the message.  A line with the type of message, calling function, and message					will appear in the appropriate output.  You are allowed printf style formatting.	Date:			June 29, 2005	Author:			James Long-------------------------------------------------------------- */#if !defined(AXLOGGER_INCLUDE)#define AXLOGGER_INCLUDE// The different log typesenum LogType {	LOG_TYPE_USER = 1,	LOG_TYPE_APPLICATION = 2,	LOG_TYPE_SYSTEM = 4,	LOG_TYPE_DEBUG = 8};// Define some macros to make logging much easier#define MESSAGE_USER LOG_TYPE_USER, __FUNCTION__#define MESSAGE_APP LOG_TYPE_APPLICATION, __FUNCTION__#define MESSAGE_SYS LOG_TYPE_SYSTEM, __FUNCTION__#define MESSAGE_DBG LOG_TYPE_DEBUG, __FUNCTION__class AXLogger : AXSingleton<AXLogger> {public:	AXLogger();	virtual ~AXLogger();	AXResult Initialize();	void Shutdown();	void Write(LogType target, const char* func, const char* msg, ...);private:	char _Temp_Buf[5012];	ofstream _FileLog;};#endif

.cpp
/* --------------------------------------------------------------	File:			AXLogger.cpp	Description:	Implementation for the AXLogger class.  See AXLogger.h for details.	Date:			June 29, 2005	Author:			James Long-------------------------------------------------------------- */#include "..\\AXCore.h"AXLogger::AXLogger() : AXSingleton<AXLogger>() {}AXLogger::~AXLogger() {}AXResult AXLogger::Initialize() {	// Open the log file	_FileLog.open("log.txt");	return AXSUCCESS;}void AXLogger::Shutdown() {	// Close the log file	_FileLog.close();}void AXLogger::Write(LogType target, const char *FunctionName, const char *Msg, ...) {	va_list args;	va_start(args, Msg);	vsprintf(_Temp_Buf, Msg, args);	va_end(args);	// Detect the log type and log accordingly (for now they basically do the same thing)	if(target & LOG_TYPE_USER) {		printf("\nAX User> *** %s *** \n\n", _Temp_Buf);		_FileLog << "\nAX User> *** " << _Temp_Buf << " *** \n\n";	}	if(target & LOG_TYPE_APPLICATION) {		printf("AX Application (%s)> %s\n", FunctionName, _Temp_Buf);		_FileLog << "AX Application (" << FunctionName << ")> " << _Temp_Buf << "\n";	}	if(target & LOG_TYPE_SYSTEM) {		printf("AX System (%s)> %s\n", FunctionName, _Temp_Buf);		_FileLog << "AX System (" << FunctionName << ")> " << _Temp_Buf << "\n";	}	if(target & LOG_TYPE_DEBUG) {#ifdef _DEBUG		printf("*** AX Debug (%s)> %s\n", FunctionName, _Temp_Buf);#endif	}}

1. 1
2. 2
3. 3
Rutin
16
4. 4
5. 5

• 14
• 9
• 9
• 9
• 10
• ### Forum Statistics

• Total Topics
632912
• Total Posts
3009186
• ### Who's Online (See full list)

There are no registered users currently online

×