FRED™  3.0
FRED™: Framework for Rapid and Easy Development
Log.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Rsi\Fred;
4 
5 class Log extends Component{
6 
7  const CUSTOM = 10; //!< Everything above this is only logged when exactly matched.
8  const EMERGENCY = 7; //!< System is unusable.
9  const ALERT = 6; //!< Action must be taken immediately.
10  const CRITICAL = 5; //!< Critical conditions.
11  const ERROR = 4; //!< Error conditions.
12  const WARNING = 3; //!< Warning conditions.
13  const NOTICE = 2; //!< Normal, but significant, condition.
14  const INFO = 1; //!< Informational message.
15  const DEBUG = 0; //!< Debug-level message.
16 
17  public $handlers = []; //!< Array with handlers (key = name, value = config).
18  public $ignore = []; //!< Reg-exp's for concatination of IP + '#' + user agent + '#' + filename + '#' + message to ignore.
19  public $break = null; //!< Reg-exp for message to throw an Exception on.
20 
21  protected $_busy = false;
22  protected $_timers = [];
23 
24  protected function init(){
25  parent::init();
26  foreach($this->handlers as &$config){
27  if(!$config) $config = [];
28  $prio = $config['prio'] ?? null;
29  if(!array_key_exists('prios',$config) || ($prio !== null))
30  $config['prios'] = array_merge($config['prios'] ?? [],range($prio ?: self::DEBUG,self::CUSTOM - 1));
31  }
32  unset($config);
33  }
34  /**
35  * Get a handler.
36  * @param string $name Name of the handler.
37  * @return Log\\Handler
38  */
39  public function handler($name){
40  if(!is_array($this->handlers[$name])) $this->handlers[$name] = [];
41  if(!array_key_exists(null,$config =& $this->handlers[$name])){
42  $class_name = \Rsi\Record::get($config,'className',__CLASS__ . '\\Handler\\' . ucfirst($name));
43  $config[null] = new $class_name($this,$config,$name);
44  }
45  return $config[null];
46  }
47  /**
48  * Check if the log has a specific handler.
49  * @param string $name Name of the handler.
50  * @return bool True if the log has the specified handler.
51  */
52  public function has($name){
53  return array_key_exists($name,$this->handlers) ? $this->handler($name) : false;
54  }
55 
56  protected function context($filename,$line_no,$context){
57  return is_array($filename)
58  ? $filename
59  : array_merge(array_filter(['*filename' => $filename,'*lineNo' => $line_no]),$context ?: []);
60  }
61  /**
62  * Add a message to the log.
63  * @param int $prio Priority of the message. Only if this priority surpasses a handlers minimum priority, the message is
64  * processed by the handler.
65  * @param string|Exception $message Message to add (if this is an Exception all other parameters will be derived from it).
66  * @param string|array $filename File from which the message originated (or context when no specific file).
67  * @param int $line_no Line from which the message originated.
68  * @param array $context Context for the message. If a key is prefixed with an '@' the value has to be a callback function
69  * that returns the real value. This is only done (once) when the message is processed by a handler.
70  */
71  public function add($prio,$message,$filename = null,$line_no = null,$context = null){
72  if($this->break && preg_match($this->break,$message)) throw new \Exception('[break]');
73  if(!$this->_busy) try{
74  $this->_busy = true;
75  $parsed = null;
76  foreach($this->handlers as $name => $config) if(in_array($prio,$config['prios'])) try{
77  if($parsed === null){
78  $parsed = [];
79  if($message instanceof \Exception){
80  $context = ($filename ?: []) + ['trace' => $message->getTraceAsString()];
81  $filename = $message->getFile();
82  $line_no = $message->getLine();
83  $message = $message->getMessage();
84  }
85  if($this->ignore){
86  $subject = implode('#',[
87  \Rsi\Record::get($context,'remoteAddr') ?: $this->component('security')->remoteAddr,
88  $_SERVER['HTTP_USER_AGENT'] ?? null,
89  is_string($filename) ? $filename : null,
90  $message
91  ]);
92  foreach($this->ignore as $filter) if(preg_match($filter,$subject)) return false;
93  }
94  foreach($this->context($filename,$line_no,$context) as $key => $value){
95  if(substr($key,0,1) == '@') $value = call_user_func($value,$key = substr($key,1));
96  $parsed[$key] = $value;
97  }
98  }
99  $this->handler($name)->add($prio,$message,$parsed);
100  }
101  catch(\Rsi\Fred\Exception $e){
102  if($this->_fred->debug) throw $e;
103  }
104  }
105  finally{
106  $this->_busy = false;
107  }
108  }
109  /**
110  * Add a timer start message to the log.
111  * @param int $prio See add().
112  * @param string|Exception $message See add().
113  * @param string|array $filename See add().
114  * @param int $line_no See add().
115  * @param array $context See add().
116  * @return string Timer id.
117  */
118  public function start($prio,$message,$filename = null,$line_no = null,$context = null){
119  $context = $this->context($filename,$line_no,$context);
120  $this->_timers[$id = \Rsi\Str::random()] = compact('prio','message','context');
121  $this->add($prio,$message,['*start' => $id] + $context);
122  return $id;
123  }
124  /**
125  * Stop a timer message.
126  * Empty parameters are copied from the start message.
127  * @param string $id Timer id.
128  * @param int $prio See add().
129  * @param string $message See add().
130  * @param string|array $filename See add().
131  * @param int $line_no See add().
132  * @param array $context See add().
133  */
134  public function stop($id,$prio = null,$message = null,$filename = null,$line_no = null,$context = null){
135  $timer = $this->_timers[$id] ?? [];
136  $this->add(
137  $prio === null ? $timer['prio'] ?? self::DEBUG : $prio,
138  $message === null ? '[stop] ' . ($timer['message'] ?? null) : $message,
139  ['*stop' => $id] + (($filename === null) && ($line_no === null) && ($context === null)
140  ? $timer['context'] ?? []
141  : $this->context($filename,$line_no,$context)
142  )
143  );
144  }
145 
146  protected function _get($key){
147  return $this->handler($key);
148  }
149 
150  public function __call($func_name,$params){
151  array_unshift($params,constant('self::' . strtoupper($func_name)));
152  call_user_func_array([$this,'add'],$params);
153  }
154 
155  public function __invoke($message,$filename = null,$line_no = null,$context = null){
156  $this->add(self::DEBUG,$message,$filename,$line_no,$context);
157  }
158 
159 }
const EMERGENCY
System is unusable.
Definition: Log.php:8
const CUSTOM
Everything above this is only logged when exactly matched.
Definition: Log.php:7
const INFO
Informational message.
Definition: Log.php:14
start($prio, $message, $filename=null, $line_no=null, $context=null)
Add a timer start message to the log.
Definition: Log.php:118
__call($func_name, $params)
Definition: Log.php:150
stop($id, $prio=null, $message=null, $filename=null, $line_no=null, $context=null)
Stop a timer message.
Definition: Log.php:134
add($prio, $message, $filename=null, $line_no=null, $context=null)
Add a message to the log.
Definition: Log.php:71
const NOTICE
Normal, but significant, condition.
Definition: Log.php:13
handler($name)
Get a handler.
Definition: Log.php:39
has($name)
Check if the log has a specific handler.
Definition: Log.php:52
const ERROR
Error conditions.
Definition: Log.php:11
const CRITICAL
Critical conditions.
Definition: Log.php:10
const ALERT
Action must be taken immediately.
Definition: Log.php:9
_get($key)
Definition: Log.php:146
const DEBUG
Debug-level message.
Definition: Log.php:15
Framework for Rapid and Easy Development.
Definition: Fred.php:18
const WARNING
Warning conditions.
Definition: Log.php:12
context($filename, $line_no, $context)
Definition: Log.php:56
Basic component class.
Definition: Component.php:8
$handlers
Array with handlers (key = name, value = config).
Definition: Log.php:17
$ignore
Reg-exp&#39;s for concatination of IP + &#39;#&#39; + user agent + &#39;#&#39; + filename + &#39;#&#39; + message to ignore...
Definition: Log.php:18
component($name)
Get a component (local or default).
Definition: Component.php:80
__invoke($message, $filename=null, $line_no=null, $context=null)
Definition: Log.php:155
init()
Definition: Log.php:24
$break
Reg-exp for message to throw an Exception on.
Definition: Log.php:19