NDC.hh 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * NDC.hh
  3. *
  4. * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
  5. * Copyright 2000, Bastiaan Bakker. All rights reserved.
  6. *
  7. * See the COPYING file for the terms of usage and distribution.
  8. */
  9. #ifndef _LOG4CPP_NDC_HH
  10. #define _LOG4CPP_NDC_HH
  11. #include <log4cpp/Portability.hh>
  12. #include <string>
  13. #include <vector>
  14. namespace log4cpp {
  15. /**
  16. The NDC class implements <i>nested diagnostic contexts</i> as
  17. defined by Neil Harrison in the article "Patterns for Logging
  18. Diagnostic Messages" part of the book "<i>Pattern Languages of
  19. Program Design 3</i>" edited by Martin et al.
  20. <p>A Nested Diagnostic Context, or NDC in short, is an instrument
  21. to distinguish interleaved log output from different sources. Log
  22. output is typically interleaved when a server handles multiple
  23. clients near-simulatanously.
  24. <p>Interleaved log output can still be meaningful if each log entry
  25. from different contexts had a distinctive stamp. This is where NDCs
  26. come into play.
  27. <p><em><b>Note that NDCs are managed on a per thread
  28. basis</b></em>. NDC operations such as <code>push</code>, <code>
  29. pop</code>, <code>clear</code>, <code>getDepth</code> and <code>
  30. setMaxDepth</code> affect the NDC of the <em>current</em> thread only.
  31. NDCs of other threads remain unaffected.
  32. <p>To build an NDC one uses the <code>push</code> operation.
  33. Simply put,
  34. <p><ul>
  35. <li>Contexts can be nested.
  36. <p><li>When entering a context, call <code>NDC.push</code>. As a
  37. side effect, if there is no nested diagnostic context for the
  38. current thread, this method will create it.
  39. <p><li>When leaving a context, call <code>NDC.pop</code>.
  40. </ul>
  41. <p>There is no penalty for forgetting to match each
  42. <code>push</code> operation with a corresponding <code>pop</code>,
  43. except the obvious mismatch between the real application context
  44. and the context set in the NDC.
  45. <p>Custom Layouts may include the nested diagnostic context for the
  46. current thread in log messages, without any user intervention.
  47. Hence, even if a server is serving multiple clients
  48. simultaneously, the logs emanating from the same code (belonging to
  49. the same category) can still be distinguished because each client
  50. request will have a different NDC tag.
  51. <p><em>Unfortunately, unlike Java, C++ does not have platform
  52. independent multithreading support. Therefore, currently log4cpp is
  53. not multithread aware, it implicitly assumes only one thread exists,
  54. the main process thread. </em>
  55. **/
  56. class LOG4CPP_EXPORT NDC {
  57. /**
  58. Whether NDC feature is ever used by the user. If it is not used then saves some time by skipping instructions
  59. from: ver.1.1
  60. **/
  61. static bool isUsedNDC;
  62. static const std::string emptyString;
  63. public:
  64. struct DiagnosticContext {
  65. DiagnosticContext(const std::string& message);
  66. DiagnosticContext(const std::string& message,
  67. const DiagnosticContext& parent);
  68. std::string message;
  69. std::string fullMessage;
  70. };
  71. typedef std::vector<DiagnosticContext> ContextStack;
  72. /**
  73. Clear any nested disgnostic information if any. This method is
  74. useful in cases where the same thread can be potentially used
  75. over and over in different unrelated contexts.
  76. <p>This method is equivalent to calling the <code>setMaxDepth</code>
  77. method with a zero <code>maxDepth</code> argument.
  78. **/
  79. static void clear();
  80. /**
  81. Clone the diagnostic context for the current thread.
  82. <p>Internally a diagnostic context is represented as a stack. A
  83. given thread can supply the stack (i.e. diagnostic context) to a
  84. child thread so that the child can inherit the parent thread's
  85. diagnostic context.
  86. <p>The child thread uses the <code>inherit</code> method to
  87. inherit the parent's diagnostic context.
  88. @return Stack A clone of the current thread's diagnostic context.
  89. **/
  90. static ContextStack* cloneStack();
  91. /**
  92. Get the current diagnostic context string.
  93. @return the context string.
  94. **/
  95. static const std::string& get();
  96. /**
  97. Get the current nesting depth of this diagnostic context.
  98. @return the nesting depth
  99. **/
  100. static size_t getDepth();
  101. static void inherit(ContextStack* stack);
  102. /**
  103. Clients should call this method before leaving a diagnostic
  104. context.
  105. <p>The returned value is the value that was pushed last. If no
  106. context is available, then the empty string "" is returned.
  107. @return String The innermost diagnostic context.
  108. **/
  109. static std::string pop();
  110. /**
  111. Push new diagnostic context information for the current thread.
  112. <p>The contents of the <code>message</code> parameter is
  113. determined solely by the client.
  114. @param message The new diagnostic context information.
  115. **/
  116. static void push(const std::string& message);
  117. /**
  118. Set the maximum nesting depth for the current NDC. Curently NDCs
  119. do not enforce a maximum depth and consequentially this method
  120. has no effect.
  121. @param maxDepth the maximum nesting depth
  122. **/
  123. static void setMaxDepth(int maxDepth);
  124. /**
  125. Return the NDC for the current thread.
  126. @return the NDC for the current thread
  127. **/
  128. static NDC& getNDC();
  129. NDC();
  130. virtual ~NDC();
  131. public:
  132. virtual void _clear();
  133. virtual ContextStack* _cloneStack();
  134. virtual const std::string& _get() const;
  135. virtual size_t _getDepth() const;
  136. virtual void _inherit(ContextStack* stack);
  137. virtual std::string _pop();
  138. virtual void _push(const std::string& message);
  139. virtual void _setMaxDepth(int maxDepth);
  140. ContextStack _stack;
  141. };
  142. }
  143. #endif // _LOG4CPP_NDC_HH