Skip to content

调试与可观测性 ​

需要知道请求有没有重试、为什么失败时,可以传入 onRequestEvent。需要统计完整调用耗时,则在调用外层计时。

记录请求事件 ​

ts
import { createHanaMusicApi } from 'hana-music-api';

const hana = createHanaMusicApi({
  onRequestEvent(event) {
    console.log({
      type: event.type,
      attempt: event.attempt,
      status: event.status,
      durationMs: event.durationMs,
      delayMs: event.delayMs,
      url: event.url,
    });
  },
});

await hana.search({ keywords: '海阔天空' });

回调只用于观测,应保持轻量并避免抛错。事件 URL 已移除 query,事件不提供 Cookie 字段;自定义日志也不要记录凭据或完整请求正文。

事件表示什么
attempt请求内核开始一次尝试
retry这次失败符合重试规则,接下来按 delayMs 等待
failure请求尝试遇到无法继续重试的失败

attempt 不等于请求已经真正发出,不能直接拿它当上游实际请求数。一次最终成功的调用也可能先出现多个 attempt 和 retry。

每个字段怎样理解 ​

字段含义
attempt、maxAttempts当前尝试序号和请求层记录的尝试上限;不表示必定会重试
connectionStrategy这次尝试使用的连接策略
cryptoAPI 加密模式,普通文本或字节请求使用空字符串
url移除 query 后的请求地址
status、error可用时提供失败状态或错误信息
durationMs通常为这次失败尝试的耗时,不是稳定的整次调用耗时
delayMs下一次尝试前的等待时间

这些字段的公开类型是 RequestDebugEvent。参数检查失败、缓存命中、模块本地计算或外层取消等情况,不一定产生对应请求事件。共享读取只执行一次上游工作,也不会替每个等待者各发一套事件。

因此不要依赖 failure 统计所有调用失败,也不要把没有 failure 当成调用成功的证明。直接 createRequest 的边界还会补充部分取消或超时失败事件,其耗时范围与普通请求尝试可能不同。

统计完整调用耗时 ​

ts
import { search } from 'hana-music-api';

const startedAt = performance.now();
try {
  const result = await search({ keywords: '海阔天空' });
  console.log(result.status, result.body);
} catch (error: unknown) {
  console.error(error);
} finally {
  console.log({ elapsedMs: performance.now() - startedAt });
}

这样能把身份初始化、缓存等待、重试和正文读取算在同一次调用里。错误对象的处理见 返回值与错误。

什么时候需要自定义 fetcher ​

onRequestEvent 观察请求内核的尝试与重试。自定义 fetcher 则能看到真正交给传输实现的 URL、请求头和响应,可以用于连接管理或测试。

包装 fetch 后立刻返回 Response,测到的通常只是收到响应头之前的时间;后续读取正文仍由内核完成。自定义实现与取消要求见 自定义 fetcher。

维护者可以继续阅读 架构详解,以及仓库中的 tests/load/ 和 agent-docs/TESTING.md。

Released under the MIT License.