| 1 | /*
|
|---|
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more
|
|---|
| 3 | * contributor license agreements. See the NOTICE file distributed with
|
|---|
| 4 | * this work for additional information regarding copyright ownership.
|
|---|
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0
|
|---|
| 6 | * (the "License"); you may not use this file except in compliance with
|
|---|
| 7 | * the License. You may obtain a copy of the License at
|
|---|
| 8 | *
|
|---|
| 9 | * http://www.apache.org/licenses/LICENSE-2.0
|
|---|
| 10 | *
|
|---|
| 11 | * Unless required by applicable law or agreed to in writing, software
|
|---|
| 12 | * distributed under the License is distributed on an "AS IS" BASIS,
|
|---|
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|---|
| 14 | * See the License for the specific language governing permissions and
|
|---|
| 15 | * limitations under the License.
|
|---|
| 16 | */
|
|---|
| 17 |
|
|---|
| 18 | #ifndef _LOG4CXX_NDC_H
|
|---|
| 19 | #define _LOG4CXX_NDC_H
|
|---|
| 20 |
|
|---|
| 21 | #if defined(_MSC_VER)
|
|---|
| 22 | #pragma warning ( push )
|
|---|
| 23 | #pragma warning ( disable: 4231 4251 4275 4786 )
|
|---|
| 24 | #endif
|
|---|
| 25 |
|
|---|
| 26 | #include <log4cxx/log4cxx.h>
|
|---|
| 27 | #include <log4cxx/logstring.h>
|
|---|
| 28 | #include <stack>
|
|---|
| 29 |
|
|---|
| 30 | namespace log4cxx
|
|---|
| 31 | {
|
|---|
| 32 | /**
|
|---|
| 33 | the ndc class implements <i>nested diagnostic contexts</i> as
|
|---|
| 34 | defined by neil harrison in the article "patterns for logging
|
|---|
| 35 | diagnostic messages" part of the book "<i>pattern languages of
|
|---|
| 36 | program design 3</i>" edited by martin et al.
|
|---|
| 37 |
|
|---|
| 38 | <p>a nested diagnostic context, or ndc in short, is an instrument
|
|---|
| 39 | to distinguish interleaved log output from different sources. log
|
|---|
| 40 | output is typically interleaved when a server handles multiple
|
|---|
| 41 | clients near-simultaneously.
|
|---|
| 42 |
|
|---|
| 43 | <p>interleaved log output can still be meaningful if each log entry
|
|---|
| 44 | from different contexts had a distinctive stamp. this is where ndcs
|
|---|
| 45 | come into play.
|
|---|
| 46 |
|
|---|
| 47 | <p><em><b>note that ndcs are managed on a per thread
|
|---|
| 48 | basis</b></em>. ndc operations such as #push,
|
|---|
| 49 | #pop, #clear and #getDepth
|
|---|
| 50 | affect the ndc of the <em>current</em> thread only. ndcs of other
|
|---|
| 51 | threads remain unaffected.
|
|---|
| 52 |
|
|---|
| 53 | <p>for example, a servlet can build a per client request ndc
|
|---|
| 54 | consisting the clients host name and other information contained in
|
|---|
| 55 | the the request. <em>cookies</em> are another source of distinctive
|
|---|
| 56 | information. to build an ndc one uses the #push
|
|---|
| 57 | operation. simply put,
|
|---|
| 58 |
|
|---|
| 59 | <p><ul>
|
|---|
| 60 | <li>contexts can be nested.
|
|---|
| 61 |
|
|---|
| 62 | <p><li>when entering a context, call <code>ndc.push</code>. as a
|
|---|
| 63 | side effect, if there is no nested diagnostic context for the
|
|---|
| 64 | current thread, this method will create it.
|
|---|
| 65 |
|
|---|
| 66 | <p><li>when leaving a context, call <code>ndc.pop</code>.
|
|---|
| 67 |
|
|---|
| 68 | <p><li><b>when exiting a thread make sure to call #remove
|
|---|
| 69 | </b>.
|
|---|
| 70 | </ul>
|
|---|
| 71 |
|
|---|
| 72 | <p>there is no penalty for forgetting to match each
|
|---|
| 73 | <code>push</code> operation with a corresponding <code>pop</code>,
|
|---|
| 74 | except the obvious mismatch between the real application context
|
|---|
| 75 | and the context set in the ndc.
|
|---|
| 76 |
|
|---|
| 77 | <p>if configured to do so, PatternLayout and
|
|---|
| 78 | TTCCLayout instances automatically retrieve the nested diagnostic
|
|---|
| 79 | context for the current thread without any user intervention.
|
|---|
| 80 | hence, even if a servlet is serving multiple clients
|
|---|
| 81 | simultaneously, the logs emanating from the same code (belonging to
|
|---|
| 82 | the same logger) can still be distinguished because each client
|
|---|
| 83 | request will have a different ndc tag.
|
|---|
| 84 |
|
|---|
| 85 | <p>heavy duty systems should call the #remove method when
|
|---|
| 86 | leaving the run method of a thread. this ensures that the memory
|
|---|
| 87 | used by the thread can be freed by the java garbage
|
|---|
| 88 | collector. there is a mechanism to lazily remove references to dead
|
|---|
| 89 | threads. in practice, this means that you can be a little sloppy
|
|---|
| 90 | and sometimes forget to call #remove before exiting a
|
|---|
| 91 | thread.
|
|---|
| 92 |
|
|---|
| 93 | */
|
|---|
| 94 | class LOG4CXX_EXPORT NDC
|
|---|
| 95 | {
|
|---|
| 96 | public:
|
|---|
| 97 | /**
|
|---|
| 98 | * Pair of Message and FullMessage.
|
|---|
| 99 | */
|
|---|
| 100 | typedef std::pair<LogString, LogString> DiagnosticContext;
|
|---|
| 101 | typedef std::stack<DiagnosticContext> Stack;
|
|---|
| 102 |
|
|---|
| 103 | /**
|
|---|
| 104 | Creates a nested diagnostic context.
|
|---|
| 105 | Since java performs no automatic cleanup of objects when a
|
|---|
| 106 | scope is left, in log4j push() and pop() must be used
|
|---|
| 107 | to manage the NDC. For convenience, log4cxx provides
|
|---|
| 108 | an NDC constructor and destructor which simply call the push() and
|
|---|
| 109 | pop() methods, allowing for automatic cleanup when the current
|
|---|
| 110 | scope ends.
|
|---|
| 111 |
|
|---|
| 112 | @param message The new diagnostic context information.
|
|---|
| 113 | @see The #push method.
|
|---|
| 114 | */
|
|---|
| 115 | NDC(const std::string& message);
|
|---|
| 116 |
|
|---|
| 117 | /**
|
|---|
| 118 | Removes the topmost element from the NDC stack.
|
|---|
| 119 |
|
|---|
| 120 | @see The #pop method.
|
|---|
| 121 | */
|
|---|
| 122 | ~NDC();
|
|---|
| 123 |
|
|---|
| 124 | /**
|
|---|
| 125 | Clear any nested diagnostic information if any. This method is
|
|---|
| 126 | useful in cases where the same thread can be potentially used
|
|---|
| 127 | over and over in different unrelated contexts.
|
|---|
| 128 | */
|
|---|
| 129 | static void clear();
|
|---|
| 130 |
|
|---|
| 131 | /**
|
|---|
| 132 | Clone the diagnostic context for the current thread.
|
|---|
| 133 | <p>Internally a diagnostic context is represented as a stack. A
|
|---|
| 134 | given thread can supply the stack (i.e. diagnostic context) to a
|
|---|
| 135 | child thread so that the child can inherit the parent thread's
|
|---|
| 136 | diagnostic context.
|
|---|
| 137 | <p>The child thread uses the #inherit method to
|
|---|
| 138 | inherit the parent's diagnostic context.
|
|---|
| 139 | <p>If not passed to #inherit, returned stack should be deleted by caller.
|
|---|
| 140 | @return Stack A clone of the current thread's diagnostic context, will not be null.
|
|---|
| 141 | */
|
|---|
| 142 | static Stack * cloneStack();
|
|---|
| 143 |
|
|---|
| 144 | /**
|
|---|
| 145 | Inherit the diagnostic context of another thread.
|
|---|
| 146 | <p>The parent thread can obtain a reference to its diagnostic
|
|---|
| 147 | context using the #cloneStack method. It should
|
|---|
| 148 | communicate this information to its child so that it may inherit
|
|---|
| 149 | the parent's diagnostic context.
|
|---|
| 150 | <p>The parent's diagnostic context is cloned before being
|
|---|
| 151 | inherited. In other words, once inherited, the two diagnostic
|
|---|
| 152 | contexts can be managed independently.
|
|---|
| 153 | @param stack The diagnostic context of the parent thread,
|
|---|
| 154 | will be deleted during call. If NULL, NDC will not be modified.
|
|---|
| 155 | */
|
|---|
| 156 | static void inherit(Stack * stack);
|
|---|
| 157 |
|
|---|
| 158 | /**
|
|---|
| 159 | * Get the current value of the NDC of the
|
|---|
| 160 | * currrent thread.
|
|---|
| 161 | * @param dest destination to which to append content of NDC.
|
|---|
| 162 | * @return true if NDC is set.
|
|---|
| 163 | */
|
|---|
| 164 | static bool get(LogString& dest);
|
|---|
| 165 |
|
|---|
| 166 | /**
|
|---|
| 167 | Get the current nesting depth of this diagnostic context.
|
|---|
| 168 | */
|
|---|
| 169 | static int getDepth();
|
|---|
| 170 |
|
|---|
| 171 |
|
|---|
| 172 | /**
|
|---|
| 173 | * Tests if the NDC is empty.
|
|---|
| 174 | */
|
|---|
| 175 | static bool empty();
|
|---|
| 176 |
|
|---|
| 177 | /**
|
|---|
| 178 | Pop top value off stack.
|
|---|
| 179 | @return top value.
|
|---|
| 180 | */
|
|---|
| 181 | static LogString pop();
|
|---|
| 182 | /**
|
|---|
| 183 | Pop top value off stack.
|
|---|
| 184 | @param buf to which top value is appended.
|
|---|
| 185 | @return true if NDC contained at least one value.
|
|---|
| 186 | */
|
|---|
| 187 | static bool pop(std::string& buf);
|
|---|
| 188 |
|
|---|
| 189 | /**
|
|---|
| 190 | Looks at the last diagnostic context at the top of this NDC
|
|---|
| 191 | without removing it.
|
|---|
| 192 | <p>The returned value is the value that was pushed last. If no
|
|---|
| 193 | context is available, then the empty string "" is returned.
|
|---|
| 194 | @return String The innermost diagnostic context.
|
|---|
| 195 | */
|
|---|
| 196 | static LogString peek();
|
|---|
| 197 | /**
|
|---|
| 198 | Get top value without removing value.
|
|---|
| 199 | @param buf to which top value is appended.
|
|---|
| 200 | @return true if NDC contained at least one value.
|
|---|
| 201 | */
|
|---|
| 202 | static bool peek(std::string& buf);
|
|---|
| 203 |
|
|---|
| 204 | /**
|
|---|
| 205 | Push new diagnostic context information for the current thread.
|
|---|
| 206 | <p>The contents of the <code>message</code> parameter is
|
|---|
| 207 | determined solely by the client.
|
|---|
| 208 | @param message The new diagnostic context information.
|
|---|
| 209 | */
|
|---|
| 210 | static void push(const std::string& message);
|
|---|
| 211 | /**
|
|---|
| 212 | Push new diagnostic context information for the current thread.
|
|---|
| 213 | <p>The contents of the <code>message</code> parameter is
|
|---|
| 214 | determined solely by the client.
|
|---|
| 215 | @param message The new diagnostic context information.
|
|---|
| 216 | */
|
|---|
| 217 | static void pushLS(const LogString& message);
|
|---|
| 218 |
|
|---|
| 219 | /**
|
|---|
| 220 | Remove the diagnostic context for this thread.
|
|---|
| 221 | <p>Each thread that created a diagnostic context by calling
|
|---|
| 222 | #push should call this method before exiting. Otherwise,
|
|---|
| 223 | the memory used by the <b>thread</b> cannot be reclaimed by the
|
|---|
| 224 | VM.
|
|---|
| 225 | <p>As this is such an important problem in heavy duty systems and
|
|---|
| 226 | because it is difficult to always guarantee that the remove
|
|---|
| 227 | method is called before exiting a thread, this method has been
|
|---|
| 228 | augmented to lazily remove references to dead threads. In
|
|---|
| 229 | practice, this means that you can be a little sloppy and
|
|---|
| 230 | occasionally forget to call #remove before exiting a
|
|---|
| 231 | thread. However, you must call <code>remove</code> sometime. If
|
|---|
| 232 | you never call it, then your application is sure to run out of
|
|---|
| 233 | memory.
|
|---|
| 234 | */
|
|---|
| 235 | static void remove();
|
|---|
| 236 |
|
|---|
| 237 | #if LOG4CXX_WCHAR_T_API
|
|---|
| 238 | /**
|
|---|
| 239 | Creates a nested diagnostic context.
|
|---|
| 240 | Since java performs no automatic cleanup of objects when a
|
|---|
| 241 | scope is left, in log4j push() and pop() must be used
|
|---|
| 242 | to manage the NDC. For convenience, log4cxx provides
|
|---|
| 243 | an NDC constructor and destructor which simply call the push() and
|
|---|
| 244 | pop() methods, allowing for automatic cleanup when the current
|
|---|
| 245 | scope ends.
|
|---|
| 246 |
|
|---|
| 247 | @param message The new diagnostic context information.
|
|---|
| 248 | @see The #push method.
|
|---|
| 249 | */
|
|---|
| 250 | NDC(const std::wstring& message);
|
|---|
| 251 | /**
|
|---|
| 252 | Push new diagnostic context information for the current thread.
|
|---|
| 253 | <p>The contents of the <code>message</code> parameter is
|
|---|
| 254 | determined solely by the client.
|
|---|
| 255 | @param message The new diagnostic context information.
|
|---|
| 256 | */
|
|---|
| 257 | static void push(const std::wstring& message);
|
|---|
| 258 | /**
|
|---|
| 259 | * Appends the current NDC content to the provided string.
|
|---|
| 260 | * @param dst destination.
|
|---|
| 261 | * @return true if NDC value set.
|
|---|
| 262 | */
|
|---|
| 263 | static bool peek(std::wstring& dst);
|
|---|
| 264 | /**
|
|---|
| 265 | * Appends the current NDC content to the provided string and removes the value from the NDC.
|
|---|
| 266 | * @param dst destination.
|
|---|
| 267 | * @return true if NDC value set.
|
|---|
| 268 | */
|
|---|
| 269 | static bool pop(std::wstring& dst);
|
|---|
| 270 | #endif
|
|---|
| 271 | #if LOG4CXX_UNICHAR_API
|
|---|
| 272 | /**
|
|---|
| 273 | Creates a nested diagnostic context.
|
|---|
| 274 | Since java performs no automatic cleanup of objects when a
|
|---|
| 275 | scope is left, in log4j push() and pop() must be used
|
|---|
| 276 | to manage the NDC. For convenience, log4cxx provides
|
|---|
| 277 | an NDC constructor and destructor which simply call the push() and
|
|---|
| 278 | pop() methods, allowing for automatic cleanup when the current
|
|---|
| 279 | scope ends.
|
|---|
| 280 |
|
|---|
| 281 | @param message The new diagnostic context information.
|
|---|
| 282 | @see The #push method.
|
|---|
| 283 | */
|
|---|
| 284 | NDC(const std::basic_string<UniChar>& message);
|
|---|
| 285 | /**
|
|---|
| 286 | Push new diagnostic context information for the current thread.
|
|---|
| 287 | <p>The contents of the <code>message</code> parameter is
|
|---|
| 288 | determined solely by the client.
|
|---|
| 289 | @param message The new diagnostic context information.
|
|---|
| 290 | */
|
|---|
| 291 | static void push(const std::basic_string<UniChar>& message);
|
|---|
| 292 | /**
|
|---|
| 293 | * Appends the current NDC content to the provided string.
|
|---|
| 294 | * @param dst destination.
|
|---|
| 295 | * @return true if NDC value set.
|
|---|
| 296 | */
|
|---|
| 297 | static bool peek(std::basic_string<UniChar>& dst);
|
|---|
| 298 | /**
|
|---|
| 299 | * Appends the current NDC content to the provided string and removes the value from the NDC.
|
|---|
| 300 | * @param dst destination.
|
|---|
| 301 | * @return true if NDC value set.
|
|---|
| 302 | */
|
|---|
| 303 | static bool pop(std::basic_string<UniChar>& dst);
|
|---|
| 304 | #endif
|
|---|
| 305 | #if LOG4CXX_CFSTRING_API
|
|---|
| 306 | /**
|
|---|
| 307 | Creates a nested diagnostic context.
|
|---|
| 308 | Since java performs no automatic cleanup of objects when a
|
|---|
| 309 | scope is left, in log4j push() and pop() must be used
|
|---|
| 310 | to manage the NDC. For convenience, log4cxx provides
|
|---|
| 311 | an NDC constructor and destructor which simply call the push() and
|
|---|
| 312 | pop() methods, allowing for automatic cleanup when the current
|
|---|
| 313 | scope ends.
|
|---|
| 314 |
|
|---|
| 315 | @param message The new diagnostic context information.
|
|---|
| 316 | @see The #push method.
|
|---|
| 317 | */
|
|---|
| 318 | NDC(const CFStringRef& message);
|
|---|
| 319 | /**
|
|---|
| 320 | Push new diagnostic context information for the current thread.
|
|---|
| 321 | <p>The contents of the <code>message</code> parameter is
|
|---|
| 322 | determined solely by the client.
|
|---|
| 323 | @param message The new diagnostic context information.
|
|---|
| 324 | */
|
|---|
| 325 | static void push(const CFStringRef& message);
|
|---|
| 326 | /**
|
|---|
| 327 | * Gets the current NDC value.
|
|---|
| 328 | * @param dst destination.
|
|---|
| 329 | * @return true if NDC value set.
|
|---|
| 330 | */
|
|---|
| 331 | static bool peek(CFStringRef& dst);
|
|---|
| 332 | /**
|
|---|
| 333 | * Gets and removes the current NDC value.
|
|---|
| 334 | * @param dst destination.
|
|---|
| 335 | * @return true if NDC value set.
|
|---|
| 336 | */
|
|---|
| 337 | static bool pop(CFStringRef& dst);
|
|---|
| 338 | #endif
|
|---|
| 339 |
|
|---|
| 340 | private:
|
|---|
| 341 | NDC(const NDC&);
|
|---|
| 342 | NDC& operator=(const NDC&);
|
|---|
| 343 | static LogString& getMessage(DiagnosticContext& ctx);
|
|---|
| 344 | static LogString& getFullMessage(DiagnosticContext& ctx);
|
|---|
| 345 | }; // class NDC;
|
|---|
| 346 | } // namespace log4cxx
|
|---|
| 347 |
|
|---|
| 348 | #if defined(_MSC_VER)
|
|---|
| 349 | #pragma warning (pop)
|
|---|
| 350 | #endif
|
|---|
| 351 |
|
|---|
| 352 |
|
|---|
| 353 | #endif // _LOG4CXX_NDC_H
|
|---|