AppExceptionHandler.php 2.88 KB
Newer Older
1 2 3 4 5 6
<?php

declare(strict_types=1);

namespace Meibuyu\Micro\Exceptions\Handler;

7
use Exception;
8 9
use Hyperf\Amqp\Producer;
use Hyperf\Contract\ConfigInterface;
10 11 12
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
13
use Hyperf\HttpServer\Contract\RequestInterface;
14
use Hyperf\Logger\LoggerFactory;
15 16
use Meibuyu\Micro\Amqp\Producer\ExceptionLogProducer;
use Psr\Container\ContainerInterface;
17 18 19 20 21 22
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Throwable;

class AppExceptionHandler extends ExceptionHandler
{
23 24 25 26 27 28

    /**
     * @var ContainerInterface
     */
    protected $container;

29 30 31 32 33 34 35 36 37 38
    /**
     * @var StdoutLoggerInterface
     */
    protected $stdoutLogger;

    /**
     * @var LoggerInterface
     */
    protected $logger;

39 40 41 42 43
    /**
     * @var ConfigInterface
     */
    protected $config;

44 45 46 47 48
    /**
     * @var RequestInterface
     */
    protected $request;

49
    public function __construct(ContainerInterface $container)
50
    {
51 52 53 54
        $this->container = $container;
        $this->stdoutLogger = $container->get(StdoutLoggerInterface::class);
        $this->logger = $container->get(LoggerFactory::class)->get('Uncaught Exception');
        $this->config = $container->get(ConfigInterface::class);
55
        $this->request = $container->get(RequestInterface::class);
56 57 58 59 60 61
    }

    public function handle(Throwable $throwable, ResponseInterface $response)
    {
        // 捕获所有未捕获的异常
        $this->stopPropagation();
62 63
        $api = sprintf('%s(%s)', $this->request->getUri(), $this->request->getMethod());
        $exceptionClass = get_class($throwable);
64 65 66 67
        $message = $throwable->getMessage();
        $line = $throwable->getLine();
        $file = $throwable->getFile();
        $code = $throwable->getCode();
68
        $trace = $throwable->getTraceAsString();
69
        $data = [
70
            'api' => $api,
71 72 73 74 75 76 77 78 79 80 81 82
            'server' => $this->config->get('app_name'),
            'file' => $file,
            'line' => $line,
            'message' => $message,
            'trace' => $trace,
            'code' => $code,
            'created_at' => now(),
        ];
        try {
            $exceptionLogProducer = new ExceptionLogProducer($data);
            $producer = $this->container->get(Producer::class);
            $producer->produce($exceptionLogProducer);
83
        } catch (Exception $e) {
84 85
            put_log('异常日志失败; ' . $e->getMessage(), 'ExceptionLogProducer.log');
        }
86 87 88 89
        $msg = sprintf('%s: %s(%s) in %s:%s', $exceptionClass, $message, $code, $file, $line);
        $error = sprintf("API: %s\n%s\nStack trace:\n%s", $api, $msg, $trace);
        $this->logger->error($error);
        $this->stdoutLogger->error($error);
90
        return $response->withStatus(500)->withBody(new SwooleStream($msg));
91 92 93 94 95 96 97
    }

    public function isValid(Throwable $throwable): bool
    {
        return true;
    }
}