From 2f4d414412bf29a4cbeab1aedd0927aa078caf06 Mon Sep 17 00:00:00 2001 From: chenhang Date: Thu, 11 Jun 2026 14:58:54 +0800 Subject: [PATCH] feat(utils): add structured error logging to Result.wrap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Integrate the Logger into `Result.wrap` so that caught exceptions are recorded with stack trace, error type, and a `component: "Result"` tag before being wrapped into a `Result`. Errors are first normalized via `toError` to preserve `.stack`, `.code`, and `.status` fields, then logged through the standard pipeline (dev console in development, JSON pipeline in production). Callers continue to receive a `Result` — re-throwing remains opt-in via `Result.unwrap`. --- src/utils/result.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/utils/result.ts b/src/utils/result.ts index 589908f1..bb6eab20 100644 --- a/src/utils/result.ts +++ b/src/utils/result.ts @@ -14,10 +14,15 @@ * (`ApiError extends Error`),仓库 `Result.wrap` 捕获后用 `toError` 规范化, * 调用方能可靠地 `instanceof ApiError` / `error.message` 访问错误信息。 */ +import { Logger } from "./logger"; + export type Result = | { readonly success: true; readonly data: T } | { readonly success: false; readonly error: Error }; +/** 仓库层 Result.wrap 专用 logger —— 自动带 component: "Result" 标签 */ +const log = new Logger("Result"); + export const Result = { /** 构造成功结果。 */ ok(data: T): Result { @@ -49,12 +54,24 @@ export const Result = { /** * 捕获异步 thunk 的异常并包装成 `Result`。仓库内主要用这个把 * `*Api` 调用从「throw 风格」桥接到「Result 风格」。 + * + * 错误处理策略(重点): + * 1. 捕获后用 `toError` 规范化(保留 .stack / .code / .status 等字段) + * 2. **用 Logger 记录**(带 stack + component=Result 标签)—— 调试 dev 控制台可见, + * 生产环境走 JSON pipeline 接入日志平台 + * 3. **不**重新抛出 —— 调用方拿到的永远是 `Result`(throw 风格调用方可在 + * 最外层显式 `throw Result.unwrap(r)`) */ async wrap(thunk: () => Promise): Promise> { try { return Result.ok(await thunk()); } catch (e) { - return Result.err(e); + const err = toError(e); + log.error( + { err, stack: err.stack, type: err.constructor.name }, + "Result.wrap caught exception", + ); + return Result.err(err); } }, } as const;