Encore d'autres
[auf_bulletin.git] / lodel-0.9 / scripts / PEAR / Log.php
CommitLineData
314c311a 1<?php
2/**
3 * $Header: /repository/pear/Log/Log.php,v 1.64 2006/10/08 23:03:15 jon Exp $
4 * $Horde: horde/lib/Log.php,v 1.15 2000/06/29 23:39:45 jon Exp $
5 *
6 * @version $Revision: 1.64 $
7 * @package Log
8 */
9
10define('PEAR_LOG_EMERG', 0); /** System is unusable */
11define('PEAR_LOG_ALERT', 1); /** Immediate action required */
12define('PEAR_LOG_CRIT', 2); /** Critical conditions */
13define('PEAR_LOG_ERR', 3); /** Error conditions */
14define('PEAR_LOG_WARNING', 4); /** Warning conditions */
15define('PEAR_LOG_NOTICE', 5); /** Normal but significant */
16define('PEAR_LOG_INFO', 6); /** Informational */
17define('PEAR_LOG_DEBUG', 7); /** Debug-level messages */
18
19define('PEAR_LOG_ALL', bindec('11111111')); /** All messages */
20define('PEAR_LOG_NONE', bindec('00000000')); /** No message */
21
22/* Log types for PHP's native error_log() function. */
23define('PEAR_LOG_TYPE_SYSTEM', 0); /** Use PHP's system logger */
24define('PEAR_LOG_TYPE_MAIL', 1); /** Use PHP's mail() function */
25define('PEAR_LOG_TYPE_DEBUG', 2); /** Use PHP's debugging connection */
26define('PEAR_LOG_TYPE_FILE', 3); /** Append to a file */
27
28/**
29 * The Log:: class implements both an abstraction for various logging
30 * mechanisms and the Subject end of a Subject-Observer pattern.
31 *
32 * @author Chuck Hagenbuch <chuck@horde.org>
33 * @author Jon Parise <jon@php.net>
34 * @since Horde 1.3
35 * @package Log
36 */
37class Log
38{
39 /**
40 * Indicates whether or not the log can been opened / connected.
41 *
42 * @var boolean
43 * @access private
44 */
45 var $_opened = false;
46
47 /**
48 * Instance-specific unique identification number.
49 *
50 * @var integer
51 * @access private
52 */
53 var $_id = 0;
54
55 /**
56 * The label that uniquely identifies this set of log messages.
57 *
58 * @var string
59 * @access private
60 */
61 var $_ident = '';
62
63 /**
64 * The default priority to use when logging an event.
65 *
66 * @var integer
67 * @access private
68 */
69 var $_priority = PEAR_LOG_INFO;
70
71 /**
72 * The bitmask of allowed log levels.
73 *
74 * @var integer
75 * @access private
76 */
77 var $_mask = PEAR_LOG_ALL;
78
79 /**
80 * Holds all Log_observer objects that wish to be notified of new messages.
81 *
82 * @var array
83 * @access private
84 */
85 var $_listeners = array();
86
87 /**
88 * Maps canonical format keys to position arguments for use in building
89 * "line format" strings.
90 *
91 * @var array
92 * @access private
93 */
94 var $_formatMap = array('%{timestamp}' => '%1$s',
95 '%{ident}' => '%2$s',
96 '%{priority}' => '%3$s',
97 '%{message}' => '%4$s',
98 '%{file}' => '%5$s',
99 '%{line}' => '%6$s',
100 '%{function}' => '%7$s',
101 '%\{' => '%%{');
102
103
104 /**
105 * Attempts to return a concrete Log instance of type $handler.
106 *
107 * @param string $handler The type of concrete Log subclass to return.
108 * Attempt to dynamically include the code for
109 * this subclass. Currently, valid values are
110 * 'console', 'syslog', 'sql', 'file', and 'mcal'.
111 *
112 * @param string $name The name of the actually log file, table, or
113 * other specific store to use. Defaults to an
114 * empty string, with which the subclass will
115 * attempt to do something intelligent.
116 *
117 * @param string $ident The identity reported to the log system.
118 *
119 * @param array $conf A hash containing any additional configuration
120 * information that a subclass might need.
121 *
122 * @param int $level Log messages up to and including this level.
123 *
124 * @return object Log The newly created concrete Log instance, or
125 * null on an error.
126 * @access public
127 * @since Log 1.0
128 */
129 function &factory($handler, $name = '', $ident = '', $conf = array(),
130 $level = PEAR_LOG_DEBUG)
131 {
132 $handler = strtolower($handler);
133 $class = 'Log_' . $handler;
134 $classfile = 'Log/' . $handler . '.php';
135
136 /*
137 * Attempt to include our version of the named class, but don't treat
138 * a failure as fatal. The caller may have already included their own
139 * version of the named class.
140 */
141 if (!class_exists($class)) {
142 include_once $classfile;
143 }
144
145 /* If the class exists, return a new instance of it. */
146 if (class_exists($class)) {
8481fff4 147 $obj = new $class($name, $ident, $conf, $level);
314c311a 148 return $obj;
149 }
150
151 $null = null;
152 return $null;
153 }
154
155 /**
156 * Attempts to return a reference to a concrete Log instance of type
157 * $handler, only creating a new instance if no log instance with the same
158 * parameters currently exists.
159 *
160 * You should use this if there are multiple places you might create a
161 * logger, you don't want to create multiple loggers, and you don't want to
162 * check for the existance of one each time. The singleton pattern does all
163 * the checking work for you.
164 *
165 * <b>You MUST call this method with the $var = &Log::singleton() syntax.
166 * Without the ampersand (&) in front of the method name, you will not get
167 * a reference, you will get a copy.</b>
168 *
169 * @param string $handler The type of concrete Log subclass to return.
170 * Attempt to dynamically include the code for
171 * this subclass. Currently, valid values are
172 * 'console', 'syslog', 'sql', 'file', and 'mcal'.
173 *
174 * @param string $name The name of the actually log file, table, or
175 * other specific store to use. Defaults to an
176 * empty string, with which the subclass will
177 * attempt to do something intelligent.
178 *
179 * @param string $ident The identity reported to the log system.
180 *
181 * @param array $conf A hash containing any additional configuration
182 * information that a subclass might need.
183 *
184 * @param int $level Log messages up to and including this level.
185 *
186 * @return object Log The newly created concrete Log instance, or
187 * null on an error.
188 * @access public
189 * @since Log 1.0
190 */
191 function &singleton($handler, $name = '', $ident = '', $conf = array(),
192 $level = PEAR_LOG_DEBUG)
193 {
194 static $instances;
195 if (!isset($instances)) $instances = array();
196
197 $signature = serialize(array($handler, $name, $ident, $conf, $level));
198 if (!isset($instances[$signature])) {
199 $instances[$signature] = &Log::factory($handler, $name, $ident,
200 $conf, $level);
201 }
202
203 return $instances[$signature];
204 }
205
206 /**
207 * Abstract implementation of the open() method.
208 * @since Log 1.0
209 */
210 function open()
211 {
212 return false;
213 }
214
215 /**
216 * Abstract implementation of the close() method.
217 * @since Log 1.0
218 */
219 function close()
220 {
221 return false;
222 }
223
224 /**
225 * Abstract implementation of the flush() method.
226 * @since Log 1.8.2
227 */
228 function flush()
229 {
230 return false;
231 }
232
233 /**
234 * Abstract implementation of the log() method.
235 * @since Log 1.0
236 */
237 function log($message, $priority = null)
238 {
239 return false;
240 }
241
242 /**
243 * A convenience function for logging a emergency event. It will log a
244 * message at the PEAR_LOG_EMERG log level.
245 *
246 * @param mixed $message String or object containing the message
247 * to log.
248 *
249 * @return boolean True if the message was successfully logged.
250 *
251 * @access public
252 * @since Log 1.7.0
253 */
254 function emerg($message)
255 {
256 return $this->log($message, PEAR_LOG_EMERG);
257 }
258
259 /**
260 * A convenience function for logging an alert event. It will log a
261 * message at the PEAR_LOG_ALERT log level.
262 *
263 * @param mixed $message String or object containing the message
264 * to log.
265 *
266 * @return boolean True if the message was successfully logged.
267 *
268 * @access public
269 * @since Log 1.7.0
270 */
271 function alert($message)
272 {
273 return $this->log($message, PEAR_LOG_ALERT);
274 }
275
276 /**
277 * A convenience function for logging a critical event. It will log a
278 * message at the PEAR_LOG_CRIT log level.
279 *
280 * @param mixed $message String or object containing the message
281 * to log.
282 *
283 * @return boolean True if the message was successfully logged.
284 *
285 * @access public
286 * @since Log 1.7.0
287 */
288 function crit($message)
289 {
290 return $this->log($message, PEAR_LOG_CRIT);
291 }
292
293 /**
294 * A convenience function for logging a error event. It will log a
295 * message at the PEAR_LOG_ERR log level.
296 *
297 * @param mixed $message String or object containing the message
298 * to log.
299 *
300 * @return boolean True if the message was successfully logged.
301 *
302 * @access public
303 * @since Log 1.7.0
304 */
305 function err($message)
306 {
307 return $this->log($message, PEAR_LOG_ERR);
308 }
309
310 /**
311 * A convenience function for logging a warning event. It will log a
312 * message at the PEAR_LOG_WARNING log level.
313 *
314 * @param mixed $message String or object containing the message
315 * to log.
316 *
317 * @return boolean True if the message was successfully logged.
318 *
319 * @access public
320 * @since Log 1.7.0
321 */
322 function warning($message)
323 {
324 return $this->log($message, PEAR_LOG_WARNING);
325 }
326
327 /**
328 * A convenience function for logging a notice event. It will log a
329 * message at the PEAR_LOG_NOTICE log level.
330 *
331 * @param mixed $message String or object containing the message
332 * to log.
333 *
334 * @return boolean True if the message was successfully logged.
335 *
336 * @access public
337 * @since Log 1.7.0
338 */
339 function notice($message)
340 {
341 return $this->log($message, PEAR_LOG_NOTICE);
342 }
343
344 /**
345 * A convenience function for logging a information event. It will log a
346 * message at the PEAR_LOG_INFO log level.
347 *
348 * @param mixed $message String or object containing the message
349 * to log.
350 *
351 * @return boolean True if the message was successfully logged.
352 *
353 * @access public
354 * @since Log 1.7.0
355 */
356 function info($message)
357 {
358 return $this->log($message, PEAR_LOG_INFO);
359 }
360
361 /**
362 * A convenience function for logging a debug event. It will log a
363 * message at the PEAR_LOG_DEBUG log level.
364 *
365 * @param mixed $message String or object containing the message
366 * to log.
367 *
368 * @return boolean True if the message was successfully logged.
369 *
370 * @access public
371 * @since Log 1.7.0
372 */
373 function debug($message)
374 {
375 return $this->log($message, PEAR_LOG_DEBUG);
376 }
377
378 /**
379 * Returns the string representation of the message data.
380 *
381 * If $message is an object, _extractMessage() will attempt to extract
382 * the message text using a known method (such as a PEAR_Error object's
383 * getMessage() method). If a known method, cannot be found, the
384 * serialized representation of the object will be returned.
385 *
386 * If the message data is already a string, it will be returned unchanged.
387 *
388 * @param mixed $message The original message data. This may be a
389 * string or any object.
390 *
391 * @return string The string representation of the message.
392 *
393 * @access private
394 */
395 function _extractMessage($message)
396 {
397 /*
398 * If we've been given an object, attempt to extract the message using
399 * a known method. If we can't find such a method, default to the
400 * "human-readable" version of the object.
401 *
402 * We also use the human-readable format for arrays.
403 */
404 if (is_object($message)) {
405 if (method_exists($message, 'getmessage')) {
406 $message = $message->getMessage();
407 } else if (method_exists($message, 'tostring')) {
408 $message = $message->toString();
409 } else if (method_exists($message, '__tostring')) {
410 if (version_compare(PHP_VERSION, '5.0.0', 'ge')) {
411 $message = (string)$message;
412 } else {
413 $message = $message->__toString();
414 }
415 } else {
416 $message = print_r($message, true);
417 }
418 } else if (is_array($message)) {
419 if (isset($message['message'])) {
420 $message = $message['message'];
421 } else {
422 $message = print_r($message, true);
423 }
424 }
425
426 /* Otherwise, we assume the message is a string. */
427 return $message;
428 }
429
430 /**
431 * Using debug_backtrace(), returns the file, line, and enclosing function
432 * name of the source code context from which log() was invoked.
433 *
434 * @param int $depth The initial number of frames we should step
435 * back into the trace.
436 *
437 * @return array Array containing three strings: the filename, the line,
438 * and the function name from which log() was called.
439 *
440 * @access private
441 * @since Log 1.9.4
442 */
443 function _getBacktraceVars($depth)
444 {
445 /* Start by generating a backtrace from the current call (here). */
446 $backtrace = debug_backtrace();
447
448 /*
449 * If we were ultimately invoked by the composite handler, we need to
450 * increase our depth one additional level to compensate.
451 */
452 if (strcasecmp(@$backtrace[$depth+1]['class'], 'Log_composite') == 0) {
453 $depth++;
454 }
455
456 /*
457 * We're interested in the frame which invoked the log() function, so
458 * we need to walk back some number of frames into the backtrace. The
459 * $depth parameter tells us where to start looking. We go one step
460 * further back to find the name of the encapsulating function from
461 * which log() was called.
462 */
463 $file = @$backtrace[$depth]['file'];
464 $line = @$backtrace[$depth]['line'];
465 $func = @$backtrace[$depth + 1]['function'];
466
467 /*
468 * However, if log() was called from one of our "shortcut" functions,
469 * we're going to need to go back an additional step.
470 */
471 if (in_array($func, array('emerg', 'alert', 'crit', 'err', 'warning',
472 'notice', 'info', 'debug'))) {
473 $file = @$backtrace[$depth + 1]['file'];
474 $line = @$backtrace[$depth + 1]['line'];
475 $func = @$backtrace[$depth + 2]['function'];
476 }
477
478 /*
479 * If we couldn't extract a function name (perhaps because we were
480 * executed from the "main" context), provide a default value.
481 */
482 if (is_null($func)) {
483 $func = '(none)';
484 }
485
486 /* Return a 3-tuple containing (file, line, function). */
487 return array($file, $line, $func);
488 }
489
490 /**
491 * Produces a formatted log line based on a format string and a set of
492 * variables representing the current log record and state.
493 *
494 * @return string Formatted log string.
495 *
496 * @access private
497 * @since Log 1.9.4
498 */
499 function _format($format, $timestamp, $priority, $message)
500 {
501 /*
502 * If the format string references any of the backtrace-driven
503 * variables (%5, %6, %7), generate the backtrace and fetch them.
504 */
505 if (strpos($format, '%5') || strpos($format, '%6') || strpos($format, '%7')) {
506 list($file, $line, $func) = $this->_getBacktraceVars(2);
507 }
508
509 /*
510 * Build the formatted string. We use the sprintf() function's
511 * "argument swapping" capability to dynamically select and position
512 * the variables which will ultimately appear in the log string.
513 */
514 return sprintf($format,
515 $timestamp,
516 $this->_ident,
517 $this->priorityToString($priority),
518 $message,
519 isset($file) ? $file : '',
520 isset($line) ? $line : '',
521 isset($func) ? $func : '');
522 }
523
524 /**
525 * Returns the string representation of a PEAR_LOG_* integer constant.
526 *
527 * @param int $priority A PEAR_LOG_* integer constant.
528 *
529 * @return string The string representation of $level.
530 *
531 * @since Log 1.0
532 */
533 function priorityToString($priority)
534 {
535 $levels = array(
536 PEAR_LOG_EMERG => 'emergency',
537 PEAR_LOG_ALERT => 'alert',
538 PEAR_LOG_CRIT => 'critical',
539 PEAR_LOG_ERR => 'error',
540 PEAR_LOG_WARNING => 'warning',
541 PEAR_LOG_NOTICE => 'notice',
542 PEAR_LOG_INFO => 'info',
543 PEAR_LOG_DEBUG => 'debug'
544 );
545
546 return $levels[$priority];
547 }
548
549 /**
550 * Returns the the PEAR_LOG_* integer constant for the given string
551 * representation of a priority name. This function performs a
552 * case-insensitive search.
553 *
554 * @param string $name String containing a priority name.
555 *
556 * @return string The PEAR_LOG_* integer contstant corresponding
557 * the the specified priority name.
558 *
559 * @since Log 1.9.0
560 */
561 function stringToPriority($name)
562 {
563 $levels = array(
564 'emergency' => PEAR_LOG_EMERG,
565 'alert' => PEAR_LOG_ALERT,
566 'critical' => PEAR_LOG_CRIT,
567 'error' => PEAR_LOG_ERR,
568 'warning' => PEAR_LOG_WARNING,
569 'notice' => PEAR_LOG_NOTICE,
570 'info' => PEAR_LOG_INFO,
571 'debug' => PEAR_LOG_DEBUG
572 );
573
574 return $levels[strtolower($name)];
575 }
576
577 /**
578 * Calculate the log mask for the given priority.
579 *
580 * This method may be called statically.
581 *
582 * @param integer $priority The priority whose mask will be calculated.
583 *
584 * @return integer The calculated log mask.
585 *
586 * @access public
587 * @since Log 1.7.0
588 */
589 function MASK($priority)
590 {
591 return (1 << $priority);
592 }
593
594 /**
595 * Calculate the log mask for all priorities up to the given priority.
596 *
597 * This method may be called statically.
598 *
599 * @param integer $priority The maximum priority covered by this mask.
600 *
601 * @return integer The resulting log mask.
602 *
603 * @access public
604 * @since Log 1.7.0
605 *
606 * @deprecated deprecated since Log 1.9.4; use Log::MAX() instead
607 */
608 function UPTO($priority)
609 {
610 return Log::MAX($priority);
611 }
612
613 /**
614 * Calculate the log mask for all priorities greater than or equal to the
615 * given priority. In other words, $priority will be the lowest priority
616 * matched by the resulting mask.
617 *
618 * This method may be called statically.
619 *
620 * @param integer $priority The minimum priority covered by this mask.
621 *
622 * @return integer The resulting log mask.
623 *
624 * @access public
625 * @since Log 1.9.4
626 */
627 function MIN($priority)
628 {
629 return PEAR_LOG_ALL ^ ((1 << $priority) - 1);
630 }
631
632 /**
633 * Calculate the log mask for all priorities less than or equal to the
634 * given priority. In other words, $priority will be the highests priority
635 * matched by the resulting mask.
636 *
637 * This method may be called statically.
638 *
639 * @param integer $priority The maximum priority covered by this mask.
640 *
641 * @return integer The resulting log mask.
642 *
643 * @access public
644 * @since Log 1.9.4
645 */
646 function MAX($priority)
647 {
648 return ((1 << ($priority + 1)) - 1);
649 }
650
651 /**
652 * Set and return the level mask for the current Log instance.
653 *
654 * @param integer $mask A bitwise mask of log levels.
655 *
656 * @return integer The current level mask.
657 *
658 * @access public
659 * @since Log 1.7.0
660 */
661 function setMask($mask)
662 {
663 $this->_mask = $mask;
664
665 return $this->_mask;
666 }
667
668 /**
669 * Returns the current level mask.
670 *
671 * @return interger The current level mask.
672 *
673 * @access public
674 * @since Log 1.7.0
675 */
676 function getMask()
677 {
678 return $this->_mask;
679 }
680
681 /**
682 * Check if the given priority is included in the current level mask.
683 *
684 * @param integer $priority The priority to check.
685 *
686 * @return boolean True if the given priority is included in the current
687 * log mask.
688 *
689 * @access private
690 * @since Log 1.7.0
691 */
692 function _isMasked($priority)
693 {
694 return (Log::MASK($priority) & $this->_mask);
695 }
696
697 /**
698 * Returns the current default priority.
699 *
700 * @return integer The current default priority.
701 *
702 * @access public
703 * @since Log 1.8.4
704 */
705 function getPriority()
706 {
707 return $this->_priority;
708 }
709
710 /**
711 * Sets the default priority to the specified value.
712 *
713 * @param integer $priority The new default priority.
714 *
715 * @access public
716 * @since Log 1.8.4
717 */
718 function setPriority($priority)
719 {
720 $this->_priority = $priority;
721 }
722
723 /**
724 * Adds a Log_observer instance to the list of observers that are listening
725 * for messages emitted by this Log instance.
726 *
727 * @param object $observer The Log_observer instance to attach as a
728 * listener.
729 *
730 * @param boolean True if the observer is successfully attached.
731 *
732 * @access public
733 * @since Log 1.0
734 */
735 function attach(&$observer)
736 {
737 if (!is_a($observer, 'Log_observer')) {
738 return false;
739 }
740
741 $this->_listeners[$observer->_id] = &$observer;
742
743 return true;
744 }
745
746 /**
747 * Removes a Log_observer instance from the list of observers.
748 *
749 * @param object $observer The Log_observer instance to detach from
750 * the list of listeners.
751 *
752 * @param boolean True if the observer is successfully detached.
753 *
754 * @access public
755 * @since Log 1.0
756 */
757 function detach($observer)
758 {
759 if (!is_a($observer, 'Log_observer') ||
760 !isset($this->_listeners[$observer->_id])) {
761 return false;
762 }
763
764 unset($this->_listeners[$observer->_id]);
765
766 return true;
767 }
768
769 /**
770 * Informs each registered observer instance that a new message has been
771 * logged.
772 *
773 * @param array $event A hash describing the log event.
774 *
775 * @access private
776 */
777 function _announce($event)
778 {
779 foreach ($this->_listeners as $id => $listener) {
780 if ($event['priority'] <= $this->_listeners[$id]->_priority) {
781 $this->_listeners[$id]->notify($event);
782 }
783 }
784 }
785
786 /**
787 * Indicates whether this is a composite class.
788 *
789 * @return boolean True if this is a composite class.
790 *
791 * @access public
792 * @since Log 1.0
793 */
794 function isComposite()
795 {
796 return false;
797 }
798
799 /**
800 * Sets this Log instance's identification string.
801 *
802 * @param string $ident The new identification string.
803 *
804 * @access public
805 * @since Log 1.6.3
806 */
807 function setIdent($ident)
808 {
809 $this->_ident = $ident;
810 }
811
812 /**
813 * Returns the current identification string.
814 *
815 * @return string The current Log instance's identification string.
816 *
817 * @access public
818 * @since Log 1.6.3
819 */
820 function getIdent()
821 {
822 return $this->_ident;
823 }
824}