1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php
declare(strict_types=1);
namespace Meibuyu\Micro\Exceptions\Handler;
use Exception;
use Hyperf\Amqp\Producer;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Logger\LoggerFactory;
use Meibuyu\Micro\Amqp\Producer\ExceptionLogProducer;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Throwable;
class AppExceptionHandler extends ExceptionHandler
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* @var StdoutLoggerInterface
*/
protected $stdoutLogger;
/**
* @var LoggerInterface
*/
protected $logger;
/**
* @var ConfigInterface
*/
protected $config;
/**
* @var RequestInterface
*/
protected $request;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->stdoutLogger = $container->get(StdoutLoggerInterface::class);
$this->logger = $container->get(LoggerFactory::class)->get('Uncaught Exception');
$this->config = $container->get(ConfigInterface::class);
$this->request = $container->get(RequestInterface::class);
}
public function handle(Throwable $throwable, ResponseInterface $response)
{
// 捕获所有未捕获的异常
$this->stopPropagation();
$api = sprintf('%s(%s)', $this->request->getUri(), $this->request->getMethod());
$exceptionClass = get_class($throwable);
$message = $throwable->getMessage();
$line = $throwable->getLine();
$file = $throwable->getFile();
$code = $throwable->getCode();
$trace = $throwable->getTraceAsString();
$data = [
'api' => $api,
'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);
} catch (Exception $e) {
put_log('异常日志失败; ' . $e->getMessage(), 'ExceptionLogProducer.log');
}
$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);
return $response->withStatus(500)->withBody(new SwooleStream($msg));
}
public function isValid(Throwable $throwable): bool
{
return true;
}
}