hyperf: 配置异常处理
一,配置
config/autoload/exceptions.php
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
return [
'handler' => [
'http' => [
Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler::class,
App\Exception\Handler\AppExceptionHandler::class,
],
],
];
保持默认配置,无需改动
二,代码
1, 异常处理类,增加我们的配置:主要三项:
记录引发异常时的http环境,url/参数/ip等
记数异常信息到日志文件
返回改为json格式
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace App\Exception\Handler;
use App\Log\ExceptionLog;
use Hyperf\Context\ApplicationContext;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\ExceptionHandler\ExceptionHandler;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\RequestInterface;
use Psr\Http\Message\ResponseInterface;
//use app\Log;
use Throwable;
class AppExceptionHandler extends ExceptionHandler
{
protected ExceptionLog $loggerFile;
public function __construct(protected StdoutLoggerInterface $logger)
//public function __construct(LoggerFactory $loggerFactory)
{
$this->loggerFile = new ExceptionLog();
}
public function handle(Throwable $throwable, ResponseInterface $response)
{
//得到请求
$request = ApplicationContext::getContainer()->get(RequestInterface::class);
//得到请求信息
$ip = $request->getServerParams()['remote_addr'];
$time = date("Y-m-d H:i:s"); //访问时间
$method = $request->getMethod();
$url = $request->fullUrl();
$protocol = $request->getProtocolVersion();
$agent = $request->getHeader('user-agent');
$agentStr = implode(",",$agent);
$params = $request->all();
$paramStr = "";
foreach ($params as $k => $value) {
$one = $k."=".$value;
if ($paramStr == "") {
$paramStr = $one;
} else {
$paramStr .= "\n".$one;
}
}
$content = $ip." ".$time." ".$method." ".$url." ".$protocol." ".$agentStr;
$content .= "\nparams:".$paramStr;
$this->loggerFile->info($content);
//写日志到文件
$this->loggerFile->info(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
$this->loggerFile->info($throwable->getTraceAsString());
//输出报错信息到控制台
$this->logger->error(sprintf('%s[%s] in %s', $throwable->getMessage(), $throwable->getLine(), $throwable->getFile()));
$this->logger->error($throwable->getTraceAsString());
// 格式化输出
$data = json_encode([
'code' => $throwable->getCode(),
'message' => $throwable->getMessage(),
], JSON_UNESCAPED_UNICODE);
// 阻止异常冒泡
$this->stopPropagation();
//返回json
return $response->withStatus(500)->withBody(new SwooleStream($data));
}
public function isValid(Throwable $throwable): bool
{
return true;
}
}
说明:默认的logger是 StdoutLoggerInterface,
我们增加了输出到文件的logger
引发异常的代码:
image/ImageController.php
public function imagedetail(RequestInterface $request, ResponseInterface $response) {
$divide = 0;
$res = 100 / $divide;
$data = [
'key' => 'value'
];
return $response->json($data);
}
三,测试效果:
日志内容:
[2025-02-08 14:04:17] exception INFO:192.168.219.1 2025-02-08 14:04:17 GET http://192.168.219.6:9501/image/detail?id=1 1.1
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
params:id=1
[2025-02-08 14:04:17] exception INFO:Division by zero[33] in /data/hyperf/imagebank/app/Controller/ImageController.php
[2025-02-08 14:04:17] exception INFO:#0 /data/hyperf/imagebank/vendor/hyperf/http-server/src/CoreMiddleware.php(148): App\Controller\ImageController->imagedetail()
#1 /data/hyperf/imagebank/vendor/hyperf/http-server/src/CoreMiddleware.php(97): Hyperf\HttpServer\CoreMiddleware->handleFound()
#2 /data/hyperf/imagebank/vendor/hyperf/dispatcher/src/AbstractRequestHandler.php(45): Hyperf\HttpServer\CoreMiddleware->process()
#3 /data/hyperf/imagebank/vendor/hyperf/dispatcher/src/HttpRequestHandler.php(27): Hyperf\Dispatcher\AbstractRequestHandler->handleRequest()
#4 /data/hyperf/imagebank/app/Middleware/AccesslogMiddleware.php(31): Hyperf\Dispatcher\HttpRequestHandler->handle()
#5 /data/hyperf/imagebank/vendor/hyperf/dispatcher/src/AbstractRequestHandler.php(45): App\Middleware\AccesslogMiddleware->process()
#6 /data/hyperf/imagebank/vendor/hyperf/dispatcher/src/HttpRequestHandler.php(27): Hyperf\Dispatcher\AbstractRequestHandler->handleRequest()
#7 /data/hyperf/imagebank/vendor/hyperf/dispatcher/src/HttpDispatcher.php(35): Hyperf\Dispatcher\HttpRequestHandler->handle()
#8 /data/hyperf/imagebank/vendor/hyperf/http-server/src/Server.php(112): Hyperf\Dispatcher\HttpDispatcher->dispatch()
#9 [internal function]: Hyperf\HttpServer\Server->onRequest()
#10 {main}
浙公网安备 33010602011771号