logger class

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

logger class

Post by sudi »

I know irrlicht has a integrated log system but sometimes u need logging in areas where you don't need irrlicht and passing a logger around is kinda anoying.
thes system flushed on every nlog, nlogl, nlerror automaticly and appends a linebreak at the end of the lastly written log/error text.
if u want to flush directly pass nlflush as last parameter.

Code: Select all

#include <stdio.h>
#include <time.h>
#include <irrlicht.h>

namespace AppFrame
{
    class ILog
    {
    public:
        class ILogAble
        {
        public:
            virtual ~ILogAble(void){}
            virtual void toLogString(ILog& logger) const = 0;
        };
        enum ILogParameter
        {
            NLP_FLUSH,
            NLP_ENDL,
            NLP_FLUSH_ENDL
        };

        enum E_LOG_TYPE
        {
            ELT_LOG = 0,
            ELT_ERROR,
            ELT_COUNT
        };

        class ILogReceiver// : public IPointer
        {
        public:
            virtual void OnLogEvent(const irr::core::stringc& event, E_LOG_TYPE type, irr::u32 loglevel) = 0;
        };

        ILog(void)
        {
            FlushTreshold = 50;
            LogLevel = 0;
            UsedLogLevel = 0;
            LogType = ELT_LOG;
            LogInfo = "LOG: ";
            ErrorInfo = "ERROR: ";
            Log_File = NULL;
            Log2Screen = true;
        }
        ~ILog(void)
        {
            flush();
            if (Log_File)
                fclose(Log_File);
            Log_File = NULL;
        }
        void check_flush(void)
        {
            if (CurrentString.size() >= FlushTreshold)
                flush();
        }
        void flush(void)
        {
            //flush log
            if (CurrentString.size() > 0)
            {
                irr::core::stringc lstring;
                if (LogType == ELT_LOG)
                    lstring.append(LogInfo);
                else
                    lstring.append(ErrorInfo);
                lstring.append(CurrentString);
                ///send to receiver
                for (irr::u32 i=0;i<Receiver.size();i++)
                {
                    Receiver[i]->OnLogEvent(CurrentString, LogType, LogLevel);
                }
                CurrentString = "";
                if (Log2Screen)
                    printf("%s", lstring.c_str());
                if (Log_File)
                    fprintf(Log_File, "%s", lstring.c_str());
            }
        }
        void addReceiver(ILogReceiver* receiver)
        {
            for (irr::u32 i=0;i<Receiver.size();i++)
                if (Receiver[i] == receiver)
                    return;
            Receiver.push_back(receiver);
        }
        void removeReceiver(ILogReceiver* receiver)
        {
            for (irr::u32 i=0;i<Receiver.size();i++)
                if (Receiver[i] == receiver)
                {
                    Receiver.erase(i);
                    return;
                }
        }

        ILog& operator<<(const ILogParameter& para)
        {
            switch (para)
            {
            case NLP_FLUSH:
                flush();
                return *this;
                break;
            case NLP_ENDL:
                add("\n");
                break;
            case NLP_FLUSH_ENDL:
                add("\n");
                flush();
                return *this;
                break;
            }
            return *this;
        }
        void add(const irr::core::stringc& s)
        {
            if (LogLevel > UsedLogLevel && LogType == ELT_LOG)
                return;
            CurrentString.append(s);
        }
        ILog& operator<<(const irr::core::stringc& s)
        {
            add(s);
            return *this;
        }
        ILog& operator<<(const irr::core::stringw& s)
        {
            add(irr::core::stringc(s.c_str()));
            return *this;
        }
        ILog& operator<<(const ILogAble* s)
        {
            s->toLogString(*this);
            return *this;
        }
        ILog& operator<<(const irr::c8* s)
        {
            add(s);
            return *this;
        }
        ILog& operator<<(const irr::u32& s)
        {
            add(irr::core::stringc(s));
            return *this;
        }
        ILog& operator<<(const irr::s32& s)
        {
            add(irr::core::stringc(s));
            return *this;
        }
        ILog& operator<<(const irr::c8 s)
        {
            add(irr::core::stringc(s));
            return *this;
        }
        ILog& operator<<(const irr::f32& s)
        {
            add(irr::core::stringc(s));
            return *this;
        }

        ILog& operator<<(const bool& s)
        {
            if (s)
                add("true");
            else
                add("false");
            return *this;
        }
        void setLogFile(const irr::c8* file, const irr::c8* appname = "")
        {
            flush();
            if (Log_File)
                fclose(Log_File);

            Log_File = fopen(file, "w");
            irr::core::stringc name = appname;
            time_t rawtime;
            tm * timeinfo;

            time ( &rawtime );
            timeinfo = localtime ( &rawtime );
            fprintf(Log_File, "%s Logfile: %s\n\n", name.c_str(), asctime (timeinfo));
        }

        ///variables
        bool Log2Screen;
        irr::u32 FlushTreshold;
        irr::u32 LogLevel;

        irr::core::stringc LogInfo;
        irr::core::stringc ErrorInfo;

        ///get singelton
        static ILog& Instance(irr::u32 loglevel = 0, E_LOG_TYPE type = ELT_LOG, bool justGetInstance = false)
        {
            static ILog l;
            if (!justGetInstance)
            {
                if (l.CurrentString.size() > 0)
                    l<<NLP_ENDL;
                l.flush();
                l.UsedLogLevel = loglevel;
                l.LogType = type;
            }
            return l;
        }
    protected:
        FILE* Log_File;
        irr::u32 UsedLogLevel;
        E_LOG_TYPE LogType;
        irr::core::stringc CurrentString;
        irr::core::array<ILogReceiver*> Receiver;
    };

#define nlget AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_LOG, true)
#define nlogl(LEVEL) AppFrame::ILog::Instance(LEVEL, AppFrame::ILog::ELT_LOG)
#define nlog AppFrame::ILog::Instance()
#define nlsetFile AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_LOG, true).setLogFile
#define nlogLevel AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_LOG, true).LogLevel
#define nlog2Screen AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_LOG, true).Log2Screen
#define nlflushTreshold AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_LOG, true).FlushTreshold
#define nlinfo AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_LOG, true).LogInfo
#define nlinfoError AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_LOG, true).ErrorInfo
#define nlerror AppFrame::ILog::Instance(0, AppFrame::ILog::ELT_ERROR)
#define nlflush AppFrame::ILog::NLP_FLUSH
#define nlendl AppFrame::ILog::NLP_ENDL
#define nlfendl AppFrame::ILog::NLP_FLUSH_ENDL
}

struct test : public AppFrame::ILog::ILogAble
{
public:
    test(void)
    {
        Health = 100;
        Power = 20;
        Mana = 400;
    }
    int Health;
    int Power;
    int Mana;
    void toLogString(AppFrame::ILog& logger) const
    {
        irr::core::stringc s;
        logger<<"test[";
        logger<<"Health(";
        logger<<irr::core::stringc(Health);
        logger<<")";
        logger<<"Power(";
        logger<<irr::core::stringc(Power);
        logger<<")";
        logger<<"Mana(";
        logger<<irr::core::stringc(Mana);
        logger<<")";
        logger<<"]";
    }
};

int main(int argc, char* argv[])
{
    irr::c8* name = "Sudi";
    irr::u32 age = 100;
    bool t = false;
    test t2;
    nlogLevel = 0;
    nlsetFile("mylog.txt", "Dungeoneer!");
    nlog<<"Hey my "<<1<<" name is "<<name<<nlendl<<"and i am "<<age<<" years old";
    nlsetFile("test2.txt");
    nlog<<"It is really "<<t;
    nlog<<"Testing class logging: "<<&t2;
    nlerror<<"Some funking error";
   return 0;
}
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Nova
Competition winner
Posts: 99
Joined: Mon May 09, 2005 10:32 am

Post by Nova »

Thank you so much for this!!!
I always wondered how to do such a thing to be able to use custom types. Like

Code: Select all

ILog& operator<<(const core::vector3df& s);
Ulf
Posts: 281
Joined: Mon Jun 15, 2009 8:53 am
Location: Australia

Post by Ulf »

sometimes u need logging in areas where you don't need irrlicht and passing a logger around is kinda anoying
Not saying anything about your code, but you don't really need to pass the logger around.

I made my own debug class and debug event receiver.
I made the debug class static. I instantiate it when my engine starts up and then all my classes can use it. They just need to include the .h file.

Code: Select all

class IDebug : public irr::IReferenceCounted
{
public:
static IDebug * getDebugger()	{ return IDebug::m_pDebugger; }

virtual irr::ILogger * getLogger() const = 0;

virtual irr::IEventReceiver * getEventReceiver() const = 0;

protected:
static IDebug *	m_pDebugger;
};

class IDebugEventReceiver : public irr::IEventReceiver
{
public:
virtual void stop() = 0;

virtual void restart(irr::io::path const * outputFileName = NULL) = 0;

virtual bool isRunning() const = 0;

protected:
//! This method is called on all events.
/** Note: This is the one method that we have to implement. Will only be called 
if this event handler is registered with the irrlicht device. 
\param event: The irrlicht generated event. 
\return: Returns true if event was processed, false if not processed. */
virtual bool OnEvent(irr::SEvent const & event) = 0;

public:
virtual irr::io::path const & getOutputFileName() const = 0;

virtual void setOutputFileName(irr::io::path const & outputFileName) = 0;

};
I can hear birds chirping
:twisted:

I live in the Eye of Insanity.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

Ulf wrote:
sometimes u need logging in areas where you don't need irrlicht and passing a logger around is kinda anoying
Not saying anything about your code, but you don't really need to pass the logger around.

I made my own debug class and debug event receiver.
I made the debug class static. I instantiate it when my engine starts up and then all my classes can use it. They just need to include the .h file.
well thats one way of doing it. i tried another approach :D
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Post Reply