NestedDiagnosticContext.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //
  2. // NestedDiagnosticContext.h
  3. //
  4. // $Id: //poco/1.4/Foundation/include/Poco/NestedDiagnosticContext.h#1 $
  5. //
  6. // Library: Foundation
  7. // Package: Core
  8. // Module: NestedDiagnosticContext
  9. //
  10. // Definition of the NestedDiagnosticContext class.
  11. //
  12. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  13. // and Contributors.
  14. //
  15. // SPDX-License-Identifier: BSL-1.0
  16. //
  17. #ifndef Foundation_NestedDiagnosticContext_INCLUDED
  18. #define Foundation_NestedDiagnosticContext_INCLUDED
  19. #include "Poco/Foundation.h"
  20. #include <vector>
  21. #include <ostream>
  22. namespace Poco {
  23. class NDCScope;
  24. class Foundation_API NestedDiagnosticContext
  25. /// This class implements a Nested Diagnostic Context (NDC),
  26. /// as described in Neil Harrison's article "Patterns for Logging
  27. /// Diagnostic Messages" in "Pattern Languages of Program Design 3"
  28. /// (Addison-Wesley).
  29. ///
  30. /// A NDC maintains a stack of context information, consisting of
  31. /// an informational string (e.g., a method name), as well as an
  32. /// optional source code line number and file name.
  33. /// NDCs are especially useful for tagging log messages with
  34. /// context information which is very helpful in a multithreaded
  35. /// server scenario.
  36. /// Every thread has its own private NDC, which is automatically
  37. /// created when needed and destroyed when the thread terminates.
  38. ///
  39. /// The NDCScope (or NDC::Scope) class can be used to automatically
  40. /// push information at the beginning of a scope, and to pop it
  41. /// at the end.
  42. /// The poco_ndc(info) macro augments the information with a
  43. /// source code line number and file name.
  44. {
  45. public:
  46. typedef NDCScope Scope;
  47. NestedDiagnosticContext();
  48. /// Creates the NestedDiagnosticContext.
  49. NestedDiagnosticContext(const NestedDiagnosticContext& ctx);
  50. /// Copy constructor.
  51. ~NestedDiagnosticContext();
  52. /// Destroys the NestedDiagnosticContext.
  53. NestedDiagnosticContext& operator = (const NestedDiagnosticContext& ctx);
  54. /// Assignment operator.
  55. void push(const std::string& info);
  56. /// Pushes a context (without line number and filename) onto the stack.
  57. void push(const std::string& info, int line, const char* filename);
  58. /// Pushes a context (including line number and filename)
  59. /// onto the stack. Filename must be a static string, such as the
  60. /// one produced by the __FILE__ preprocessor macro.
  61. void pop();
  62. /// Pops the top-most context off the stack.
  63. int depth() const;
  64. /// Returns the depth (number of contexts) of the stack.
  65. std::string toString() const;
  66. /// Returns the stack as a string with entries
  67. /// delimited by colons. The string does not contain
  68. /// line numbers and filenames.
  69. void dump(std::ostream& ostr) const;
  70. /// Dumps the stack (including line number and filenames)
  71. /// to the given stream. The entries are delimited by
  72. /// a newline.
  73. void dump(std::ostream& ostr, const std::string& delimiter) const;
  74. /// Dumps the stack (including line number and filenames)
  75. /// to the given stream.
  76. void clear();
  77. /// Clears the NDC stack.
  78. static NestedDiagnosticContext& current();
  79. /// Returns the current thread's NDC.
  80. private:
  81. struct Context
  82. {
  83. std::string info;
  84. const char* file;
  85. int line;
  86. };
  87. typedef std::vector<Context> Stack;
  88. Stack _stack;
  89. };
  90. typedef NestedDiagnosticContext NDC;
  91. class Foundation_API NDCScope
  92. /// This class can be used to automatically push a context onto
  93. /// the NDC stack at the beginning of a scope, and to pop
  94. /// the context at the end of the scope.
  95. {
  96. public:
  97. NDCScope(const std::string& info);
  98. /// Pushes a context on the stack.
  99. NDCScope(const std::string& info, int line, const char* filename);
  100. /// Pushes a context on the stack.
  101. ~NDCScope();
  102. /// Pops the top-most context off the stack.
  103. };
  104. //
  105. // inlines
  106. //
  107. inline NDCScope::NDCScope(const std::string& info)
  108. {
  109. NestedDiagnosticContext::current().push(info);
  110. }
  111. inline NDCScope::NDCScope(const std::string& info, int line, const char* filename)
  112. {
  113. NestedDiagnosticContext::current().push(info, line, filename);
  114. }
  115. inline NDCScope::~NDCScope()
  116. {
  117. try
  118. {
  119. NestedDiagnosticContext::current().pop();
  120. }
  121. catch (...)
  122. {
  123. poco_unexpected();
  124. }
  125. }
  126. //
  127. // helper macros
  128. //
  129. #define poco_ndc(func) \
  130. Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__)
  131. #if defined(_DEBUG)
  132. #define poco_ndc_dbg(func) \
  133. Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__)
  134. #else
  135. #define poco_ndc_dbg(func)
  136. #endif
  137. } // namespace Poco
  138. #endif // Foundation_NestedDiagnosticContext_INCLUDED