123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*
- * NDC.hh
- *
- * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
- * Copyright 2000, Bastiaan Bakker. All rights reserved.
- *
- * See the COPYING file for the terms of usage and distribution.
- */
- #ifndef _LOG4CPP_NDC_HH
- #define _LOG4CPP_NDC_HH
- #include <log4cpp/Portability.hh>
- #include <string>
- #include <vector>
- LOG4CPP_NS_BEGIN
- /**
- The NDC class implements <i>nested diagnostic contexts</i> as
- defined by Neil Harrison in the article "Patterns for Logging
- Diagnostic Messages" part of the book "<i>Pattern Languages of
- Program Design 3</i>" edited by Martin et al.
- <p>A Nested Diagnostic Context, or NDC in short, is an instrument
- to distinguish interleaved log output from different sources. Log
- output is typically interleaved when a server handles multiple
- clients near-simulatanously.
- <p>Interleaved log output can still be meaningful if each log entry
- from different contexts had a distinctive stamp. This is where NDCs
- come into play.
- <p><em><b>Note that NDCs are managed on a per thread
- basis</b></em>. NDC operations such as <code>push</code>, <code>
- pop</code>, <code>clear</code>, <code>getDepth</code> and <code>
- setMaxDepth</code> affect the NDC of the <em>current</em> thread only.
- NDCs of other threads remain unaffected.
- <p>To build an NDC one uses the <code>push</code> operation.
- Simply put,
- <p><ul>
- <li>Contexts can be nested.
- <p><li>When entering a context, call <code>NDC.push</code>. As a
- side effect, if there is no nested diagnostic context for the
- current thread, this method will create it.
- <p><li>When leaving a context, call <code>NDC.pop</code>.
- </ul>
- <p>There is no penalty for forgetting to match each
- <code>push</code> operation with a corresponding <code>pop</code>,
- except the obvious mismatch between the real application context
- and the context set in the NDC.
- <p>Custom Layouts may include the nested diagnostic context for the
- current thread in log messages, without any user intervention.
- Hence, even if a server is serving multiple clients
- simultaneously, the logs emanating from the same code (belonging to
- the same category) can still be distinguished because each client
- request will have a different NDC tag.
- <p><em>Unfortunately, unlike Java, C++ does not have platform
- independent multithreading support. Therefore, currently log4cpp is
- not multithread aware, it implicitly assumes only one thread exists,
- the main process thread. </em>
- **/
- class LOG4CPP_EXPORT NDC {
- static bool isUsedNDC;
- static const std::string emptyString;
- public:
- struct DiagnosticContext {
- DiagnosticContext(const std::string& message);
- DiagnosticContext(const std::string& message,
- const DiagnosticContext& parent);
- std::string message;
- std::string fullMessage;
- };
- //! cleans up
- static void shutdown();
- typedef std::vector<DiagnosticContext> ContextStack;
- /**
- Clear any nested disgnostic information if any. This method is
- useful in cases where the same thread can be potentially used
- over and over in different unrelated contexts.
- <p>This method is equivalent to calling the <code>setMaxDepth</code>
- method with a zero <code>maxDepth</code> argument.
- **/
- static void clear();
- /**
- Clone the diagnostic context for the current thread.
- <p>Internally a diagnostic context is represented as a stack. A
- given thread can supply the stack (i.e. diagnostic context) to a
- child thread so that the child can inherit the parent thread's
- diagnostic context.
- <p>The child thread uses the <code>inherit</code> method to
- inherit the parent's diagnostic context.
- @return Stack A clone of the current thread's diagnostic context.
- **/
- static ContextStack* cloneStack();
- /**
- Get the current diagnostic context string.
- @return the context string.
- **/
- static const std::string& get();
- /**
- Get the current nesting depth of this diagnostic context.
- @return the nesting depth
- **/
- static size_t getDepth();
- static void inherit(ContextStack* stack);
- /**
- Clients should call this method before leaving a diagnostic
- context.
- <p>The returned value is the value that was pushed last. If no
- context is available, then the empty string "" is returned.
- @return String The innermost diagnostic context.
- **/
- static std::string pop();
- /**
- Push new diagnostic context information for the current thread.
- <p>The contents of the <code>message</code> parameter is
- determined solely by the client.
- @param message The new diagnostic context information.
- **/
- static void push(const std::string& message);
- /**
- Set the maximum nesting depth for the current NDC. Curently NDCs
- do not enforce a maximum depth and consequentially this method
- has no effect.
- @param maxDepth the maximum nesting depth
- **/
- static void setMaxDepth(int maxDepth);
- /**
- Return the NDC for the current thread.
- @return the NDC for the current thread
- **/
- static NDC& getNDC();
- NDC();
- virtual ~NDC();
- public:
- virtual void _clear();
- virtual ContextStack* _cloneStack();
- virtual const std::string& _get() const;
- virtual size_t _getDepth() const;
- virtual void _inherit(ContextStack* stack);
- virtual std::string _pop();
- virtual void _push(const std::string& message);
- virtual void _setMaxDepth(int maxDepth);
- ContextStack _stack;
- };
- LOG4CPP_NS_END
- #endif // _LOG4CPP_NDC_HH
|