错误日志没有准确堆栈信息

二环狄仁杰

问题描述

补充:进程是 Fiber 协程环境。

我在 service 里写了会出异常的代码,控制器里调用,错误信息没有把controller到 service的链路打印出来。
这导致我无法定位问题代码,应该怎么做才能显示完整堆栈信息。

service 方法

    public function getTopNsymbols(int $limit = 100): array
    {
        $api = 'http://a.com/index/json';
        $httpClient = new Client();
        $response = $httpClient->get($api);
        $httpStatusCode = $response->getStatusCode();
        $data = json_decode($response->getBody(), true);
        if ($httpStatusCode == 429) {
            throw new BusinessException("错误 429,访问频率超过限制", 5000);
        }
        if ($httpStatusCode == 418) {
            throw new BusinessException("错误 418,IP 被封了", 5000);
        }
        if ($httpStatusCode !== 200) {
            throw new BusinessException("其他错误" . $httpStatusCode, 5000);
        }

        uasort($data, function ($a, $b) {
            return $b['quoteVolume'] <=> $a['quoteVolume'];
        });

        return array_slice($data, 0, $limit);
    }

controller 方法

public function test(Request $request)
{
    $demoService = new DemoService();
    $data = $demoService->getTopNsymbols(10);
    var_dump($data);
    return json($data);
}

页面报错内容:
截图

错误日志内容:
截图

355 2 0
2个回答

北月妖王
$api = 'http://a.com/index/json';
$httpClient = new Client();
$response = $httpClient->get($api);

其实是在这里抛出的异常,你没有进行拦截,所以在这里中断了。

  • 二环狄仁杰 2025-09-05

    只能防御性编程,try 起来吗?

  • 二环狄仁杰 2025-09-05

    我想要代码里没有严谨的 try 到的部分,也全部能被日志记录起来,应该怎么做呐

二环狄仁杰

换成这个客户端就有完整的日志了:https://www.workerman.net/plugin/94
我有点迷茫了。

  • lsmir2 2025-09-05

    你这里导入的是那个?
    https://www.workerman.net/doc/workerman/components/workerman-http-client.html
    是这个吗?

    composer require workerman/http-client
     $httpClient = new Client();
     $response = $httpClient->get($api);
  • 二环狄仁杰 2025-09-06

    是的

  • lsmir2 2025-09-09

    直接用 $httpClient->request 封装一个通用类就可以了 $httpClient->get() 不适合使用在封装类里面 只能直接在控制类使用.具体的自己看文档 webman 部分
    我是这么写的

     private static WorkermanClient $client;
        private array $options = ['max_conn_per_addr' => 128, 'keepalive_timeout' => 30, 'connect_timeout' => 10, 'timeout' => 10];
        private array $headers = ['Connection' => 'keep-alive'];
        private string $method = 'POST';
        private bool $isJson = true;
    
        private array $retryData = [];
    
        public function __construct()
        {
            if (!isset(self::$client)) self::$client = new WorkermanClient();
        }
    
        public function get(string $url): string
        {
            $this->method = 'GET';
            return self::request($url, [])->getBody()->getContents();
        }
    
     /**
         * 发起 HTTP 请求
         *
         * @param string $url
         * @param array $data
         * @param callable|null $successCallback 成功回调函数
         * @param callable|null $errorCallback 错误回调函数
         * @return mixed|\Workerman\Http\Response
         * @throws Throwable
         */
        private function request(string $url, array $data, callable $successCallback = null, callable $errorCallback = null): mixed
        {
            if ($this->isJson) {
                $this->headers['Content-Type'] = 'application/json';
                $data = json_encode($data);
            } else {
                $this->headers['Content-Type'] = 'application/x-www-form-urlencoded';
            }
            global $isdebug;
            if ($isdebug) $this->headers['cookie'] = "XDEBUG_SESSION=PHPSTORM";
    
            $oprions = [
                'method' => $this->method,
                'version' => '1.1',
                'headers' => $this->headers,
                'data' => $data,
                'success' => $successCallback,
                'error' => $errorCallback,
            ];
    
            $oprions = array_merge($this->options, $oprions);
    
            // 发起异步请求
            return self::$client->request($url, $oprions);
        }
🔝