CTracerST v1.0






2.23/5 (3 votes)
Jun 18, 2000

53170

1364
A flexible trace class for consistent application debug traces.
SoftechSoftware
homepage
SoftechSoftware Email
If you write commercial or real-time applications you are familiar with trace strings. These traces are those cryptic strings sent to screen or disk that help the programmer during the debug phase of his work.
If you write more than one application that needs traces you will look for a standard, simple to integrate and easy to use trace system.
CTracerST
presents a consistent way to implement and use
a trace system inside your applications.
Features of this class are:
-
Supports up to 10 different trace levels (can be increased to infinite)
- Buffers trace strings
- Trace strings can be automatically saved on disk
- Automatically writes files of predefined size
- Trace strings can be displayed in any way desired
(up to the programmer)
- Full UNICODE support
- Writes a plain text file (UNICODE compatible)
This class has been tested on:
-
Visual C++ 6.0 sp3
- Windows NT Workstation 4.0 sp6a
- Windows 2000
Terms of use
You can use CTracerST
anywhere you want, without limitations.
You can include this software in DLLs, libriaries, CD-ROM collections
etc. You are only asked to give credits to SoftechSoftware
for this portion of code.
If you use this class a screenshot of your application or a download
link (if shareware/freeware) is welcome.
If you find bugs or make improvements please let SoftechSoftware
know it!
Abstract
Basically CTracerST
accepts a string and a trace level.
If the level is enabled the string is stored internally else it is
discarded. Also, if save-to-disk is enabled, the string is
immediately saved.
Why trace levels?
Your application can produce a lot of trace strings. If you assign a particular type of information (info/errors/fatal errors ...) to each string then you will have the ability to programmatically select which type of traces produce. For example if you trace all information at level 0 then all information can be toggled on and off by disabling level 0 traces.
Trace strings are stored internally in the form of a STRUCT_TRACERST
structure:
typedef struct _STRUCT_TRACERST
{
DWORDdwLevel;
TCHARszText[256];
SYSTEMTIMEcsTime;
} STRUCT_TRACERST;
You will need to play with this structure only if your application needs to display the trace strings.
CTracerST
saves strings on disk in a plain text file. If
your application is built for UNICODE then these text files will be
UNICODE, that is, the characters 0xFFFE are written at the top of
file. This marker seems to be a standard mode to recognize an UNICODE
text file (Notepad does this).
The filename of the produced files is in the form ddmmyyyy_Tracexxx.txt
where xxx is a number starting from 000 to 255. CTracerST
has the ability to produce files more or less of a predefined size;
eachtime a new file is created it will be numbered sequentially from
0 to 255. The numeration starts by default from 0.
Example: 07062000_Trace000.txt
Trace strings are written in the form hh:mm:ss:ms [level]
< trace string>
Example: 09:26:03:0214 [0] Database started (Size = 32672 bytes)
CSharedQueueST
CTracerST
stores trace strings using a queue implemented
through a class called CSharedQueueST
.
When an element is added to the queue this class has the ability to:
-
Send a message to a window
- Set an event
- Resume a thread
Using one of this ways an application that needs to display trace
strings can detect when a new string is available.
The correct steps required to get a trace string from CTracerST
are:
-
Wait for a message, an event or a thread-resume
- Read the first available trace string (a
STRUCT_TRACERST
structure)
- Prepare the string as needed by the application
- Do whatever you want with the string
The following example shows how to display trace strings using a listbox:
STRUCT_TRACERST csTracer;
TCHAR szText[512];
int nIndex;
// Get the first string trace available
COLOR="BLUE">if (m_Tracer.GetItem((char*)&csTracer) == TRACERST_OK)
{
// Prepare a human-readable version of the string
::wsprintf(szText, _T("%02d:%02d:%02d:%04d [%lu] %s"), csTracer.csTime.wHour,
csTracer.csTime.wMinute,
csTracer.csTime.wSecond,
csTracer.csTime.wMilliseconds,
csTracer.dwLevel,
csTracer.szText);
COLOR="GREEN"> // Add the string to our listbox
nIndex = m_lbxTrace.AddString(szText);
COLOR="GREEN"> // Hilight the just added string
COLOR="BLUE">if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
m_lbxTrace.SetCurSel(nIndex);
} // if
How to integrate CTracerST in your application
Include in your application's project the following files:
<LI CLASS="mvd-PRE">TracerST.h
<LI CLASS="mvd-PRE">TracerST.cpp
<LI CLASS="mvd-PRE">SharedQueueST.h
<LI CLASS="mvd-PRE">SharedQueueST.cpp
<LI CLASS="mvd-PRE">Macros.h
declare a CTracerST
object:
CTracerST m_Tracer;
initialize your object:
m_Tracer.Create(250, 64, FALSE, this->m_hWnd, WM_APP + 1);
That's all! To use your tracer:
m_Tracer.Trace(0, _T("Trace string"));
CTracerST methods
Constructor
CTracerST();
Standard constructor. It does nothing.
Create
DWORD Create(DWORD dwMaxItems,
DWORD dwMaxFilesize,
BOOL bUseAlternateDateFormat,
HWND hWndParent = NULL,
UINT nMsgParent = NULL,
HANDLE hEventParent = NULL,
HANDLE hThreadHandle = NULL);
Initializes a CTracerST
object.
Parameters:
-
dwMaxItems
[IN] Maximum number of trace strings the object can hold.
-
dwMaxFilesize
[IN] Maximum size (in KBytes) of the saved files.
-
bUseAlternateDateFormat
[IN] Indicates if an alternate date-format convention must be used.
If TRUE files will be saved in the form mmddyyyy_Tracexxx.txt
If FALSE files will be saved in the form ddmmyyyy_Tracexxx.txt -
hWndParent
[IN] Handle of the window that will receive a message every time a string is traced.
-
nMsgParent
[IN] Message to send every time a string is traced.
-
hEventParent
[IN] Handle of the event to set every time a string is traced.
-
hThreadParent
[IN] Handle of the thread to resume every time a string is traced.
Return value:
-
TRACERST_OK
Object initialized successfully.
-
TRACERST_QUEUEERROR
An error occured while initializing the queue.
Example:
DWORD dwRetValue;
dwRetValue = m_Tracer.Create(250, 64, FALSE, this->m_hWnd, WM_APP + 1);
ASSERT(dwRetValue == TRACERST_OK);
Trace
DWORD Trace(BYTE byLevelNumber, LPCTSTR lpszText);
Traces a string.
Parameters:
-
byLevelNumber
[IN] The zero-based trace level number.
-
lpszText
[IN] String to trace. Maximum 256 TCHARs are allowed.
Remarks:
If the trace level is disabled the string will be ignored and
discarded. Also no message/event/thread will be sent/set/resumed. If
the trace level is outside the limits the string will be processed.
You can use SetTraceLevels
to enable/disable trace levels.
If the save flag is set then the string will be written to disk in
the specified directory. You can use SetFlags
to
set/reset flags and SetTraceDirectory
to set the
directory in which to save trace files.
CTracerST
comes with a default of 10 trace levels. If
you need more levels just change the TRACERST_MAX_LEVELS
define located in the TracerST.h
file.
#defineTRACERST_MAX_LEVELS 10
Return value:
-
TRACERST_OK
String traced successfully.
-
TRACERST_QUEUEERROR
An error is reported by the queue.
Example:
DWORD dwRetValue;
// This string will be traced only if level 2 is enabled
dwRetValue = m_Tracer.Trace(2, _T("Trace string"));
ASSERT(dwRetValue == TRACERST_OK);
COLOR="GREEN">// This string will always traced
dwRetValue = m_Tracer.Trace(99, _T("Trace string 2"));
GetItem
DWORD GetItem(char* szpBuffer,
BOOL bRemove = TRUE,
LPDWORD lpdwNumBytesCopied = NULL);
Gets the first available trace data from the CTracerST's queue.
Parameters:
-
szpBuffer
[IN] Points to a
STRUCT_TRACERST
structure that will receive the trace data.
It must be cast aschar*
. -
bRemove
[IN] Indicates if the trace data must be removed from the queue.
If TRUE the trace data will be removed from the queue.
If FALSE the trace data will remain in the queue. A second call toGetItem
will return the same trace data.
This value should be always TRUE. -
lpdwNumBytesCopied
[OUT] Returns the number of bytes copied in
szpBuffer
.
This value is alwaysSIZE_STRUCT_TRACERST
.
Return value:
-
TRACERST_OK
Function executed successfully.
-
TRACERST_QUEUEERROR
An error is reported by the queue.
This value also indicates that the queue is empty (no trace data available).
Example:
STRUCT_TRACERST csTracer;
TCHAR szText[512];
int nIndex;
// Get the first string trace available
COLOR="BLUE">if (m_Tracer.GetItem((char*)&csTracer) == TRACERST_OK)
{
// Prepare a human-readable version of the string
::wsprintf(szText, _T("%02d:%02d:%02d:%04d [%lu] %s"), csTracer.csTime.wHour,
csTracer.csTime.wMinute,
csTracer.csTime.wSecond,
csTracer.csTime.wMilliseconds,
csTracer.dwLevel,
csTracer.szText);
COLOR="GREEN">// Add the string to our listbox
nIndex = m_lbxTrace.AddString(szText);
COLOR="GREEN">// Hilight the just added string
COLOR="BLUE">if (nIndex != LB_ERR && nIndex != LB_ERRSPACE)
m_lbxTrace.SetCurSel(nIndex);
} // if
SetTraceDirectory
void SetTraceDirectory(LPCTSTR lpszTraceDir);
Sets the directory where trace files are to be saved.
Parameters:
-
lpszTraceDir
[IN] Pointer to a null-terminated string that specifies the directory where save trace files.
This directory must exists and must be backslash terminated.
Maximum _MAX_PATH TCHARs are allowed.
Remarks:
By default trace files are saved in the directory from which the
application loaded.
Example:
m_Tracer.SetTraceDirectory(_T("c:\\traces\\"));
GetTraceLevels
void GetTraceLevels(LPBYTE lpbyTraceLevels);
Retrieves the state (enabled/disabled) of all trace levels.
Parameters:
-
lpbyTraceLevels
[OUT] Pointer to an array of bytes that will receive the trace levels state.
Remarks:
The specified byte array must be large enough to receive the state of
all available trace levels.
A state set to 1 means enabled, while set to 0 means disabled.
byArray[0] --- Trace level 0 state
.
.
.
byArray[TRACERST_MAX_LEVELS - 1] --- Trace level TRACERST_MAX_LEVELS - 1 state
Example:
the following example tests the state of the trace level number 0.
BYTE byTraceLevels[TRACERST_MAX_LEVELS];
m_Tracer.GetTraceLevels(byTraceLevels);
if (byTraceLevels[0] == 1) // Enabled
{
}
COLOR="BLUE">else // Disabled
{
}
SetTraceLevels
void SetTraceLevels(LPBYTE lpbyTraceLevels);
Sets the state (enabled/disabled) of all trace levels.
Parameters:
-
lpbyTraceLevels
[IN] Pointer to an array of bytes that specifies the state of all trace levels.
Remarks:
The specified byte array must hold the state of all available trace levels.
A state set to 1 means enabled, while set to 0 means disabled.
Example:
the following example sets to enabled all trace levels.
BYTE byTraceLevels[TRACERST_MAX_LEVELS];
::FillMemory(&byTraceLevels, sizeof(byTraceLevels), 1);
m_Tracer.SetTraceLevels(byTraceLevels);
GetFlags
void GetFlags(LPBYTE lpbyFlags);
Get CTracerST
flags.
Parameters:
-
lpbyFlags
[OUT] Pointer to a byte that will receive the flags.
Example:
BYTE byFlags;
m_Tracer.GetFlags(&byFlags);
SetFlags
void SetFlags(LPBYTE lpbyFlags);
Set CTracerST
flags.
Parameters:
-
lpbyFlags
[IN] Pointer to a byte that specifies the new flags.
Remarks:
Each bit of the byte specifies a single flag.
Currently only one flag is supported:
-
TRACERST_FLAG_SAVE
Save traces to disk.
Example:
the following example sets the save-to-disk flag.
BYTE byFlags;
m_Tracer.GetFlags(&byFlags);
byFlags |= TRACERST_FLAG_SAVE;
m_Tracer.SetFlags(&byFlags);
GetVersionI
short GetVersionI();
Returns the CTracerST
version as a short number.
Divide by 10 to get actual version.
GetVersionC
LPCTSTR GetVersionC();
Returns the CTracerST
version as a string.
Example:
TCHAR szText[128];
::wsprintf(szText, _T("Version is: %s"), CTracerST::GetVersionC());
::MessageBox(NULL, szText, NULL, MB_OK);
Remarks
CTracerST
is Critical-Section protected. This makes it
callable from different threads at the same time without problems
(thread-safe). It's currently used in two industrial application
without problems of any type.
The only area where an application must take care is to not fill the
trace queue. This queue has a limited number of trace strings that
can buffered, as specified in the Create
function (dwMaxItems
parameters). Trace data are not removed from the queue by CTracerST
.
Even if an application doesn't need to display traces it should
remove trace datas from the queue. It can be done with the following example:
// The application handles the WM_APP + 1 message with the following function
LRESULT MyApp::On_RM_TRACE(WPARAM wParam, LPARAM lParam)
{
m_Tracer.GetItem(NULL);
COLOR="BLUE">return 0;
} // End of On_RM_TRACE
Want to include CTracerST in a DLL ?
CTracerST
is ready to be used from inside a DLL. You
need to export from your DLL CTracerST
and also CSharedQueueST
.
Include in your DLL's project the following files:
<LI CLASS="mvd-PRE">TracerST.h
<LI CLASS="mvd-PRE">TracerST.cpp
<LI CLASS="mvd-PRE">SharedQueueST.h
<LI CLASS="mvd-PRE">SharedQueueST.cpp
<LI CLASS="mvd-PRE">Macros.h
Add to your DLL's project settings the following defines:
<LI CLASS="mvd-PRE">_CMLHTDLL_NOLIB_
<LI CLASS="mvd-PRE">_CMLHTDLL_BUILDDLL_
From TracerST.h
comment the following line:
#define _TRACERST_NODLL_
then update the various #pragma comment(lib, "???")
according to your DLL produced .lib files.
From SharedQueueST.h
comment the following line:
#define _SHAREDQUEUEST_NODLL_
then update the various #pragma comment(lib, "???")
according to your DLL produced .lib files.
History
-
CTracerST v1.0
First release