Click here to Skip to main content
Licence 
First Posted 29 Dec 2004
Views 29,994
Bookmarked 12 times

Debugging Technique: Logger for making logs in many ways at once

By | 29 Dec 2004 | Article
This logger can be configured to produce log output using various output types.

Introduction

This article is useful for those who want to see good design implementations. This article uses design patterns to solve the problem of logging in an effective way. Logging is an essential part of our development effort. Often we don't know the kind of inputs that can be passed as parameters to the API/Calls written. This can produce unexpected behavior by the application. So to check/verify, we must log the details in various ways, like we can store it in XML, Text file, Email, Print on console etc. Here I have only provided text based implementation as it is easy to do. You can derive your classes to implement other loggers.

Background

If you really want to learn what is behind the scenes then pick any simple book where design patterns have been given with examples. You will really learn something with this example as well.

Using the code

A little description of the code is given below. Don't forget to copy the example configuration file in a given directory in the source code of demo application.

We have one main class which is the parent of all loggers, CLogger.

class  CLogger
{
public:
    virtual void MakeLog( enum EnumLogType enumType ,string sData ) = 0;
    virtual void AddDate() = 0;
    virtual ~CLogger(){ }
protected:
    friend class CLoggerManager;
    virtual BOOL UpLoadSettings( ifstream &in_confile ){ return 0; }
};

Two main functions MakeLog, AddDate are provided which can serve to be either basic or the minimum functions for any logger. Now, any class derived from it must implement these two. The third function UpLoadSettings is explained later. See the section below:

class  CLoggerManager : public CLogger
{
    string m_sConfigFile;
    CLogResolver*    m_pResolver;
    void set_members( string &sConfigFile ,CLogResolver* pResolver );
    CLoggerManager(){}
    CLoggerManager( const CLoggerManager& );
    CLoggerManager& operator = ( const CLoggerManager& );
    vector<CLogger*> m_vOutput;
public:
    static CLoggerManager& instantiate( string sConfigFile ,
                    CLogResolver* pResolver );
    ~CLoggerManager();
private:
    BOOL LoadConfig();
public:
    void MakeLog( enum EnumLogType enumType ,string sData );
};

CLoggerManager class is an important part of logging. It acquires the interface from CLogger but also acts as manager by letting various loggers initialize with the data required by each one of them.

First understand the format of the configuration File. Config file contains the following:

  • Class name
  • Specific data
  • again class name and specific data....

Resolver returns the address of the new object whose class is specified in the class name. Then, UpLoadSettings loads the specific data. Here Resolver is added as we need not complicate reading of the configuration file. The most important thing to remember about resolver is that you can have derived classes of Resolver to handle more Loggers. Here, in the code, LoadConfig function loads the loggers one by one in the specified vector.

BOOL LoadConfig()
{
    try
    {
        if ( !m_pResolver )
            return FALSE;

        ifstream in_confile; 
        in_confile.open( m_sConfigFile.c_str() );
        if ( !in_confile.is_open() )
            return FALSE;


        // Now Read Settings
        while ( 1 )
        {
            string sClassName;
            in_confile >> sClassName;

            if ( !sClassName.length() )
                break;

            CLogger* pLogger = m_pResolver->Resolve( sClassName );

            if ( pLogger )
            {
                if ( !pLogger->UpLoadSettings( in_confile ) )
                    break;
            }
            else
                break;

            m_vOutput.push_back( pLogger );
        }
    }
    catch(...)
    {
        // Catch any exception
    }
    return TRUE;
}

Now, if we make a call to CLoggerManager to log then it is routed to all the loggers inside, like this:

void MakeLog( enum EnumLogType enumType ,string sData )
{
   for (vector<CLogger *>::const_iterator iter_output = m_vOutput.begin();
                                            iter_output != m_vOutput.end() ; 
                                            ++iter_output )
   {
        CLogger* p_output = *iter_output;

        if ( p_output )
        {
            p_output->MakeLog( enumType ,sData );
        }
   }
}

Below is the code to make a single instance of Logger as we don't want to replicate our CLoggerManager object (we don't need it).

static CLoggerManager& instantiate(string sConfigFile ,CLogResolver* pResolver)
{
    static CLoggerManager m_Manager;
    m_Manager.set_members( sConfigFile ,pResolver );
    m_Manager.LoadConfig();
    return m_Manager;
}

Have a look at the CFileLogger code in source code files to see how it works. It's very simple to understand.

History

This is the first article I have posted. I have many more new ideas that can enhance knowledge. I am also a learner. I'll wait for your responses. If you have any suggestions, you are welcome.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

DevRanjeet

Web Developer

France France

Member

C,C++,MFC,COM,ATL,Mathematics,Simulation

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralNice Example PinmemberDavid E8:21 29 Dec '04  
GeneralStop reinventing the wheel PinsitebuilderUwe Keim5:23 29 Dec '04  
GeneralRe: Stop reinventing the wheel PinmemberHurricane Gordon5:57 29 Dec '04  
GeneralRe: Stop reinventing the wheel PinsitebuilderUwe Keim6:08 29 Dec '04  
GeneralRe: Stop reinventing the wheel PinmemberHurricane Gordon6:30 29 Dec '04  
GeneralRe: Stop reinventing the wheel PinmemberDmityShm23:48 29 Mar '07  
GeneralRe: Stop reinventing the wheel PinmemberDevRanjeet16:08 29 Dec '04  
Generalnice article Pinmembersudhir mangla0:53 29 Dec '04  
GeneralRe: nice article Pinsussyafan4:14 29 Dec '04  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 29 Dec 2004
Article Copyright 2004 by DevRanjeet
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid