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: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: October 29, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this eSeminar, Gene Kim will discuss these survey findings and will share woeful tales of artifact management gone wrong! Gene will also share examples of how …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds