[2] | 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
|
---|