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

Fixed-Length Logging

, 13 May 2002
Rate this:
Please Sign up or sign in to vote.
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

Share

About the Author

Jason Henderson
Software Developer (Senior)
United States United States
I have been a professional developer since 1996. I live in the middle of no where in Illinois, USA. I am married and have four children.

Comments and Discussions

 
GeneralUsing in VC2008 PinmemberJPhelps1-Nov-14 6:56 
Questionhow to fixed space between characters Pinmemberhd428-Feb-06 7:43 
AnswerRe: how to fixed space between characters PinmemberJason Henderson28-Feb-06 9:49 
GeneralRe: how to fixed space between characters Pinmemberhd428-Feb-06 10:43 
GeneralRe: how to fixed space between characters Pinmemberhd428-Feb-06 10:53 
GeneralRe: how to fixed space between characters Pinmemberhd49-Mar-06 12:53 
GeneralRe: how to fixed space between characters PinmemberJörgen Sigvardsson17-Aug-06 14:11 
GeneralGreat Job! Pinmemberciaoroma28-Feb-05 16:44 
GeneralRe: Great Job! PinmemberCiaoRoma28-Feb-05 16:50 
GeneralSome suggestions PinmemberSnakebyte5-Jun-03 20:46 
GeneralRe: Some suggestions PinmemberJason Henderson6-Jun-03 3:47 
Snakebyte wrote:
1) Use CStdioFile instead of CFile
 
What are the advantages over CFile?
 

Snakebyte wrote:
2) Use __FILE__ & __LINE__ macros
 
I assume these would be to give the source file and line number of the code?
 

Jason Henderson

My articles

"The best argument against democracy is a five-minute conversation with the average voter." - Winston Churchill


GeneralRe: Some suggestions PinmemberSnakebyte6-Jun-03 4:28 
Generalplease tell me PinmemberJason Henderson26-Jun-02 8:49 
GeneralRe: please tell me PinsubeditorNishant S11-Jul-02 0:10 
GeneralRe: please tell me PinmemberJason Henderson11-Jul-02 4:20 
GeneralRe: please tell me PinsussAnonymous2-Sep-02 8:12 

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 | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 14 May 2002
Article Copyright 2002 by Jason Henderson
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid