Log.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. <?php
  2. /**
  3. * $Header: /repository/pear/Log/Log.php,v 1.45 2004/01/19 08:02:38 jon Exp $
  4. * $Horde: horde/lib/Log.php,v 1.15 2000/06/29 23:39:45 jon Exp $
  5. *
  6. * @version $Revision: 1.45 $
  7. * @package Log
  8. */
  9. define('PEAR_LOG_EMERG', 0); /** System is unusable */
  10. define('PEAR_LOG_ALERT', 1); /** Immediate action required */
  11. define('PEAR_LOG_CRIT', 2); /** Critical conditions */
  12. define('PEAR_LOG_ERR', 3); /** Error conditions */
  13. define('PEAR_LOG_WARNING', 4); /** Warning conditions */
  14. define('PEAR_LOG_NOTICE', 5); /** Normal but significant */
  15. define('PEAR_LOG_INFO', 6); /** Informational */
  16. define('PEAR_LOG_DEBUG', 7); /** Debug-level messages */
  17. define('PEAR_LOG_ALL', bindec('11111111')); /** All messages */
  18. define('PEAR_LOG_NONE', bindec('00000000')); /** No message */
  19. /* Log types for PHP's native error_log() function. */
  20. define('PEAR_LOG_TYPE_SYSTEM', 0); /** Use PHP's system logger */
  21. define('PEAR_LOG_TYPE_MAIL', 1); /** Use PHP's mail() function */
  22. define('PEAR_LOG_TYPE_DEBUG', 2); /** Use PHP's debugging connection */
  23. define('PEAR_LOG_TYPE_FILE', 3); /** Append to a file */
  24. /**
  25. * The Log:: class implements both an abstraction for various logging
  26. * mechanisms and the Subject end of a Subject-Observer pattern.
  27. *
  28. * @author Chuck Hagenbuch <chuck@horde.org>
  29. * @author Jon Parise <jon@php.net>
  30. * @since Horde 1.3
  31. * @package Log
  32. */
  33. class Log
  34. {
  35. /**
  36. * Indicates whether or not the log can been opened / connected.
  37. *
  38. * @var boolean
  39. * @access private
  40. */
  41. var $_opened = false;
  42. /**
  43. * Instance-specific unique identification number.
  44. *
  45. * @var integer
  46. * @access private
  47. */
  48. var $_id = 0;
  49. /**
  50. * The label that uniquely identifies this set of log messages.
  51. *
  52. * @var string
  53. * @access private
  54. */
  55. var $_ident = '';
  56. /**
  57. * The default priority to use when logging an event.
  58. *
  59. * @var integer
  60. * @access private
  61. */
  62. var $_priority = PEAR_LOG_INFO;
  63. /**
  64. * The bitmask of allowed log levels.
  65. * @var integer
  66. * @access private
  67. */
  68. var $_mask = PEAR_LOG_ALL;
  69. /**
  70. * Holds all Log_observer objects that wish to be notified of new messages.
  71. *
  72. * @var array
  73. * @access private
  74. */
  75. var $_listeners = array();
  76. /**
  77. * Attempts to return a concrete Log instance of type $handler.
  78. *
  79. * @param string $handler The type of concrete Log subclass to return.
  80. * Attempt to dynamically include the code for
  81. * this subclass. Currently, valid values are
  82. * 'console', 'syslog', 'sql', 'file', and 'mcal'.
  83. *
  84. * @param string $name The name of the actually log file, table, or
  85. * other specific store to use. Defaults to an
  86. * empty string, with which the subclass will
  87. * attempt to do something intelligent.
  88. *
  89. * @param string $ident The identity reported to the log system.
  90. *
  91. * @param array $conf A hash containing any additional configuration
  92. * information that a subclass might need.
  93. *
  94. * @param int $level Log messages up to and including this level.
  95. *
  96. * @return object Log The newly created concrete Log instance, or an
  97. * false on an error.
  98. * @access public
  99. * @since Log 1.0
  100. */
  101. function &factory($handler, $name = '', $ident = '', $conf = array(),
  102. $level = PEAR_LOG_DEBUG)
  103. {
  104. $handler = strtolower($handler);
  105. $class = 'Log_' . $handler;
  106. $classfile = 'Log/' . $handler . '.php';
  107. /*
  108. * Attempt to include our version of the named class, but don't treat
  109. * a failure as fatal. The caller may have already included their own
  110. * version of the named class.
  111. */
  112. @include_once $classfile;
  113. /* If the class exists, return a new instance of it. */
  114. if (class_exists($class)) {
  115. return new $class($name, $ident, $conf, $level);
  116. }
  117. return false;
  118. }
  119. /**
  120. * Attempts to return a reference to a concrete Log instance of type
  121. * $handler, only creating a new instance if no log instance with the same
  122. * parameters currently exists.
  123. *
  124. * You should use this if there are multiple places you might create a
  125. * logger, you don't want to create multiple loggers, and you don't want to
  126. * check for the existance of one each time. The singleton pattern does all
  127. * the checking work for you.
  128. *
  129. * <b>You MUST call this method with the $var = &Log::singleton() syntax.
  130. * Without the ampersand (&) in front of the method name, you will not get
  131. * a reference, you will get a copy.</b>
  132. *
  133. * @param string $handler The type of concrete Log subclass to return.
  134. * Attempt to dynamically include the code for
  135. * this subclass. Currently, valid values are
  136. * 'console', 'syslog', 'sql', 'file', and 'mcal'.
  137. *
  138. * @param string $name The name of the actually log file, table, or
  139. * other specific store to use. Defaults to an
  140. * empty string, with which the subclass will
  141. * attempt to do something intelligent.
  142. *
  143. * @param string $ident The identity reported to the log system.
  144. *
  145. * @param array $conf A hash containing any additional configuration
  146. * information that a subclass might need.
  147. *
  148. * @param int $level Log messages up to and including this level.
  149. *
  150. * @return object Log The newly created concrete Log instance, or an
  151. * false on an error.
  152. * @access public
  153. * @since Log 1.0
  154. */
  155. function &singleton($handler, $name = '', $ident = '', $conf = array(),
  156. $level = PEAR_LOG_DEBUG)
  157. {
  158. static $instances;
  159. if (!isset($instances)) $instances = array();
  160. $signature = serialize(array($handler, $name, $ident, $conf, $level));
  161. if (!isset($instances[$signature])) {
  162. $instances[$signature] = &Log::factory($handler, $name, $ident,
  163. $conf, $level);
  164. }
  165. return $instances[$signature];
  166. }
  167. /**
  168. * Abstract implementation of the open() method.
  169. * @since Log 1.0
  170. */
  171. function open()
  172. {
  173. return false;
  174. }
  175. /**
  176. * Abstract implementation of the close() method.
  177. * @since Log 1.0
  178. */
  179. function close()
  180. {
  181. return false;
  182. }
  183. /**
  184. * Abstract implementation of the flush() method.
  185. * @since Log 1.8.2
  186. */
  187. function flush()
  188. {
  189. return false;
  190. }
  191. /**
  192. * Abstract implementation of the log() method.
  193. * @since Log 1.0
  194. */
  195. function log($message, $priority = null)
  196. {
  197. return false;
  198. }
  199. /**
  200. * A convenience function for logging a emergency event. It will log a
  201. * message at the PEAR_LOG_EMERG log level.
  202. *
  203. * @param mixed $message String or object containing the message
  204. * to log.
  205. *
  206. * @return boolean True if the message was successfully logged.
  207. *
  208. * @access public
  209. * @since Log 1.7.0
  210. */
  211. function emerg($message)
  212. {
  213. return $this->log($message, PEAR_LOG_EMERG);
  214. }
  215. /**
  216. * A convenience function for logging an alert event. It will log a
  217. * message at the PEAR_LOG_ALERT log level.
  218. *
  219. * @param mixed $message String or object containing the message
  220. * to log.
  221. *
  222. * @return boolean True if the message was successfully logged.
  223. *
  224. * @access public
  225. * @since Log 1.7.0
  226. */
  227. function alert($message)
  228. {
  229. return $this->log($message, PEAR_LOG_ALERT);
  230. }
  231. /**
  232. * A convenience function for logging a critical event. It will log a
  233. * message at the PEAR_LOG_CRIT log level.
  234. *
  235. * @param mixed $message String or object containing the message
  236. * to log.
  237. *
  238. * @return boolean True if the message was successfully logged.
  239. *
  240. * @access public
  241. * @since Log 1.7.0
  242. */
  243. function crit($message)
  244. {
  245. return $this->log($message, PEAR_LOG_CRIT);
  246. }
  247. /**
  248. * A convenience function for logging a error event. It will log a
  249. * message at the PEAR_LOG_ERR log level.
  250. *
  251. * @param mixed $message String or object containing the message
  252. * to log.
  253. *
  254. * @return boolean True if the message was successfully logged.
  255. *
  256. * @access public
  257. * @since Log 1.7.0
  258. */
  259. function err($message)
  260. {
  261. return $this->log($message, PEAR_LOG_ERR);
  262. }
  263. /**
  264. * A convenience function for logging a warning event. It will log a
  265. * message at the PEAR_LOG_WARNING log level.
  266. *
  267. * @param mixed $message String or object containing the message
  268. * to log.
  269. *
  270. * @return boolean True if the message was successfully logged.
  271. *
  272. * @access public
  273. * @since Log 1.7.0
  274. */
  275. function warning($message)
  276. {
  277. return $this->log($message, PEAR_LOG_WARNING);
  278. }
  279. /**
  280. * A convenience function for logging a notice event. It will log a
  281. * message at the PEAR_LOG_NOTICE log level.
  282. *
  283. * @param mixed $message String or object containing the message
  284. * to log.
  285. *
  286. * @return boolean True if the message was successfully logged.
  287. *
  288. * @access public
  289. * @since Log 1.7.0
  290. */
  291. function notice($message)
  292. {
  293. return $this->log($message, PEAR_LOG_NOTICE);
  294. }
  295. /**
  296. * A convenience function for logging a information event. It will log a
  297. * message at the PEAR_LOG_INFO log level.
  298. *
  299. * @param mixed $message String or object containing the message
  300. * to log.
  301. *
  302. * @return boolean True if the message was successfully logged.
  303. *
  304. * @access public
  305. * @since Log 1.7.0
  306. */
  307. function info($message)
  308. {
  309. return $this->log($message, PEAR_LOG_INFO);
  310. }
  311. /**
  312. * A convenience function for logging a debug event. It will log a
  313. * message at the PEAR_LOG_DEBUG log level.
  314. *
  315. * @param mixed $message String or object containing the message
  316. * to log.
  317. *
  318. * @return boolean True if the message was successfully logged.
  319. *
  320. * @access public
  321. * @since Log 1.7.0
  322. */
  323. function debug($message)
  324. {
  325. return $this->log($message, PEAR_LOG_DEBUG);
  326. }
  327. /**
  328. * Returns the string representation of the message data.
  329. *
  330. * If $message is an object, _extractMessage() will attempt to extract
  331. * the message text using a known method (such as a PEAR_Error object's
  332. * getMessage() method). If a known method, cannot be found, the
  333. * serialized representation of the object will be returned.
  334. *
  335. * If the message data is already a string, it will be returned unchanged.
  336. *
  337. * @param mixed $message The original message data. This may be a
  338. * string or any object.
  339. *
  340. * @return string The string representation of the message.
  341. *
  342. * @access private
  343. */
  344. function _extractMessage($message)
  345. {
  346. /*
  347. * If we've been given an object, attempt to extract the message using
  348. * a known method. If we can't find such a method, default to the
  349. * "human-readable" version of the object.
  350. *
  351. * We also use the human-readable format for arrays.
  352. */
  353. if (is_object($message)) {
  354. if (method_exists($message, 'getmessage')) {
  355. $message = $message->getMessage();
  356. } else if (method_exists($message, 'tostring')) {
  357. $message = $message->toString();
  358. } else if (method_exists($message, '__tostring')) {
  359. $message = (string)$message;
  360. } else {
  361. $message = print_r($message, true);
  362. }
  363. } else if (is_array($message)) {
  364. $message = print_r($message, true);
  365. }
  366. /* Otherwise, we assume the message is a string. */
  367. return $message;
  368. }
  369. /**
  370. * Returns the string representation of a PEAR_LOG_* integer constant.
  371. *
  372. * @param int $priority A PEAR_LOG_* integer constant.
  373. *
  374. * @return string The string representation of $level.
  375. *
  376. * @since Log 1.0
  377. */
  378. function priorityToString($priority)
  379. {
  380. $levels = array(
  381. PEAR_LOG_EMERG => 'emergency',
  382. PEAR_LOG_ALERT => 'alert',
  383. PEAR_LOG_CRIT => 'critical',
  384. PEAR_LOG_ERR => 'error',
  385. PEAR_LOG_WARNING => 'warning',
  386. PEAR_LOG_NOTICE => 'notice',
  387. PEAR_LOG_INFO => 'info',
  388. PEAR_LOG_DEBUG => 'debug'
  389. );
  390. return $levels[$priority];
  391. }
  392. /**
  393. * Calculate the log mask for the given priority.
  394. *
  395. * @param integer $priority The priority whose mask will be calculated.
  396. *
  397. * @return integer The calculated log mask.
  398. *
  399. * @access public
  400. * @since Log 1.7.0
  401. */
  402. function MASK($priority)
  403. {
  404. return (1 << $priority);
  405. }
  406. /**
  407. * Calculate the log mask for all priorities up to the given priority.
  408. *
  409. * @param integer $priority The maximum priority covered by this mask.
  410. *
  411. * @return integer The calculated log mask.
  412. *
  413. * @access public
  414. * @since Log 1.7.0
  415. */
  416. function UPTO($priority)
  417. {
  418. return ((1 << ($priority + 1)) - 1);
  419. }
  420. /**
  421. * Set and return the level mask for the current Log instance.
  422. *
  423. * @param integer $mask A bitwise mask of log levels.
  424. *
  425. * @return integer The current level mask.
  426. *
  427. * @access public
  428. * @since Log 1.7.0
  429. */
  430. function setMask($mask)
  431. {
  432. $this->_mask = $mask;
  433. return $this->_mask;
  434. }
  435. /**
  436. * Returns the current level mask.
  437. *
  438. * @return interger The current level mask.
  439. *
  440. * @access public
  441. * @since Log 1.7.0
  442. */
  443. function getMask()
  444. {
  445. return $this->_mask;
  446. }
  447. /**
  448. * Check if the given priority is included in the current level mask.
  449. *
  450. * @param integer $priority The priority to check.
  451. *
  452. * @return boolean True if the given priority is included in the current
  453. * log mask.
  454. *
  455. * @access private
  456. * @since Log 1.7.0
  457. */
  458. function _isMasked($priority)
  459. {
  460. return (Log::MASK($priority) & $this->_mask);
  461. }
  462. /**
  463. * Returns the current default priority.
  464. *
  465. * @return integer The current default priority.
  466. *
  467. * @access public
  468. * @since Log 1.8.4
  469. */
  470. function getPriority()
  471. {
  472. return $this->_priority;
  473. }
  474. /**
  475. * Sets the default priority to the specified value.
  476. *
  477. * @param integer $priority The new default priority.
  478. *
  479. * @access public
  480. * @since Log 1.8.4
  481. */
  482. function setPriority($priority)
  483. {
  484. $this->_priority = $priority;
  485. }
  486. /**
  487. * Adds a Log_observer instance to the list of observers that are listening
  488. * for messages emitted by this Log instance.
  489. *
  490. * @param object $observer The Log_observer instance to attach as a
  491. * listener.
  492. *
  493. * @param boolean True if the observer is successfully attached.
  494. *
  495. * @access public
  496. * @since Log 1.0
  497. */
  498. function attach(&$observer)
  499. {
  500. if (!is_a($observer, 'Log_observer')) {
  501. return false;
  502. }
  503. $this->_listeners[$observer->_id] = &$observer;
  504. return true;
  505. }
  506. /**
  507. * Removes a Log_observer instance from the list of observers.
  508. *
  509. * @param object $observer The Log_observer instance to detach from
  510. * the list of listeners.
  511. *
  512. * @param boolean True if the observer is successfully detached.
  513. *
  514. * @access public
  515. * @since Log 1.0
  516. */
  517. function detach($observer)
  518. {
  519. if (!is_a($observer, 'Log_observer') ||
  520. !isset($this->_listeners[$observer->_id])) {
  521. return false;
  522. }
  523. unset($this->_listeners[$observer->_id]);
  524. return true;
  525. }
  526. /**
  527. * Informs each registered observer instance that a new message has been
  528. * logged.
  529. *
  530. * @param array $event A hash describing the log event.
  531. *
  532. * @access private
  533. */
  534. function _announce($event)
  535. {
  536. foreach ($this->_listeners as $id => $listener) {
  537. if ($event['priority'] <= $this->_listeners[$id]->_priority) {
  538. $this->_listeners[$id]->notify($event);
  539. }
  540. }
  541. }
  542. /**
  543. * Indicates whether this is a composite class.
  544. *
  545. * @return boolean True if this is a composite class.
  546. *
  547. * @access public
  548. * @since Log 1.0
  549. */
  550. function isComposite()
  551. {
  552. return false;
  553. }
  554. /**
  555. * Sets this Log instance's identification string.
  556. *
  557. * @param string $ident The new identification string.
  558. *
  559. * @access public
  560. * @since Log 1.6.3
  561. */
  562. function setIdent($ident)
  563. {
  564. $this->_ident = $ident;
  565. }
  566. /**
  567. * Returns the current identification string.
  568. *
  569. * @return string The current Log instance's identification string.
  570. *
  571. * @access public
  572. * @since Log 1.6.3
  573. */
  574. function getIdent()
  575. {
  576. return $this->_ident;
  577. }
  578. }
  579. ?>