PocketMine-MP  1.4 - API 1.10.0
 All Classes Namespaces Functions Variables Pages
MainLogger.php
1 <?php
2 
3 /*
4  *
5  * ____ _ _ __ __ _ __ __ ____
6  * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7  * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8  * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9  * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10  *
11  * This program is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * @author PocketMine Team
17  * @link http://www.pocketmine.net/
18  *
19  *
20 */
21 
22 namespace pocketmine\utils;
23 
24 use LogLevel;
25 
26 class MainLogger extends \AttachableThreadedLogger{
27  protected $logFile;
28  protected $logStream;
29  protected $shutdown;
30  protected $hasANSI;
31  protected $logDebug;
32  private $logResource;
34  public static $logger = null;
35 
43  public function __construct($logFile, $hasANSI = false, $logDebug = false){
44  if(static::$logger instanceof MainLogger){
45  throw new \RuntimeException("MainLogger has been already created");
46  }
47  static::$logger = $this;
48  touch($logFile);
49  $this->logFile = $logFile;
50  $this->hasANSI = (bool) $hasANSI;
51  $this->logDebug = (bool) $logDebug;
52  $this->logStream = "";
53  $this->start(PTHREADS_INHERIT_NONE);
54  }
55 
59  public static function getLogger(){
60  return static::$logger;
61  }
62 
63  public function emergency($message){
64  $this->send(TextFormat::RED . "[EMERGENCY] " . $message, \LogLevel::EMERGENCY);
65  }
66 
67  public function alert($message){
68  $this->send(TextFormat::RED . "[ALERT] " . $message, \LogLevel::ALERT);
69  }
70 
71  public function critical($message){
72  $this->send(TextFormat::RED . "[CRITICAL] " . $message, \LogLevel::CRITICAL);
73  }
74 
75  public function error($message){
76  $this->send(TextFormat::DARK_RED . "[ERROR] " . $message, \LogLevel::ERROR);
77  }
78 
79  public function warning($message){
80  $this->send(TextFormat::YELLOW . "[WARNING] " . $message, \LogLevel::WARNING);
81  }
82 
83  public function notice($message){
84  $this->send(TextFormat::AQUA . "[NOTICE] " . $message, \LogLevel::NOTICE);
85  }
86 
87  public function info($message){
88  $this->send(TextFormat::WHITE . "[INFO] " . $message, \LogLevel::INFO);
89  }
90 
91  public function debug($message){
92  if($this->logDebug === false){
93  return;
94  }
95  $this->send(TextFormat::GRAY . "[DEBUG] " . $message, \LogLevel::DEBUG);
96  }
97 
101  public function setLogDebug($logDebug){
102  $this->logDebug = (bool) $logDebug;
103  }
104 
105  public function logException(\Exception $e, $trace = null){
106  if($trace === null){
107  $trace = $e->getTrace();
108  }
109  $errstr = $e->getMessage();
110  $errfile = $e->getFile();
111  $errno = $e->getCode();
112  $errline = $e->getLine();
113 
114  $errorConversion = [
115  0 => "EXCEPTION",
116  E_ERROR => "E_ERROR",
117  E_WARNING => "E_WARNING",
118  E_PARSE => "E_PARSE",
119  E_NOTICE => "E_NOTICE",
120  E_CORE_ERROR => "E_CORE_ERROR",
121  E_CORE_WARNING => "E_CORE_WARNING",
122  E_COMPILE_ERROR => "E_COMPILE_ERROR",
123  E_COMPILE_WARNING => "E_COMPILE_WARNING",
124  E_USER_ERROR => "E_USER_ERROR",
125  E_USER_WARNING => "E_USER_WARNING",
126  E_USER_NOTICE => "E_USER_NOTICE",
127  E_STRICT => "E_STRICT",
128  E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
129  E_DEPRECATED => "E_DEPRECATED",
130  E_USER_DEPRECATED => "E_USER_DEPRECATED",
131  ];
132  if($errno === 0){
133  $type = LogLevel::CRITICAL;
134  }else{
135  $type = ($errno === E_ERROR or $errno === E_USER_ERROR) ? LogLevel::ERROR : (($errno === E_USER_WARNING or $errno === E_WARNING) ? LogLevel::WARNING : LogLevel::NOTICE);
136  }
137  $errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno;
138  if(($pos = strpos($errstr, "\n")) !== false){
139  $errstr = substr($errstr, 0, $pos);
140  }
141  $errfile = \pocketmine\cleanPath($errfile);
142  $this->log($type, get_class($e) . ": \"$errstr\" ($errno) in \"$errfile\" at line $errline");
143  foreach(@\pocketmine\getTrace(1, $trace) as $i => $line){
144  $this->debug($line);
145  }
146  }
147 
148  public function log($level, $message){
149  switch($level){
150  case LogLevel::EMERGENCY:
151  $this->emergency($message);
152  break;
153  case LogLevel::ALERT:
154  $this->alert($message);
155  break;
156  case LogLevel::CRITICAL:
157  $this->critical($message);
158  break;
159  case LogLevel::ERROR:
160  $this->error($message);
161  break;
162  case LogLevel::WARNING:
163  $this->warning($message);
164  break;
165  case LogLevel::NOTICE:
166  $this->notice($message);
167  break;
168  case LogLevel::INFO:
169  $this->info($message);
170  break;
171  case LogLevel::DEBUG:
172  $this->debug($message);
173  break;
174  }
175  }
176 
177  public function shutdown(){
178  $this->shutdown = true;
179  }
180 
181  protected function send($message, $level = -1){
182  $now = time();
183  $message = TextFormat::toANSI(TextFormat::AQUA . date("H:i:s", $now) . TextFormat::RESET . " " . $message . TextFormat::RESET . PHP_EOL);
184  $cleanMessage = TextFormat::clean(preg_replace('/\x1b\[[0-9;]*m/', "", $message));
185 
186  if(!$this->hasANSI){
187  echo $cleanMessage;
188  }else{
189  echo $message;
190  }
191 
192  if($this->attachment instanceof \ThreadedLoggerAttachment){
193  $this->attachment->call($level, $message);
194  }
195 
196  $this->logStream .= date("Y-m-d", $now) . " " . $cleanMessage;
197  }
198 
199  public function run(){
200  $this->shutdown = false;
201  $this->logResource = fopen($this->logFile, "a+b");
202  if(!is_resource($this->logResource)){
203  throw new \RuntimeException("Couldn't open log file");
204  }
205 
206  while($this->shutdown === false){
207  if(strlen($this->logStream) >= 4096){
208  $this->lock();
209  $chunks = strlen($this->logStream) >> 12;
210  $chunk = substr($this->logStream, 0, $chunks << 12);
211  $this->logStream = substr($this->logStream, $chunks << 12);
212  $this->unlock();
213  fwrite($this->logResource, $chunk);
214  }else{
215  usleep(250000); //sleep for 0.25 seconds
216  }
217  }
218  if(strlen($this->logStream) > 0){
219  fwrite($this->logResource, $this->logStream);
220  }
221 
222  fclose($this->logResource);
223  }
224 }
__construct($logFile, $hasANSI=false, $logDebug=false)
Definition: MainLogger.php:43