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 internal representation of logging event. 23 * 24 * @version $Revision: 832662 $ 25 * @package log4php 26 */ 27class LoggerLoggingEvent { 28 29 private static $startTime; 30 31 /** 32 * @var string Fully Qualified Class Name of the calling category class. 33 */ 34 private $fqcn; 35 36 /** 37 * @var Logger reference 38 */ 39 private $logger = null; 40 41 /** 42 * The category (logger) name. 43 * This field will be marked as private in future 44 * releases. Please do not access it directly. 45 * Use the {@link getLoggerName()} method instead. 46 * @deprecated 47 */ 48 private $categoryName; 49 50 /** 51 * Level of logging event. 52 * <p> This field should not be accessed directly. You shoud use the 53 * {@link getLevel()} method instead. 54 * 55 * @deprecated 56 * @var LoggerLevel 57 */ 58 protected $level; 59 60 /** 61 * @var string The nested diagnostic context (NDC) of logging event. 62 */ 63 private $ndc; 64 65 /** 66 * Have we tried to do an NDC lookup? If we did, there is no need 67 * to do it again. Note that its value is always false when 68 * serialized. Thus, a receiving SocketNode will never use it's own 69 * (incorrect) NDC. See also writeObject method. 70 * @var boolean 71 */ 72 private $ndcLookupRequired = true; 73 74 /** 75 * Have we tried to do an MDC lookup? If we did, there is no need 76 * to do it again. Note that its value is always false when 77 * serialized. See also the getMDC and getMDCCopy methods. 78 * @var boolean 79 */ 80 private $mdcCopyLookupRequired = true; 81 82 /** 83 * @var mixed The application supplied message of logging event. 84 */ 85 private $message; 86 87 /** 88 * The application supplied message rendered through the log4php 89 * objet rendering mechanism. At present renderedMessage == message. 90 * @var string 91 */ 92 private $renderedMessage = null; 93 94 /** 95 * The name of thread in which this logging event was generated. 96 * log4php saves here the process id via {@link PHP_MANUAL#getmypid getmypid()} 97 * @var mixed 98 */ 99 private $threadName = null; 100 101 /** 102 * The number of seconds elapsed from 1/1/1970 until logging event 103 * was created plus microseconds if available. 104 * @var float 105 */ 106 public $timeStamp; 107 108 /** 109 * @var LoggerLocationInfo Location information for the caller. 110 */ 111 private $locationInfo = null; 112 113 /** 114 * Instantiate a LoggingEvent from the supplied parameters. 115 * 116 * <p>Except {@link $timeStamp} all the other fields of 117 * LoggerLoggingEvent are filled when actually needed. 118 * 119 * @param string $fqcn name of the caller class. 120 * @param mixed $logger The {@link Logger} category of this event or the logger name. 121 * @param LoggerLevel $priority The level of this event. 122 * @param mixed $message The message of this event. 123 * @param integer $timeStamp the timestamp of this logging event. 124 */ 125 public function __construct($fqcn, $logger, $priority, $message, $timeStamp = null) { 126 $this->fqcn = $fqcn; 127 if($logger instanceof Logger) { 128 $this->logger = $logger; 129 $this->categoryName = $logger->getName(); 130 } else { 131 $this->categoryName = strval($logger); 132 } 133 $this->level = $priority; 134 $this->message = $message; 135 if($timeStamp !== null && is_float($timeStamp)) { 136 $this->timeStamp = $timeStamp; 137 } else { 138 if(function_exists('microtime')) { 139 // get microtime as float 140 $this->timeStamp = microtime(true); 141 } else { 142 $this->timeStamp = floatval(time()); 143 } 144 } 145 } 146 147 /** 148 * Set the location information for this logging event. The collected 149 * information is cached for future use. 150 * 151 * <p>This method uses {@link PHP_MANUAL#debug_backtrace debug_backtrace()} function (if exists) 152 * to collect informations about caller.</p> 153 * <p>It only recognize informations generated by {@link Logger} and its subclasses.</p> 154 * @return LoggerLocationInfo 155 */ 156 public function getLocationInformation() { 157 if($this->locationInfo === null) { 158 159 $locationInfo = array(); 160 161 if(function_exists('debug_backtrace')) { 162 $trace = debug_backtrace(); 163 $prevHop = null; 164 // make a downsearch to identify the caller 165 $hop = array_pop($trace); 166 while($hop !== null) { 167 if(isset($hop['class'])) { 168 // we are sometimes in functions = no class available: avoid php warning here 169 $className = strtolower($hop['class']); 170 if(!empty($className) and ($className == 'logger' or $className == 'loggercategory' or 171 strtolower(get_parent_class($className)) == 'logger' or 172 strtolower(get_parent_class($className)) == 'loggercategory')) { 173 $locationInfo['line'] = $hop['line']; 174 $locationInfo['file'] = $hop['file']; 175 break; 176 } 177 } 178 $prevHop = $hop; 179 $hop = array_pop($trace); 180 } 181 $locationInfo['class'] = isset($prevHop['class']) ? $prevHop['class'] : 'main'; 182 if(isset($prevHop['function']) and 183 $prevHop['function'] !== 'include' and 184 $prevHop['function'] !== 'include_once' and 185 $prevHop['function'] !== 'require' and 186 $prevHop['function'] !== 'require_once') { 187 188 $locationInfo['function'] = $prevHop['function']; 189 } else { 190 $locationInfo['function'] = 'main'; 191 } 192 } 193 194 $this->locationInfo = new LoggerLocationInfo($locationInfo, $this->fqcn); 195 } 196 return $this->locationInfo; 197 } 198 199 /** 200 * Return the level of this event. Use this form instead of directly 201 * accessing the {@link $level} field. 202 * @return LoggerLevel 203 */ 204 public function getLevel() { 205 return $this->level; 206 } 207 208 /** 209 * Return the name of the logger. Use this form instead of directly 210 * accessing the {@link $categoryName} field. 211 * @return string 212 */ 213 public function getLoggerName() { 214 return $this->categoryName; 215 } 216 217 /** 218 * Return the message for this logging event. 219 * 220 * <p>Before serialization, the returned object is the message 221 * passed by the user to generate the logging event. After 222 * serialization, the returned value equals the String form of the 223 * message possibly after object rendering. 224 * @return mixed 225 */ 226 public function getMessage() { 227 if($this->message !== null) { 228 return $this->message; 229 } else { 230 return $this->getRenderedMessage(); 231 } 232 } 233 234 /** 235 * This method returns the NDC for this event. It will return the 236 * correct content even if the event was generated in a different 237 * thread or even on a different machine. The {@link LoggerNDC::get()} method 238 * should <b>never</b> be called directly. 239 * @return string 240 */ 241 public function getNDC() { 242 if($this->ndcLookupRequired) { 243 $this->ndcLookupRequired = false; 244 $this->ndc = implode(' ', LoggerNDC::get()); 245 } 246 return $this->ndc; 247 } 248 249 /** 250 * Returns the the context corresponding to the <code>key</code> 251 * parameter. 252 * @return string 253 */ 254 public function getMDC($key) { 255 return LoggerMDC::get($key); 256 } 257 258 /** 259 * Render message. 260 * @return string 261 */ 262 public function getRenderedMessage() { 263 if($this->renderedMessage === null and $this->message !== null) { 264 if(is_string($this->message)) { 265 $this->renderedMessage = $this->message; 266 } else { 267 // $this->logger might be null or an instance of Logger or RootLogger 268 // But in contrast to log4j, in log4php there is only have one LoggerHierarchy so there is 269 // no need figure out which one is $this->logger part of. 270 // TODO: Logger::getHierarchy() is marked @deprecated! 271 $repository = Logger::getHierarchy(); 272 $rendererMap = $repository->getRendererMap(); 273 $this->renderedMessage= $rendererMap->findAndRender($this->message); 274 } 275 } 276 return $this->renderedMessage; 277 } 278 279 /** 280 * Returns the time when the application started, in seconds 281 * elapsed since 01.01.1970 plus microseconds if available. 282 * 283 * @return float 284 * @static 285 */ 286 public static function getStartTime() { 287 if(!isset(self::$startTime)) { 288 if (function_exists('microtime')) { 289 // microtime as float 290 self::$startTime = microtime(true); 291 } else { 292 self::$startTime = floatval(time()); 293 } 294 } 295 return self::$startTime; 296 } 297 298 /** 299 * @return float 300 */ 301 public function getTimeStamp() { 302 return $this->timeStamp; 303 } 304 305 /** 306 * Calculates the time of this event. 307 * @return the time after event starttime when this event has occured 308 */ 309 public function getTime() { 310 $eventTime = (float)$this->getTimeStamp(); 311 $eventStartTime = (float)LoggerLoggingEvent::getStartTime(); 312 return number_format(($eventTime - $eventStartTime) * 1000, 0, '', ''); 313 } 314 315 /** 316 * @return mixed 317 */ 318 public function getThreadName() { 319 if ($this->threadName === null) { 320 $this->threadName = (string)getmypid(); 321 } 322 return $this->threadName; 323 } 324 325 /** 326 * @return mixed null 327 */ 328 public function getThrowableInformation() { 329 return null; 330 } 331 332 /** 333 * Serialize this object 334 * @return string 335 */ 336 public function toString() { 337 serialize($this); 338 } 339 340 /** 341 * Avoid serialization of the {@link $logger} object 342 */ 343 public function __sleep() { 344 return array( 345 'fqcn', 346 'categoryName', 347 'level', 348 'ndc', 349 'ndcLookupRequired', 350 'message', 351 'renderedMessage', 352 'threadName', 353 'timeStamp', 354 'locationInfo', 355 ); 356 } 357 358} 359 360LoggerLoggingEvent::getStartTime(); 361