Overview

Packages

  • log4php
    • appenders
    • configurators
    • filters
    • helpers
    • layouts
    • pattern
    • renderers

Classes

  • Logger
  • LoggerAppender
  • LoggerAppenderPool
  • LoggerAutoloader
  • LoggerConfigurable
  • LoggerConfiguratorDefault
  • LoggerFilter
  • LoggerHierarchy
  • LoggerLayout
  • LoggerLevel
  • LoggerLocationInfo
  • LoggerLoggingEvent
  • LoggerMDC
  • LoggerNDC
  • LoggerReflectionUtils
  • LoggerRoot
  • LoggerThrowableInformation

Interfaces

  • LoggerConfigurator

Exceptions

  • LoggerException
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Licensed to the Apache Software Foundation (ASF) under one or more
  4:  * contributor license agreements. See the NOTICE file distributed with
  5:  * this work for additional information regarding copyright ownership.
  6:  * The ASF licenses this file to You under the Apache License, Version 2.0
  7:  * (the "License"); you may not use this file except in compliance with
  8:  * the License. You may obtain a copy of the License at
  9:  *
 10:  *     http://www.apache.org/licenses/LICENSE-2.0
 11:  *
 12:  * Unless required by applicable law or agreed to in writing, software
 13:  * distributed under the License is distributed on an "AS IS" BASIS,
 14:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15:  * See the License for the specific language governing permissions and
 16:  * limitations under the License.
 17:  *
 18:  * @package log4php
 19:  */
 20: 
 21: /**
 22:  * The NDC class implements <i>nested diagnostic contexts</i>.
 23:  * 
 24:  * NDC was defined by Neil Harrison in the article "Patterns for Logging
 25:  * Diagnostic Messages" part of the book <i>"Pattern Languages of
 26:  * Program Design 3"</i> edited by Martin et al.
 27:  *
 28:  * A Nested Diagnostic Context, or NDC in short, is an instrument
 29:  * to distinguish interleaved log output from different sources. Log
 30:  * output is typically interleaved when a server handles multiple
 31:  * clients near-simultaneously.
 32:  *
 33:  * This class is similar to the {@link LoggerMDC} class except that it is
 34:  * based on a stack instead of a map.
 35:  *
 36:  * Interleaved log output can still be meaningful if each log entry
 37:  * from different contexts had a distinctive stamp. This is where NDCs
 38:  * come into play.
 39:  *
 40:  * <b>Note that NDCs are managed on a per thread basis</b>. 
 41:  * 
 42:  * NDC operations such as {@link push()}, {@link pop()}, 
 43:  * {@link clear()}, {@link getDepth()} and {@link setMaxDepth()}
 44:  * affect the NDC of the <i>current</i> thread only. NDCs of other
 45:  * threads remain unaffected.
 46:  *
 47:  * For example, a servlet can build a per client request NDC
 48:  * consisting the clients host name and other information contained in
 49:  * the the request. <i>Cookies</i> are another source of distinctive
 50:  * information. To build an NDC one uses the {@link push()}
 51:  * operation.
 52:  * 
 53:  * Simply put,
 54:  *
 55:  * - Contexts can be nested.
 56:  * - When entering a context, call <kbd>LoggerNDC::push()</kbd>
 57:  *   As a side effect, if there is no nested diagnostic context for the
 58:  *   current thread, this method will create it.
 59:  * - When leaving a context, call <kbd>LoggerNDC::pop()</kbd>
 60:  * - <b>When exiting a thread make sure to call {@link remove()}</b>
 61:  *   
 62:  * There is no penalty for forgetting to match each
 63:  * <kbd>push</kbd> operation with a corresponding <kbd>pop</kbd>,
 64:  * except the obvious mismatch between the real application context
 65:  * and the context set in the NDC.
 66:  *
 67:  * If configured to do so, {@link LoggerPatternLayout} and {@link LoggerLayoutTTCC} 
 68:  * instances automatically retrieve the nested diagnostic
 69:  * context for the current thread without any user intervention.
 70:  * Hence, even if a servlet is serving multiple clients
 71:  * simultaneously, the logs emanating from the same code (belonging to
 72:  * the same category) can still be distinguished because each client
 73:  * request will have a different NDC tag.
 74:  *
 75:  * Example:
 76:  *  
 77:  * {@example ../../examples/php/ndc.php 19}<br>
 78:  *
 79:  * With the properties file:
 80:  * 
 81:  * {@example ../../examples/resources/ndc.properties 18}<br>
 82:  * 
 83:  * Will result in the following (notice the conn and client ids):
 84:  * 
 85:  * <pre>
 86:  * 2009-09-13 19:04:27 DEBUG root conn=1234: just received a new connection in src/examples/php/ndc.php at 23
 87:  * 2009-09-13 19:04:27 DEBUG root conn=1234 client=ab23: some more messages that can in src/examples/php/ndc.php at 25
 88:  * 2009-09-13 19:04:27 DEBUG root conn=1234 client=ab23: now related to a client in src/examples/php/ndc.php at 26
 89:  * 2009-09-13 19:04:27 DEBUG root : back and waiting for new connections in src/examples/php/ndc.php at 29
 90:  * </pre>
 91:  *  
 92:  * @version $Revision: 1350602 $
 93:  * @package log4php 
 94:  * @since 0.3
 95:  */
 96: class LoggerNDC {
 97:     
 98:     /** This is the repository of NDC stack */
 99:     private static $stack = array();
100:     
101:     /**
102:      * Clear any nested diagnostic information if any. This method is
103:      * useful in cases where the same thread can be potentially used
104:      * over and over in different unrelated contexts.
105:      *
106:      * <p>This method is equivalent to calling the {@link setMaxDepth()}
107:      * method with a zero <var>maxDepth</var> argument.
108:      */
109:     public static function clear() {
110:         self::$stack = array();
111:     }
112: 
113:     /**
114:      * Never use this method directly, use the {@link LoggerLoggingEvent::getNDC()} method instead.
115:      * @return array
116:      */
117:     public static function get() {
118:         return implode(' ', self::$stack);
119:     }
120:   
121:     /**
122:      * Get the current nesting depth of this diagnostic context.
123:      *
124:      * @see setMaxDepth()
125:      * @return integer
126:      */
127:     public static function getDepth() {
128:         return count(self::$stack);
129:     }
130: 
131:     /**
132:      * Clients should call this method before leaving a diagnostic
133:      * context.
134:      *
135:      * <p>The returned value is the value that was pushed last. If no
136:      * context is available, then the empty string "" is returned.</p>
137:      *
138:      * @return string The innermost diagnostic context.
139:      */
140:     public static function pop() {
141:         if(count(self::$stack) > 0) {
142:             return array_pop(self::$stack);
143:         } else {
144:             return '';
145:         }
146:     }
147: 
148:     /**
149:      * Looks at the last diagnostic context at the top of this NDC
150:      * without removing it.
151:      *
152:      * <p>The returned value is the value that was pushed last. If no
153:      * context is available, then the empty string "" is returned.</p>
154:      * @return string The innermost diagnostic context.
155:      */
156:     public static function peek() {
157:         if(count(self::$stack) > 0) {
158:             return end(self::$stack);
159:         } else {
160:             return '';
161:         }
162:     }
163:     
164:     /**
165:      * Push new diagnostic context information for the current thread.
166:      *
167:      * <p>The contents of the <var>message</var> parameter is
168:      * determined solely by the client.
169:      *  
170:      * @param string $message The new diagnostic context information.
171:      */
172:     public static function push($message) {
173:         array_push(self::$stack, (string)$message);
174:     }
175: 
176:     /**
177:      * Remove the diagnostic context for this thread.
178:      */
179:     public static function remove() {
180:         LoggerNDC::clear();
181:     }
182: 
183:     /**
184:      * Set maximum depth of this diagnostic context. If the current
185:      * depth is smaller or equal to <var>maxDepth</var>, then no
186:      * action is taken.
187:      *
188:      * <p>This method is a convenient alternative to multiple 
189:      * {@link pop()} calls. Moreover, it is often the case that at 
190:      * the end of complex call sequences, the depth of the NDC is
191:      * unpredictable. The {@link setMaxDepth()} method circumvents
192:      * this problem.
193:      *
194:      * @param integer $maxDepth
195:      * @see getDepth()
196:      */
197:     public static function setMaxDepth($maxDepth) {
198:         $maxDepth = (int)$maxDepth;
199:         if(LoggerNDC::getDepth() > $maxDepth) {
200:             self::$stack = array_slice(self::$stack, 0, $maxDepth);
201:         }
202:     }
203: }
204: 
Apache log4php API documentation generated by ApiGen 2.8.0