Click here to Skip to main content
15,881,173 members
Articles / Desktop Programming / MFC
Article

Fixed-Length Logging

Rate me:
Please Sign up or sign in to vote.
4.58/5 (11 votes)
13 May 20023 min read 83.2K   1.6K   23   16
A simple class derived from CFile that will handle many of your logging needs.

Introduction

I do a lot of behind the scenes programming (no GUI) either in DLLs or DCOM/COM objects, and its not as easy to figure out any problems that occur if you can't see what is going on. Therefore, I try to log as many areas of my programs as I can. In this article I will give you a simple logging class that you can modify to suit your own needs.

To MFC, or not to MFC?

That is the question. I decided to derive the CLogFile class from CFile instead of using the File APIs because CFile is much easier to use. If you want to modify the code to use the API functions, have at it.

Why Fixed-Length?

Fixed-Length logging, where every record in the log is the same size in bytes, is easy to read with your eyes as well as with your applications. Each field in the record is also given a fixed-length. When the file is opened in Notepad you can easily distinguish each field as well as each record. If your application needs to read the log file, a fixed-length log is much easier for parsing records.

The biggest drawbacks to fixed-length logging is limited information. Since you are limited by the size of the field, you may not always have enough room for important information. Make sure you give your fields enough space before you start using the log.

LogRecord Structure and #defines

// maximum size of each record
#define RECORDSIZE  140     

// maximum number of records in the log (including header)
#define MAXRECORDS  11      

struct LogRecord
{
    char cDate[10];         // date of record entry
    char cTime[8];          // time of record entry
    char cModuleName[20];   // name of the exe the record 
                            //is associated with

    char cProcName[20];     // name of the procedure 
                            //generating the record

    char cDescription[80];  // description of the event 
                            // being logged

    // leave 2 bytes for \r\n at the end of the record
};

LogRecord is used to read and write all of the fields in the record. I chose 140 bytes as the size of each record (RECORDSIZE) and 11 records per log file (MAXRECORDS). RECORDSIZE is 2 bytes larger than LogRecord to account for a carriage return and line feed at the end of each record. If you change RECORDSIZE you must reflect that change in the size of your LogRecord fields and vise versa.

The CLogFile Class

As noted earlier, CLogFile inherits from CFile.

Public methods/members:

CLogFile();
CLogFile(LPCSTR filename, LPCSTR archivename = ""); 
virtual ~CLogFile();

void Set_cFileName(LPCSTR filename);
LPCSTR Get_cFileName();
void Set_cArchiveName(LPCSTR archivename);
LPCSTR Get_cArchiveName() { return cArchiveName; }; 
void Set_cModuleName(LPCSTR module);
void Set_cProcName(LPCSTR proc);
BOOL AddRecord(LPCSTR description);

Protected methods/members:

BOOL bArchiveIfMaxReached;  // archive the log file
char cFileName[MAX_PATH + 1]; // log file full path
char cArchiveName[MAX_PATH + 1]; // archive file full path
char cModuleName[20]; // name of the module using this log
char cProcName[20]; // name of the procedure generating the record
LogRecord HeaderRec; // header record
long lCurrentRecord; // the number of the last record in the log

BOOL OpenLogFile(LPCSTR filename);

void Set_HeaderRec();
BOOL AddHeaderRecord();

To get started, include LogFile.h and declare a CLogFile object. Use Set_cFileName(LPCSTR filename) to set the path and filename of the log file and Set_cModuleName(LPCSTR module) to set the Module name (I just use AfxGetApp()->m_pszAppName).

CLogFile supports archiving. Use Set_cArchiveName(LPCSTR archivename) to set the path and filename of the archive file and also to set bArchiveIfMaxReached = TRUE. If you do not archive, the first record in the file will be deleted for each new record surpassing the MAXRECORDS limit (FIFO - first in first out).

At the beginning of a procedure that will utilize the log, call the Set_cProcName(LPCSTR proc) method, passing in the name of your procedure. To add a log record, call AddRecord(LPCSTR description) and pass in the text you would like to see in the log file's description field.

The log file is opened before each record is added and closed directly afterwards so your app won't keep it open in case of a catastrophic failure.

Conclusion

The sample application I included, creates C:\mylog.log and C:\mylog.archive so you can see how the logging works first hand. There are more fields that I could have added, like error codes or record ids, but I will leave that up to you. Happy logging!

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


Written By
Software Developer (Senior)
United States United States
I have been a professional developer since 1996. I live in Illinois, in the USA. I am married and have four children.

Comments and Discussions

 
GeneralUsing in VC2008 Pin
JPhelps1-Nov-14 5:56
JPhelps1-Nov-14 5:56 
Questionhow to fixed space between characters Pin
hd428-Feb-06 6:43
hd428-Feb-06 6:43 
AnswerRe: how to fixed space between characters Pin
Jason Henderson28-Feb-06 8:49
Jason Henderson28-Feb-06 8:49 
GeneralRe: how to fixed space between characters Pin
hd428-Feb-06 9:43
hd428-Feb-06 9:43 
GeneralRe: how to fixed space between characters Pin
hd428-Feb-06 9:53
hd428-Feb-06 9:53 
GeneralRe: how to fixed space between characters Pin
hd49-Mar-06 11:53
hd49-Mar-06 11:53 
GeneralRe: how to fixed space between characters Pin
Jörgen Sigvardsson17-Aug-06 13:11
Jörgen Sigvardsson17-Aug-06 13:11 
GeneralGreat Job! Pin
ciaoroma28-Feb-05 15:44
ciaoroma28-Feb-05 15:44 
GeneralRe: Great Job! Pin
ciaoroma28-Feb-05 15:50
ciaoroma28-Feb-05 15:50 
GeneralSome suggestions Pin
Snakebyte5-Jun-03 19:46
Snakebyte5-Jun-03 19:46 
1) Use CStdioFile instead of CFile
2) Use __FILE__ & __LINE__ macros



I'm too geeky for this shirt,
too geeky for this shirt,
so geeky it Hertz!


GeneralRe: Some suggestions Pin
Jason Henderson6-Jun-03 2:47
Jason Henderson6-Jun-03 2:47 
GeneralRe: Some suggestions Pin
Snakebyte6-Jun-03 3:28
Snakebyte6-Jun-03 3:28 
Generalplease tell me Pin
Jason Henderson26-Jun-02 7:49
Jason Henderson26-Jun-02 7:49 
GeneralRe: please tell me Pin
Nish Nishant10-Jul-02 23:10
sitebuilderNish Nishant10-Jul-02 23:10 
GeneralRe: please tell me Pin
Jason Henderson11-Jul-02 3:20
Jason Henderson11-Jul-02 3:20 
GeneralRe: please tell me Pin
Anonymous2-Sep-02 7:12
Anonymous2-Sep-02 7:12 

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

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