writer($message, $method); } /** * @param mixed $message * @param string $method * @throws Exception */ public function trance(mixed $message, string $method = 'app') { $this->writer($message, $method); } /** * @param mixed $message * @param string $method * @param null $file * @throws Exception */ public function error(mixed $message, $method = 'error', $file = null) { $this->writer($message, $method); } /** * @param mixed $message * @param string $method * @param null $file * @throws Exception */ public function success(mixed $message, string $method = 'app', $file = null) { $this->writer($message, $method); } /** * @param $message * @param string $method * @return string * @throws Exception */ private function writer($message, string $method = 'app'): string { $this->print_r($message, $method); if ($message instanceof Throwable) { $message = $message->getMessage(); } else { if (is_array($message) || is_object($message)) { $message = $this->arrayFormat($message); } } if (is_array($message)) { $message = $this->arrayFormat($message); } if (!empty($message)) { if (!is_array($this->logs)) { $this->logs = []; } $this->logs[] = [$method, $message]; } return $message; } /** * @param $message * @param string $method * @throws Exception */ public function print_r($message, string $method = '') { $debug = Config::get('debug', ['enable' => false]); if ((bool)$debug['enable'] === true) { if (!is_callable($debug['callback'] ?? null, true)) { return; } call_user_func($debug['callback'], $message, $method); } } /** * @param $message */ public function output($message) { if (str_contains($message, 'Event::rshutdown(): Event::wait()')) { return; } echo $message; } /** * @param string $application * @return mixed */ public function getLastError(string $application = 'app'): mixed { $filetype = []; foreach ($this->logs as $key => $val) { if ($val[0] != $application) { continue; } $filetype[] = $val[1]; } if (empty($filetype)) { return 'Unknown error.'; } return end($filetype); } /** * @param string $messages * @param string $method * @throws Exception */ public function write(string $messages, string $method = 'app') { if (empty($messages)) { return; } $to_day = date('Y-m-d'); if (!isset($this->sources[$to_day])) $this->sources[$to_day] = []; $fileName = storage('server-' . $to_day . '.log', $dirName = 'log/' . ($method ?? 'app')); if (!isset($this->sources[$to_day][$fileName])) { $this->sources[$to_day][$fileName] = fopen($fileName, 'rw'); } fwrite($this->sources[$to_day][$fileName], '[' . date('Y-m-d H:i:s') . ']:' . PHP_EOL . $messages . PHP_EOL); $this->clearHistoryFile($dirName); $this->clearPrevLog($to_day); } /** * 清理文件资源 */ public function closeSource() { foreach ($this->sources as $source) { fclose($source); } $this->sources = []; } /** * @param $to_day */ public function clearPrevLog($to_day) { if (count($this->sources) > 1) { foreach ($this->sources as $day => $source) { if ($day == $to_day) { continue; } foreach ($source as $value) { fclose($value); } unset($this->sources[$day]); } } } /** * @param string $dirName * @throws \Exception */ private function clearHistoryFile(string $dirName) { $command = 'find ' . storage(null, $dirName) . '/ -mtime +15 -name "*.log" -exec rm -rf {} \;'; Coroutine::getCid() !== -1 ? Coroutine\System::exec($command) : \shell_exec($command); } /** * @param $logFile * @return string */ private function getSource($logFile): string { if (!file_exists($logFile)) { Coroutine\System::exec('echo 3 > /proc/sys/vm/drop_caches'); touch($logFile); } if (is_writeable($logFile)) { $logFile = realpath($logFile); } return $logFile; } /** * @throws Exception * 写入日志 */ public function insert() { if (empty($this->logs)) { return; } foreach ($this->logs as $log) { [$method, $message] = $log; $this->write($message, $method); } $this->logs = []; } /** * @return array */ public function clear(): array { return $this->logs = []; } /** * @param $data * @return string */ private function arrayFormat($data): string { if (is_string($data)) { return $data; } if ($data instanceof Throwable) { $data = $this->getException($data); } else if (is_object($data)) { $data = get_object_vars($data); } $filetype = []; foreach ($data as $key => $val) { if (is_array($val)) { $filetype[] = $this->arrayFormat($val); } else { $filetype[] = (is_string($key) ? $key . ' : ' : '') . $val; } } return implode(PHP_EOL, $filetype); } /** * @param Throwable $exception * @return mixed * @throws Exception */ public function exception(Throwable $exception): mixed { $errorInfo = [ 'message' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine() ]; $this->error(var_export($errorInfo, true)); $code = $exception->getCode() == 0 ? 500 : $exception->getCode(); $logger = Snowflake::app()->getLogger(); $string = 'Exception: ' . PHP_EOL; $string .= '#. message: ' . $errorInfo['message'] . PHP_EOL; $string .= '#. file: ' . $errorInfo['file'] . PHP_EOL; $string .= '#. line: ' . $errorInfo['line'] . PHP_EOL; $logger->write($string . $exception->getTraceAsString(), 'trace'); $logger->write(jTraceEx($exception), 'exception'); return Json::to($code, $errorInfo['message'], [ 'file' => $exception->getFile(), 'line' => $exception->getLine() ]); } /** * @param Throwable $exception * @return array */ private function getException(Throwable $exception): array { $filetype = [$exception->getMessage()]; $filetype[] = $exception->getFile() . ' on line ' . $exception->getLine(); $filetype[] = $exception->getTrace(); return $filetype; } }