User/Developer Runtime Selectable Diagnostic Messages
[Runtime Diagnostics and Timers]

The runtime diagnostic output selection is achieved utilizing message marking within the source code and selection from the command line or input deck.

The First,

by implementing a dump member function and an operator<< free function, the class may be easily dumped using the << operator. And, second, by assigning appropriate bit masks, the diagnostic writer allows the diagnostic output to be selectively output by the developer or user at runtime.

For Example:

     class AnotherClass
     {
     public:
       AnotherClass(int i)
       {}
  
       double hairyCalc(int i) {
         return sin((double) i);
       }
  
       Writer &dump(Writer &dout) const {
         if (dout.shouldPrint()) {
           dout << "AnotherClass " << push << dendl;
  
           dout.m(LOG_MEMBERS) << "m_m1, " << m_m1 << dendl;
           dout.m(LOG_MEMBERS) << "m_mem2, " << m_mem2 << dendl;
  
           if (dout.shouldPrint(LOG_MEMBERS)) {
             dout << "hairyCalc" << push << dendl;
             for (int i = 0; i < 1000; ++i)
               dout << "hairyCalc(" << i << ") = " << hairyCalc(i) << dendl;
  
             dout << pop;
           }
           dout << pop;
         }
         return dout;
       }
  
     private:
       int    m_m1;
       int    m_mem2;
     };
  
     inline Writer &operator<<(Writer &dout, const AnotherClass &another_class) {
       return another_class.dump(dout);
     }
  
     class ShowWriter
     {
       void Func() {
         sierra::diag_writer dout(std::cout);
         dout.setPrintMask(LOG_LIGHT | LOG_HEAVY | LOG_MEMBERS);
  
         int j = 7;
  
         m_anotherClassVector.push_back(AnotherClass(j));
         m_anotherClassVector.push_back(AnotherClass(j*2));
         m_anotherClassVector.push_back(AnotherClass(j*2 + 1));
  
  
         dout.m(LOG_LIGHT) << "Light weight diagnostic message, j is " << j << dendl;
         dout.m(LOG_HEAVY) << "Heavy weight diagnostic message " << m_anotherClassVector << dendl;
       }
  
       Writer &dump(Writer &dout) const {
         if (dout.shouldPrint()) {
           dout << "ShowWriter, " << push << dendl;
  
           dout.m(LOG_MEMBERS) << "m_anotherClassVector, " << m_anotherClassVector << dendl;
           dout << pop;
         }
  
         return dout;
       }
  
       std::vector<AnotherClass> m_anotherClassVector;
     };
  
     inline Writer &operator<<(Writer &dout, const ShowWriter &show_diag_writer) {
       return show_diag_writer.dump(dout);
     }

Adding diagnostic writer to your application

Adding a diagnostic writer to your application allows you to leave diagnostic code in your application which is only seen when desired.

Adding additional LOG_mask

Adding a new mask and option name requires only adding the new bit to the enumeration in App_DiagWriter_fwd.h, where 0xmmmmmm00 is a previously unusd bit:

     #ifndef SIERRA_App_DiagWriter_fwd_h
     #define SIERRA_App_DiagWriter_fwd_h
    
     #include <Slib_DiagWriter_fwd.h>
    
     namespace sierra {
     namespace app {
    
     enum {
       LOG_ALWAYS          = sierra::LOG_ALWAYS,
       LOG_TRACE           = sierra::LOG_TRACE,
       LOG_TRACE_STATS     = sierra::LOG_TRACE_STATS,
       LOG_TRACE_SUB_CALLS = sierra::LOG_TRACE_SUB_CALLS,
       LOG_MEMBERS         = sierra::LOG_MEMBERS,
    
       ...
       LOG_NEWUNUSEDBIT = 0x<i>mmmmmm00</i>,
       ...

     };
    
     } // namespace app
     } // namespace sierra
    
     #endif // SIERRA_App_DiagWriter_fwd_h

And, adding a mask function call in the parser constructor in the App_DiagWriter.C file.

     DiagWriterParser::DiagWriterParser()
         : Diag::WriterParser()
     {
       /* %TRACE% */  /* %TRACE% */

       ...
       mask("new-bit-name", (Diag::PrintMask) (LOG_NEWUNUSEDBIT), "Some brief description");
       ...
     }

Adding diagnostic output to your classes

To incorporate the diagnostic writer into a class or application, there are only a few steps to follow. And, by following these guidelines, the newly created class can fully participate is class data diagnostic output.

In your class header:

In your class implementation:

Adding diagnostic output to library classes

Writing to the appout writer

There are several functions and manipulators which control the selection and formatting of the diagnostic output.

Indentation and exceptions

When exception occur, the pops put-to the output stream are skipped by the exception catch block. As a result, the indentation can start to march across the screen. To correct this behavior, add a ThrowSafe sentry within your try block prior to any push operations.

  try { // TimeStepError
       stk::diag::WriterThrowSafe throw_safe_sentry;
 
       appout.m(LOG_TEST) << "Executing run_it() on " << name() << push << dendl;
       run_it();
       appout.m(LOG_TEST) << pop;   
     }
     catch (std::exception &x) {
       appout.m(LOG_TEST) << "Exception caught running run_it() on " << name() << dendl;
     }


Generated on Tue Jul 13 09:27:33 2010 for Sierra Toolkit by  doxygen 1.4.7