Click here to Skip to main content
Click here to Skip to main content

Advanced Logging for all kind of applications

, 23 Feb 2002
Rate this:
Please Sign up or sign in to vote.
Simple to use classes for logging and tracing.
<!-- Download Links --> <!-- Article image -->

Sample Image - gui_window.gif

Logging Module

This logging module has seven classes: CLog, CFuncLog, IStoreLog, CWinLog, CFileLog, CAutoCritic, CLogSimpleLock.

The main class of the Logging module is the CLog class and in most cases it must be a singleton in the application. Being a Singleton is not a requirement for it though.

The Second most useful class is CFuncLog. This class is used to log functions when entering and leaving. Also this class gives the developer an easy way to log any data. The Class has overloaded operators <<, that is why adding something to log is very easy.

UML Design of Logging Module

UML Diagram of Classes  
Figure 1. UML Design Class Inheritance Diagram

As you saw from Figure 1 the module classes are divided on two parts:

  • 1. Storage classes

  • 2. Logging classes

Storage Classes

The declaration of IStoreLog:

//////////////////////////////////////////////////////////////////////////
// Abstract class set three default function which must support any child.
// Any child must support buffered and non-buffered store

class IStoreLog
{
  public:
    virtual ~IStoreLog( void ){}; // virtual destructor
    virtual int FlushData() = 0;
    virtual int WriteString( const std::string &Message ) = 0;
    virtual int SetBufferLimit( long lSize ) = 0;
};
  

Storage classes have the functionality to buffer with data flushing. By default the storage class must store the data in its own buffer and only on a FlushData function call will it flush the buffer data to disk or elsewhere. As you understand the buffer of storage class in mostly cases are limited by system resources, that is why when the buffer reaches it's limit it will flush the data automatically. To set the buffer limit use the function SetBufferLimit. By default the Storage class implementation must allocate a buffer and only on a SetBufferLimit function call will it change its size.

To store string into storage use the function WriteString. The Storage class must have no formatting and store RAW data as is.

Logging Classes

In this section we have two classes: CLog - our main class and CFuncLog - helper class. Class CLog declared in clog.h and it implementation is in clog.cpp file. Class CFuncLog declared in cfuncLog.h, cfunclog.cpp.

Logger classes have special functions which make logging easier. While logging you can configure trace output: If you have no need for time then simply set the flag of CLog class using the function SetLogTime to false and the time will be not be added to the output. Also you can change the output format of time by calling SetTimeFormat. By default the class use Long time format. In the header can be found two defines of most useful time formats. First is a long default to class format, second is short one format without millisecond in output.

#define DEF_TIME_LONG_STR "%02u:%02u:%02u ms:%03u"
#define DEF_TIME_SHORT_STR "%02u:%02u:%02u"

WARNING: time formatting string must always have 4 or less printf formatting templates, otherwise you will have a stack error.

Also for CLog class can be set such properties as:

  • Message Output Format - SetMessageFormat and GetMessageFormat functions

  • AutoFlush - SetAutoFlush and GetAutoFlush functions. true mean flushing of storage buffer after each trace message. Very useful when application is in alpha testing and have some GPF's in code. Second mode useful when logging needed for controlling state of application and it's not very critical by time - this is top perfomance mode of logging system.

For logging in CLog class there are three functions:

  • LogRawString - trace raw string without formatting to storage class.

  • LogString - trace message with special level and formatting. There are two functions with the same name, only difference is a format of output string, in first case is a std::string on second simple char *.

  • LogFormatString - formatting function - wrapper on printf function.

In many cases developer will need more then three categories of messages that is why in CLog class is virtual function LevelText. As input parameter it have number of required LEVEL. Function will return string with Category Name. By default on Category name class set limitation on 12 symbols, but this can be changed by SetMessageFormat function template string.

To use Logging in application include into project such headers:

    #include "clog.h"
    #include "cfunclog.h"
    #include "cwinlog.h"  // include it if you want logging into GUI window
    #include "cfilelog.h" // include it if you want logging into files
    ...

CFuncLog class is not required it's only simplify logging of most used features, like: entering and leaving of function. Special Formatting and all needed to logging operations are implemented in CLog file. That is why you can choose: use it or not.

NOTE: CWinLog class store traced messages in window and are not multiprocess safe. Otherwise for multiprocess logging can be used only CFileLog class. By Using CFileLog all traced messages are store in file. All file operations are synchronized by OS.

How to use the module

  1. Create instance of CLog class:
    CLog *m_pLog = new CLog( new CFileLog( "c:\\log.log" ), LOG_MAX_LEVEL, true ); 

    First parameter of the CLog constructor must be pointer of class which support IStoreLog interface. In module are two implementations of IStoreLog virtual class: CWinLog and CFileLog.

    As you understand CWinLog class create GDI window in which display traced messages and second log class store logging into file.

    As a output file can be used any OS device or named pipe or something else, which use syntax of CreateFile API function.

    Second parameter is a upper limit of messages. It must be set to needed upper value limit.

    So if you set it to 0 then in log output will be only ERROR messages. If you set it to 1 then in log will be ERROR and WARNING messages... and so on.

    Third param said to CLog class instance is it a parent of IStoreLog class instance or not. By default this value is true. So CLog Class on destroy delete instance of IStoreLog class implementation.

  2. If you want to log functions entering and leaving then do like this:
    CRepTestApp::CRepTestApp()
    {
      CFuncLog log( m_pLog, "CRepTestApp::CRepTestApp" );
      ...
    }

    Such code will add into log entering and leaving of function code. Here used feature of automatic variables. On Construct into log added "enter ..." message and on destroy into log will be added "leave ..." message. To add something to log you can type such code:

    int something = 100;
    log << something;
    ...

    such code will add 100 into log output.

    WARNING: operator << stores log values in RAW format.

    To add message to log correctly use LogString function of the CFuncLog class.

If you want to store log into any other place then you must write implementation of IStoreLog class and use it instance as a constructor param. CAutoCritic and CLogSimpleLock classes is a wrappers on Critical Section API of windows. Such classes are implemented in stand alone file with namespace LOGGER and can be freely used by other IStoreLog class implementations.

History

First logger module was implemented in 2000 and after that was rewritten some times. I found that in many cases the Logger system was a requirement for commercial projects, that is why I spent some time and wrote such an easy to use and extendible logger/trace subsystem.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Oleksandr Kucherenko
CEO ArtfulBits Inc.
Ukraine Ukraine
Name:Kucherenko Oleksandr

Born:September 20, 1979

Platforms: Win32, Linux; - well known and MS-DOS; Win16; OS/2 - old time not touched;

Hardware: IBM PC

Programming Languages: Assembler (for Intel 80386); Borland C/C++; Borland Pascal; Object Pascal; Borland C++Builder; Delphi; Perl; Java; Visual C++; Visual J++; UML; XML/XSL; C#; VB.NET; T-SQL; PL/SQL; and etc.

Development Environments: MS Visual Studio 2001-2008; MS Visual C++; Borland Delphi; Borland C++Builder; C/C++ any; Rational Rose; GDPro; Together and etc.

Libraries: STL, ATL, WTL, MFC, NuMega Driver Works, VCL; .NET 1.0, 1.1, 2.0, 3.5; and etc.

Technologies: Client/Server; COM; DirectX; DirectX Media; BDE; HTML/DHTML; ActiveX; Java Servlets; DCOM; COM+; ADO; CORBA; .NET; Windows Forms; GDI/GDI+; and etc.

Application Skills: Databases - design and maintain, support, programming; GUI Design; System Programming, Security; Business Software Development. Win/Web Services development and etc.

Comments and Discussions

 
QuestionLicense agreement? Pinmemberfjosesen24-Jun-09 0:57 
AnswerRe: License agreement? PinmemberAlex Kucherenko24-Jun-09 2:49 
GeneralRe: License agreement? Pinmemberfjosesen24-Jun-09 11:34 
Generalthe bug of cwinlog [modified] PinmemberMember 134815818-Mar-09 16:58 
GeneralRe: the bug of cwinlog [modified] Pinmembermlh4627-Nov-12 22:12 
GeneralExcellent work! Pinmemberjcoco11-May-08 12:16 
GeneralRe: Excellent work! PinmemberAlex Kucherenko11-May-08 21:36 
Generalnot serious PinmemberDmityShm2-Apr-07 21:44 
GeneralRe: not serious PinmemberAlex Kucherenko2-Apr-07 21:53 
GeneralRe: not serious PinmemberDmityShm2-Apr-07 22:49 
GeneralRe: not serious PinmemberAlex Kucherenko2-Apr-07 22:54 
QuestionWhich tool used for UML Design ? Pinmemberana_v12315-Sep-05 3:13 
AnswerRe: Which tool used for UML Design ? PinmemberAlex Kucherenko2-Apr-07 21:55 
QuestionWhy don't this support unicode? PinmemberLam Ngo12-Jan-05 5:20 
AnswerRe: Why don't this support unicode? PinmemberAlex Kucherenko2-Apr-07 22:00 
Hi,
 
please look carefully on STL and it class std::string.
Easy modifications will allow you to make unicode available for you in 5 minutes.
 

 
Good Luck
Alex Kucherenko

Generalchange operator&lt;&lt; (char *) PinmemberBjörn Carlsson1-Dec-04 2:49 
GeneralRe: change operator&lt;&lt; (char *) PinmemberAlex Kucherenko2-Apr-07 22:03 
GeneralSynchronization bug PinsussBogdan Gonciulea30-Nov-04 1:31 
GeneralRe: Synchronization bug PinmemberAlex Kucherenko30-Nov-04 2:09 
Generalon current moment code not supported yet PinmemberAlex Kucherenko19-Oct-04 1:40 
Questioncan not set log file size Pinmemberxqyz888819-Oct-04 0:33 
GeneralConsole app Pinmemberrromerot28-Apr-04 8:45 
GeneralRe: Console app PinmemberAlex Kucherenko28-Apr-04 21:44 
Generalwhy don't call FlushFileBuffers in ~CFileLog Pinmemberzmxjh22-Oct-03 9:02 
GeneralRe: why don't call FlushFileBuffers in ~CFileLog PinmemberAlex Kucherenko23-Oct-03 21:39 
GeneralFile logger is not thread safe Pinmemberkrumpet24-Feb-03 12:36 
GeneralRe: File logger is not thread safe PinmemberAlex Kucherenko14-Jul-03 3:39 
GeneralRe: File logger is not thread safe Pinmemberphavd23-Sep-04 23:21 
GeneralRe: File logger is not thread safe PinmemberAlex Kucherenko23-Sep-04 23:57 
General<code>CClassLog</code> PinmemberThomas Freudenberg25-Feb-02 15:51 
GeneralRe: <code>CClassLog</code> PinmemberAlex Kucherenko25-Feb-02 21:36 
GeneralRe: <code>CClassLog</code> PinmemberThomas Freudenberg25-Feb-02 23:45 
GeneralRe: CClassLog PinmemberDmityShm2-Apr-07 20:42 
GeneralNice classes! PinmemberDaniel Lohmann24-Feb-02 14:05 
GeneralHelpful PinmemberThomas Freudenberg24-Feb-02 9:19 

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.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 24 Feb 2002
Article Copyright 2002 by Oleksandr Kucherenko
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid