TRACER -- Reusable Class to Make Traces to Log File and External Trace Window

Environment: Windows 2000 SP2, VC6 SP3

  1. MFC is NOT needed.
  2. File logging and Trace to Window (OR BOTH) are possible. Set it by using the TRACE_INIT macro.
  3. Trace Window per process OR one within a machine is possible. Set it by using the TRACE_INIT macro.
  4. Maximum trace file size is controlled. Set it with TRACE_INIT. Just give 1, 2, 3...10 for size in MB.
  5. Trace Macros can be used just like ostream << outputs.
    • TRACER_STREAM("My test value is" << value1 << "String = " << String)
    • For printf like trace, use TRACER.Print("Value = %d, Value %s", value1, valueString)
    • To easily distinguish between lines, use Progress, error, exception, message markers in Print() statement. Refer to TraceMaker.h for these markers.
    • To log function entry and exit, use TRACE_FUNCTION_IN(). It will automatically add "Leaving from Function xyz in the trace window&file".
  6. Include TraceMaker.cpp and TraceMaker.H in the project and start using it. First, set the trace file name (if file logging is needed), maximum log file size, trace mode (window, file, or both), trace window mode using TRACE_INIT() macro.
  7. A precompiled header is not necessary. If needed, uncomment #include "stdafx.h" in the TraceMaker.cpp file.
  8. Enable/Disable trace by defining TRACER_ENABLED.

To see the working, left/right mouse click OR double-click it. Trace will be added to the window and file. Also, watch CTraceAppApp::InitInstance() to see the usage of the tracer macros/functions. See sample source code below.

BOOL CTraceAppApp::InitInstance()
{
  TRACE_INIT( _T("C:\\_MyTraceLog.txt"),
        2        /* MB */,
        FILE_AND_WINDOW /* Log file & window is needed */,
        true     /* One WIndow Per Process */);

  TRACE_FUNCTION_IN(_T("CTraceAppApp::InitInstance()"));
  int   nValue = 45678;
  float fValue = 2398.1039f;
  char  cFirst = 'R';
  char *String1  = "Tracer Test-1";
  TRACER_STREAM("1. TRACER_STREAM; These are my values "
    << nValue << fValue << cFirst << String1 << "\r\n");
  TRACER.Print(_T("2. TRACER.Print; These are my values %d, %f,
                                    %c, %s"),
    nValue, fValue, cFirst, String1);
  TRACER.Print(TRACER_OPE_PROGRESS, _T("Application Init
                                        in progress"));

  // Standard initialization
  AfxEnableControlContainer();
#ifdef _AFXDLL
  Enable3dControls();        // Call this when using MFC in a
                             // shared DLL
#else
  Enable3dControlsStatic();  // Call this when linking to MFC
                             // statically
#endif

  // Change the registry key under which our settings are stored.
  // TODO: You should modify this string to be something
  // appropriate, such as the name of your company or organization.
  SetRegistryKey(_T("Local AppWizard-Generated Applications"));

  LoadStdProfileSettings();  // Load standard INI file options
                             // (including MRU)

  // Register the application's document templates. Document
  // templates serve as the connection between documents, frame
  // windows, and views.

  CSingleDocTemplate* pDocTemplate;
  pDocTemplate = new CSingleDocTemplate(
    IDR_MAINFRAME,
    RUNTIME_CLASS(CTraceAppDoc),
    RUNTIME_CLASS(CMainFrame),         // main SDI frame window
    RUNTIME_CLASS(CTraceAppView));
  AddDocTemplate(pDocTemplate);

  // Parse command line for standard shell commands, DDE, file open
  CCommandLineInfo cmdInfo;
  ParseCommandLine(cmdInfo);

  // Dispatch commands specified on the command line
  if (!ProcessShellCommand(cmdInfo))
    return FALSE;

  // The one and only window has been initialized, so show and
  // update it.
  m_pMainWnd->ShowWindow(SW_SHOW);
  m_pMainWnd->UpdateWindow();

  return TRUE;
}

void CTraceAppView::OnLButtonDown(UINT nFlags, CPoint point)
{
  // To log entry and exit of the function.
  TRACE_FUNCTION_IN(_T("CTraceAppView::OnLButtonDown()"));
  // Logging using << operator.
  TRACER_STREAM(" L button clicked " << point.x << point.y
                                     <<"\r\n");
  // Trace marker can also be printed. Using first parameter.
  // Format is same as printf.
  TRACER.Print(TRACER_OPE_ERROR, _T("Error Here"));

  CView::OnLButtonDown(nFlags, point);
}


void CTraceAppView::OnRButtonDblClk(UINT nFlags, CPoint point)
{
  // To log entry and exit of the function.
  TRACE_FUNCTION_IN(_T("CTraceAppView::OnRButtonDblClk()"));
  // Simple printf like logging.
  TRACER.Print(_T("Right button double clicked at point %d, %d"),
    point.x, point.y);

  CView::OnRButtonDblClk(nFlags, point);
}

void CTraceAppView::OnRButtonDown(UINT nFlags, CPoint point)
{
  TRACE_FUNCTION_IN(_T("CTraceAppView::OnRButtonDown()"));
  // Using Exception marker; No newline is added at END;
  //                         So write "\r\n".
  TRACER_STREAM(" Right button clicked at" << point.x << point.y
                                           << "\r\n");

  try
  {
    int nDrawIncrment = m_nMaxSize / (prevPoint.y - point.y) ;
  }
  catch(...)
  {
    // Using Exception marker; Newline is added at END.
    TRACER.Print(TRACER_OPE_EXCEPTION, _T("OnRButtonDown -
                                           division by ZERO"));
  }

  CView::OnRButtonDown(nFlags, point);
}

void CTraceAppView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
  TRACE_FUNCTION_IN(_T("CTraceAppView::OnLButtonDblClk()"));
  // Without any markers. Newline is added at END.
  TRACER.Print(_T("Left button double clicked at %d, %d"),
                   point.x, point.y);

  // Using error trace marker.
  if (point.x > m_nMaxSize)
    TRACER.Print(TRACER_OPE_ERROR, _T("Invalid point"));

  CView::OnLButtonDblClk(nFlags, point);
}

Downloads

Download source - 145 Kb


Comments

  • Small bug and solution

    Posted by Legacy on 10/02/2003 12:00am

    Originally posted by: DAKOT


    if first arg in TRACE.Print is string, for example

    char *buffer="some string";
    TRACE.Print(_T("Sample string is %s"),buffer);

    then
    output will be wrong:
    Sample string is %ssome string

    reason: functions
    void CTraceMaker::Print(LPCTSTR szType, LPCTSTR szData, ...)
    and
    void CTraceMaker::Print(LPCTSTR szData, ...)
    are the same at this case.

    Solution:
    I changed first function name to PrintType

    Best regards

    Reply
  • Memory leak and solution...

    Posted by Legacy on 08/29/2003 12:00am

    Originally posted by: Baptiste Pierard

    Hi,
    
    This class is very usefull. I just add a timestamp for each entry.
    I detect a memory leak in your demo program. Here is how to correct it:

    add a destructor in TraceApp.h:
    -------------------------------
    class CTraceAppApp : public CWinApp
    {
    public:
    CTraceAppApp();
    virtual ~CTraceAppApp(); // <<<<<<< ADD THIS LINE

    // Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CTraceAppApp)
    public:
    virtual BOOL InitInstance();
    //}}AFX_VIRTUAL

    // Implementation
    //{{AFX_MSG(CTraceAppApp)
    afx_msg void OnAppAbout();
    // NOTE - the ClassWizard will add and remove member functions here.
    // DO NOT EDIT what you see in these blocks of generated code !
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    };


    and add the destructor code in TraceApp.cpp:
    ---------------------------------------------
    CTraceAppApp::~CTraceAppApp()
    {
    TRACER.Release(); // free memory
    }

    Now, everything should be ok !!!

    Baptiste ;-)


    Reply
  • Generalized one that everybody will make use of

    Posted by Legacy on 12/08/2002 12:00am

    Originally posted by: R.Sundararaman

    Good work.
    You can generalize the tracer window instead of creating your own window by having a member m_hwnd. But in that case,
    the result window should be writable( editable ).
    Fine work once again.
    Thankx

    Reply
  • Stay on top / Autoscroll

    Posted by Legacy on 12/08/2002 12:00am

    Originally posted by: Michal Mecinski

    Good work and very useful.

    I would make two small changes:
    - make the output window stay on top of other windows
    - scroll the output down after you add new lines
    This would make tracing a bit easier.

    Thank you.

    Reply
  • Add OutputDebugString

    Posted by Legacy on 12/06/2002 12:00am

    Originally posted by: Enda Mannion

    Very good have used it already, but maybe it should incorporate an OutputDebugString() feature so traces can 
    
    also be seen in debuggers as well as a file and a window.

    Very usefull code.
    Enda

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

  • When it comes to desktops – physical or virtual – it's all about the applications. Cloud-hosted virtual desktops are growing fast because you get local data center-class security and 24x7 access with the complete personalization and flexibility of your own desktop. Organizations make five common mistakes when it comes to planning and implementing their application management strategy. This eBook tells you what they are and how to avoid them, and offers real-life case studies on customers who didn't let …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds