You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4cxx-user@logging.apache.org by "Shuvalov, Andrew V" <An...@gs.com> on 2004/05/11 00:37:18 UTC

Nice NDC example

I want to contribute a nice example of how to use NDC. First I defined a
class and few macros:

    /** The helper class enabling \ref NDC. */
    class NDContext {

        static log4cxx::helpers::ThreadSpecificData _threadSpecificData;

        const char *_group;
        log4cxx::StringBuffer &_oss;
        const char *_file;
        int _line;

    public:

        NDContext (const char *group, log4cxx::StringBuffer &msg, const char
*file, int line);
        
        ~NDContext ();

        static void raiseErrorFlag ();
        static void clearErrorFlag ();
    };

Matrix::NDContext::NDContext (const char *group, log4cxx::StringBuffer &msg,
const char *file, int line)
    : _group(group), _oss(msg), _file(file), _line(line)
{
}

Matrix::NDContext::~NDContext ()
{
    bool *flag = (bool *)_threadSpecificData.GetData();
    if (flag != NULL && *flag) {
        ::log4cxx::StringBuffer oss;
        oss << "\t" << _group << ": " << _oss.str() << " at " << _file <<
":" << _line << "\n"; 
        log4cxx::NDC::push (oss.str());
    }
}

void Matrix::NDContext::raiseErrorFlag ()
{
    bool *flag = (bool *)_threadSpecificData.GetData();
    if (flag == NULL) { // first time
        flag = new bool;
        *flag = true;
        _threadSpecificData.SetData ((void *)flag);
    }
    *flag = true;
}

void Matrix::NDContext::clearErrorFlag ()
{
    bool *flag = (bool *)_threadSpecificData.GetData();
    if (flag != NULL) { // first time
        delete flag;
        _threadSpecificData.SetData (NULL);
    }        
}

/** See \ref NDC for details */
#define MATRIX_NDC_PUSH(group, message) \
    log4cxx::StringBuffer __nds_oss; \
    __nds_oss << message; \
    Matrix::NDContext __nds_ctx (group, __nds_oss, __FILE__, __LINE__);

#define MATRIX_NDC_RAISE_ERROR_FLAG Matrix::NDContext::raiseErrorFlag ()


Now, you can collect NDC in destructors, like this:

  void f3 ()
  {
      MATRIX_NDC_PUSH ("myprog", "f3");
    
      MATRIX_NDC_RAISE_ERROR_FLAG;
  }

  void f2 ()
  {
      MATRIX_NDC_PUSH ("myprog", "f2");
      f3();
  }

  void f1 ()
  {
      MATRIX_NDC_PUSH ("myprog", "f1");
      f2();
  }
  
  int main () 
  {
      f1();
      MATRIX_ERROR ("test", 0, "f1 failed");
  }    

  The output is: 

22:02:31 t\@1 ERROR - test:f1 failed
NDC:    myprog: f3 at HelloLog.cc:17
        myprog: f2 at HelloLog.cc:24
        myprog: f1 at HelloLog.cc:30