Making a logger accessable to all classes?

Started by
28 comments, last by colinisinhere 19 years, 7 months ago
I wrote a logger class, and it works fine... but, how can i make this logger accessable to all of the classes in my project? are there any good tutorials on coding loggers? thanks!
Advertisement
class   logger{    //stuff}    g_logger;


globals have their use.
There's two ways to do this.

One is to do what Telastyn says, and use the
"extern" keyword for each of your files


logger g_logger in your main file, then any other file that uses it, use
extern logger g_logger

to declare it.
--
The other, more OO way is to use a flywheel / singleton.

Each class will assume it owns it's own verson of your logger, but that logger points to a single instance of logger. There's a singleton tutorial on this website.

Instead of having a single global Logger object, you could make the Logger class a singleton:

class Logger{public:        // The single Logger object    static Logger logger;        // ...private:        // Make constructors private to prevent object construction    Logger();    Logger(const Logger&);        // ...};

Note that this is only a very simple way to implement a singleton, and is definitely not the best way to do things. If you haven't already, you should read up on singletons.
One of the ways I sometimes like to handle singletons is through a "handle" which you use it through:

template <typename SingletonT> class Singleton{        static SingletonT singleton;public:        static SingletonT & operator*( void ) { reutrn singleton; }        static SingletonT * operator->( void ) { return &singleton }};template <typename SingletonT> SingletonT Singleton::singleton;class MySingletonClass{//...};typedef Singleton< MySingletonClass > MySingleton;void function_that_uses_singleton ( void ){    MySingleton mysingleton;    mysingleton->CallFunction();    (*mysingleton).CallFunction();}
wow, thats tricky.... Ive been trying to get it working, but I got a small problem when compiling on the overload operators lines:

c:\Documents and Settings\Colin\My Documents\Colin's Projects\Narcotik\CSingleton.h(15): error C2802: static member 'operator *' has no formal parameters
c:\Documents and Settings\Colin\My Documents\Colin's Projects\Narcotik\CSingleton.h(15): error C2333: 'CSingleton<SingletonT>::operator`*'' : error in function declaration; skipping function body
c:\Documents and Settings\Colin\My Documents\Colin's Projects\Narcotik\CSingleton.h(16): error C2801: 'operator ->' must be a non-static member
c:\Documents and Settings\Colin\My Documents\Colin's Projects\Narcotik\CSingleton.h(16): error C2333: 'CSingleton<SingletonT>::operator`->'' : error in function declaration; skipping function body


Any idea?
operator -> and operator * cannot be statics, however the error I recall is something informing you of that. Possibly the templates are messing with the compiler's errors or something, but I am sure that operator -> and operator * can't be statics.

edit: Well DUUUUUUUUUUUUUUUUUUUURRRRR it has it right there, I must be blind. sorry for the stupidity.
my logger is not OO, and i dont think it needs to be!
This is mutch cleaner!

iLog.h

#define ILOGFILENAME "iLog.txt"

iLogInit(bool do_we_log);
iLog(char *c);
iLogNum(float f);

iLog.cpp

bool log;

iLogInit(bool do_we_log){
log = do_we_log;
//creates/clears the log file
};
iLog(char *c){
if(!log)return;
//opens the file, and logs the string (0-terminated)
};
iLogNum(float f){
if(!log)return;
//opens the file, and logs the number(converted to string)
};

This is so easy and clean, only include iLog.h anywhere you want to log something, no globals, no templates, no singeltons, just a simple logger... Its slow, but you dont want to log something that runs 1000000 times a sec, no problem....
You can easely create a macro, witch uses the _LINE_ and _FILE_ strings automaticly, and so on...
-Anders-Oredsson-Norway-
Using a singleton the way you suggest instead of a global is just syntactic difference IMO, it's not more OO or anything. As long as you're not actually passing a logger instance (in this case: the only instance) to each user of the logger, you're just doing global variables with different syntax (which is not necessarily bad).

@uncutno:
It's not a good idea to open the file, write and close in each logger call. This'll reduce performance, especially when outputting complex data.

Q: Coder
It's not a good idea to open the file, write and close in each logger call. This'll reduce performance, especially when outputting complex data.

This is the cons of this method.

The pros:
Its bullit safe, if your app craches, the file is closed, and the log file wont be touched, you got simple noOO functioncalls instead of a singelton... Why do we need a singelton in this problem? The logger dont need to have any stored variables?

If you miss the Init func, the new log will be added to the old log, no problem.

If i understand this right, there is no reason for a log file to be 1 MB large, you are suposed to read it.... If you load 1000000 enteties from a file, you are only interested in the ones that messed things up. add a logical filter around the log filter!

I use my logfile for testing, and in my app, you have to press a key combination at the start for it to start to log, i dont want end users to se the logfile, but they can if needed!

If you use the logger all the time, you get alot of reading ahead, my logger can easely produce hundreds of pages in seconds..

If you got this supercomplex data you want to log, add the func:
iLogSuperComplexData(SuperComplexDataClass *a);
Now you got all the bennefits!

My argument is: dont optimize or overcomplex things because of speed or design when you dont need to... a logger is a perfect example of "dont need to"...

-Anders-Oredsson-Norway-

This topic is closed to new replies.

Advertisement