Fixed-Length Logging






4.58/5 (11 votes)
May 14, 2002
3 min read

84543

1627
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!