354 lines
15 KiB
C++
354 lines
15 KiB
C++
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef _LOG4CXX_NDC_H
|
|
#define _LOG4CXX_NDC_H
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma warning ( push )
|
|
#pragma warning ( disable: 4231 4251 4275 4786 )
|
|
#endif
|
|
|
|
#include <log4cxx/log4cxx.h>
|
|
#include <log4cxx/logstring.h>
|
|
#include <stack>
|
|
|
|
namespace log4cxx
|
|
{
|
|
/**
|
|
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-simultaneously.
|
|
|
|
<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 #push,
|
|
#pop, #clear and #getDepth
|
|
affect the ndc of the <em>current</em> thread only. ndcs of other
|
|
threads remain unaffected.
|
|
|
|
<p>for example, a servlet can build a per client request ndc
|
|
consisting the clients host name and other information contained in
|
|
the the request. <em>cookies</em> are another source of distinctive
|
|
information. to build an ndc one uses the #push
|
|
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>.
|
|
|
|
<p><li><b>when exiting a thread make sure to call #remove
|
|
</b>.
|
|
</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>if configured to do so, PatternLayout and
|
|
TTCCLayout instances automatically retrieve the nested diagnostic
|
|
context for the current thread without any user intervention.
|
|
hence, even if a servlet is serving multiple clients
|
|
simultaneously, the logs emanating from the same code (belonging to
|
|
the same logger) can still be distinguished because each client
|
|
request will have a different ndc tag.
|
|
|
|
<p>heavy duty systems should call the #remove method when
|
|
leaving the run method of a thread. this ensures that the memory
|
|
used by the thread can be freed by the java garbage
|
|
collector. there is a mechanism to lazily remove references to dead
|
|
threads. in practice, this means that you can be a little sloppy
|
|
and sometimes forget to call #remove before exiting a
|
|
thread.
|
|
|
|
*/
|
|
class LOG4CXX_EXPORT NDC
|
|
{
|
|
public:
|
|
/**
|
|
* Pair of Message and FullMessage.
|
|
*/
|
|
typedef std::pair<LogString, LogString> DiagnosticContext;
|
|
typedef std::stack<DiagnosticContext> Stack;
|
|
|
|
/**
|
|
Creates a nested diagnostic context.
|
|
Since java performs no automatic cleanup of objects when a
|
|
scope is left, in log4j push() and pop() must be used
|
|
to manage the NDC. For convenience, log4cxx provides
|
|
an NDC constructor and destructor which simply call the push() and
|
|
pop() methods, allowing for automatic cleanup when the current
|
|
scope ends.
|
|
|
|
@param message The new diagnostic context information.
|
|
@see The #push method.
|
|
*/
|
|
NDC(const std::string& message);
|
|
|
|
/**
|
|
Removes the topmost element from the NDC stack.
|
|
|
|
@see The #pop method.
|
|
*/
|
|
~NDC();
|
|
|
|
/**
|
|
Clear any nested diagnostic information if any. This method is
|
|
useful in cases where the same thread can be potentially used
|
|
over and over in different unrelated contexts.
|
|
*/
|
|
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 #inherit method to
|
|
inherit the parent's diagnostic context.
|
|
<p>If not passed to #inherit, returned stack should be deleted by caller.
|
|
@return Stack A clone of the current thread's diagnostic context, will not be null.
|
|
*/
|
|
static Stack * cloneStack();
|
|
|
|
/**
|
|
Inherit the diagnostic context of another thread.
|
|
<p>The parent thread can obtain a reference to its diagnostic
|
|
context using the #cloneStack method. It should
|
|
communicate this information to its child so that it may inherit
|
|
the parent's diagnostic context.
|
|
<p>The parent's diagnostic context is cloned before being
|
|
inherited. In other words, once inherited, the two diagnostic
|
|
contexts can be managed independently.
|
|
@param stack The diagnostic context of the parent thread,
|
|
will be deleted during call. If NULL, NDC will not be modified.
|
|
*/
|
|
static void inherit(Stack * stack);
|
|
|
|
/**
|
|
* Get the current value of the NDC of the
|
|
* currrent thread.
|
|
* @param dest destination to which to append content of NDC.
|
|
* @return true if NDC is set.
|
|
*/
|
|
static bool get(LogString& dest);
|
|
|
|
/**
|
|
Get the current nesting depth of this diagnostic context.
|
|
*/
|
|
static int getDepth();
|
|
|
|
|
|
/**
|
|
* Tests if the NDC is empty.
|
|
*/
|
|
static bool empty();
|
|
|
|
/**
|
|
Pop top value off stack.
|
|
@return top value.
|
|
*/
|
|
static LogString pop();
|
|
/**
|
|
Pop top value off stack.
|
|
@param buf to which top value is appended.
|
|
@return true if NDC contained at least one value.
|
|
*/
|
|
static bool pop(std::string& buf);
|
|
|
|
/**
|
|
Looks at the last diagnostic context at the top of this NDC
|
|
without removing it.
|
|
<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 LogString peek();
|
|
/**
|
|
Get top value without removing value.
|
|
@param buf to which top value is appended.
|
|
@return true if NDC contained at least one value.
|
|
*/
|
|
static bool peek(std::string& buf);
|
|
|
|
/**
|
|
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);
|
|
/**
|
|
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 pushLS(const LogString& message);
|
|
|
|
/**
|
|
Remove the diagnostic context for this thread.
|
|
<p>Each thread that created a diagnostic context by calling
|
|
#push should call this method before exiting. Otherwise,
|
|
the memory used by the <b>thread</b> cannot be reclaimed by the
|
|
VM.
|
|
<p>As this is such an important problem in heavy duty systems and
|
|
because it is difficult to always guarantee that the remove
|
|
method is called before exiting a thread, this method has been
|
|
augmented to lazily remove references to dead threads. In
|
|
practice, this means that you can be a little sloppy and
|
|
occasionally forget to call #remove before exiting a
|
|
thread. However, you must call <code>remove</code> sometime. If
|
|
you never call it, then your application is sure to run out of
|
|
memory.
|
|
*/
|
|
static void remove();
|
|
|
|
#if LOG4CXX_WCHAR_T_API
|
|
/**
|
|
Creates a nested diagnostic context.
|
|
Since java performs no automatic cleanup of objects when a
|
|
scope is left, in log4j push() and pop() must be used
|
|
to manage the NDC. For convenience, log4cxx provides
|
|
an NDC constructor and destructor which simply call the push() and
|
|
pop() methods, allowing for automatic cleanup when the current
|
|
scope ends.
|
|
|
|
@param message The new diagnostic context information.
|
|
@see The #push method.
|
|
*/
|
|
NDC(const std::wstring& message);
|
|
/**
|
|
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::wstring& message);
|
|
/**
|
|
* Appends the current NDC content to the provided string.
|
|
* @param dst destination.
|
|
* @return true if NDC value set.
|
|
*/
|
|
static bool peek(std::wstring& dst);
|
|
/**
|
|
* Appends the current NDC content to the provided string and removes the value from the NDC.
|
|
* @param dst destination.
|
|
* @return true if NDC value set.
|
|
*/
|
|
static bool pop(std::wstring& dst);
|
|
#endif
|
|
#if LOG4CXX_UNICHAR_API
|
|
/**
|
|
Creates a nested diagnostic context.
|
|
Since java performs no automatic cleanup of objects when a
|
|
scope is left, in log4j push() and pop() must be used
|
|
to manage the NDC. For convenience, log4cxx provides
|
|
an NDC constructor and destructor which simply call the push() and
|
|
pop() methods, allowing for automatic cleanup when the current
|
|
scope ends.
|
|
|
|
@param message The new diagnostic context information.
|
|
@see The #push method.
|
|
*/
|
|
NDC(const std::basic_string<UniChar>& message);
|
|
/**
|
|
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::basic_string<UniChar>& message);
|
|
/**
|
|
* Appends the current NDC content to the provided string.
|
|
* @param dst destination.
|
|
* @return true if NDC value set.
|
|
*/
|
|
static bool peek(std::basic_string<UniChar>& dst);
|
|
/**
|
|
* Appends the current NDC content to the provided string and removes the value from the NDC.
|
|
* @param dst destination.
|
|
* @return true if NDC value set.
|
|
*/
|
|
static bool pop(std::basic_string<UniChar>& dst);
|
|
#endif
|
|
#if LOG4CXX_CFSTRING_API
|
|
/**
|
|
Creates a nested diagnostic context.
|
|
Since java performs no automatic cleanup of objects when a
|
|
scope is left, in log4j push() and pop() must be used
|
|
to manage the NDC. For convenience, log4cxx provides
|
|
an NDC constructor and destructor which simply call the push() and
|
|
pop() methods, allowing for automatic cleanup when the current
|
|
scope ends.
|
|
|
|
@param message The new diagnostic context information.
|
|
@see The #push method.
|
|
*/
|
|
NDC(const CFStringRef& message);
|
|
/**
|
|
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 CFStringRef& message);
|
|
/**
|
|
* Gets the current NDC value.
|
|
* @param dst destination.
|
|
* @return true if NDC value set.
|
|
*/
|
|
static bool peek(CFStringRef& dst);
|
|
/**
|
|
* Gets and removes the current NDC value.
|
|
* @param dst destination.
|
|
* @return true if NDC value set.
|
|
*/
|
|
static bool pop(CFStringRef& dst);
|
|
#endif
|
|
|
|
private:
|
|
NDC(const NDC&);
|
|
NDC& operator=(const NDC&);
|
|
static LogString& getMessage(DiagnosticContext& ctx);
|
|
static LogString& getFullMessage(DiagnosticContext& ctx);
|
|
}; // class NDC;
|
|
} // namespace log4cxx
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma warning (pop)
|
|
#endif
|
|
|
|
|
|
#endif // _LOG4CXX_NDC_H
|