浏览代码

feat: 记录异常日志,追加请求信息方便重现 bug

runphp 1 周之前
父节点
当前提交
1464b486e8
共有 1 个文件被更改,包括 84 次插入0 次删除
  1. 84 0
      src/Exception/ExceptionHandle.php

+ 84 - 0
src/Exception/ExceptionHandle.php

@@ -30,6 +30,90 @@ class ExceptionHandle extends Handle
         });
     }
 
+    /**
+     * 记录异常日志,追加请求信息方便重现 bug
+     */
+    public function report(Throwable $exception): void
+    {
+        if (!$this->isIgnoreReport($exception)) {
+            if ($this->app->isDebug()) {
+                $data = [
+                    'file'    => $exception->getFile(),
+                    'line'    => $exception->getLine(),
+                    'message' => $this->getMessage($exception),
+                    'code'    => $this->getCode($exception),
+                ];
+                $log = "[{$data['code']}]{$data['message']}[{$data['file']}:{$data['line']}]";
+            } else {
+                $data = [
+                    'code'    => $this->getCode($exception),
+                    'message' => $this->getMessage($exception),
+                ];
+                $log = "[{$data['code']}]{$data['message']}";
+            }
+
+            if ($this->app->config->get('log.record_trace')) {
+                $log .= PHP_EOL . $exception->getTraceAsString();
+            }
+
+            // 追加请求信息,方便重现 bug
+            $log .= $this->buildRequestInfo();
+
+            try {
+                $this->app->log->record($log, 'error');
+            } catch (\Exception $e) {
+            }
+        }
+    }
+
+    /**
+     * 构建请求信息,用于异常日志
+     */
+    private function buildRequestInfo(): string
+    {
+        // 命令行模式没有 HTTP 请求,跳过
+        if ($this->app->runningInConsole()) {
+            return '';
+        }
+
+        try {
+            $request = $this->app->request;
+
+            $curl  = PHP_EOL . '--- Curl Command ---';
+
+            $method = $request->method();
+            $url = $request->url(true);
+
+            $curl .= PHP_EOL . 'curl';
+            if ($method !== 'GET') {
+                $curl .= ' -X ' . $method;
+            }
+            $curl .= ' "' . $url . '"';
+
+            // 请求头
+            foreach ($request->header() as $name => $value) {
+                if ('' === $value) {
+                    continue;
+                }
+                $curl .= ' \\' . PHP_EOL . '  -H "' . $name . ': ' . $value . '"';
+            }
+
+            // Body
+            if (in_array($method, ['POST', 'PUT', 'PATCH'])) {
+                $body = $request->getInput();
+                if ($body) {
+                    // 用单引号包裹 body,内部单引号需要转义
+                    $body = str_replace("'", "'\\''", $body);
+                    $curl .= ' \\' . PHP_EOL . "  -d '" . $body . "'";
+                }
+            }
+
+            return $curl;
+        } catch (\Throwable $e) {
+            return PHP_EOL . '--- Request Info: (unavailable) ---';
+        }
+    }
+
     protected function getDebugMsg(Throwable $exception): array
     {
         $debugInfo = parent::getDebugMsg($exception);