让缓存 provider 日志可观测:Astro 运行时 logger 注入上下文与 memoryCache 实践
让缓存 provider 日志可观测Astro 运行时 logger 注入上下文与 memoryCache 实践【免费下载链接】astroThe web framework for content-driven websites. ⭐️ Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/as/astro缓存命中率低、响应被意外跳过缓存、后台刷新静默失败……排查这类问题时日志往往是第一突破口。在较新版本的 Astro 中CacheProvider通过onRequest()接收到的 context 正式加入了logger字段使得自定义缓存 provider 可以不再console.log裸输出而是把日志交给 Astro 运行时统一路由。本篇文章以仓库变更记录 .changeset/plenty-moons-repeat.md 为主体结合缓存 provider 的源码实现讲清楚这个 logger 的类型契约、底层路由机制以及内置memoryCache()的实际接入方式帮助你写出日志规范、可观测的自定义缓存层。logger 进入 cache provider context一次面向可观测性的增强该变更记录的核心改动只有一句话“Addsloggerto the context object passed to cache providers”即向传入自定义 cache provider 的 context 对象中新增logger字段。它的意义在于不再裸写 console。此前 provider 如果要提示“这条响应因为带 cookie 而跳过缓存”只能直接打到控制台无法被 Astro 的日志体系感知日志流向由你配置的 logger destination 决定。消息通过logger输出后会被路由到 astro.config 中logger配置指定的输出端destination并遵守你设置的日志级别log level而不是固定出现在终端调用方代码不变。onRequest()的第二个参数next仍然是继续执行渲染的中间件风格回调只是 context 多了logger这一项。该变更还同步更新了 Astro 内置的memoryCache()provider当它因响应设置 cookie 而跳过缓存、以及当后台 stale-while-revalidateSWR重新验证失败时发出的警告现在都改由这个 logger 输出。CacheProvider 的接口全景先看 provider 被调用时的真实类型契约它定义在 packages/astro/src/core/cache/types.tsexport interface CacheProvider { name: string; setHeaders?(options: CacheOptions, request: Request): Headers; onRequest?( context: { request: Request; url: URL; waitUntil?: WaitUntilHook; logger: AstroRuntimeLogger; }, next: MiddlewareNext, ): PromiseResponse; invalidate(options: InvalidateOptions): Promisevoid; }其中logger的类型为AstroRuntimeLogger是专为运行时runtime场景精简出的只读日志接口。它的完整定义位于 packages/astro/src/types/public/context.tsexport interface AstroRuntimeLogger { info: (msg: string) void; warn: (msg: string) void; error: (msg: string) void; }可见它只有info/warn/error三个方法、无debug入参只有一条消息字符串。provider 内无需关心日志如何输出、输出到哪里只需按语义选择合适的级别调用即可。运行时 logger 从何而来handler 中的实际注入logger并不只是类型层面新增的字段运行时确实会注入一个与当前请求状态绑定的实现。真正的封装点在 packages/astro/src/core/cache/handler.ts当配置的 provider 实现了onRequest时handleCache会调用它并传入一个 logger 对象const response await cacheProvider.onRequest( { request: state.request, url: new URL(state.request.url), waitUntil: state.renderOptions.waitUntil, logger: { info(msg) { state.logger.info(cache, msg); }, warn(msg) { state.logger.warn(cache, msg); }, error(msg) { state.logger.error(cache, msg); }, }, }, async () { const res await next(); applyCacheHeaders(cache!, res, state.request); return res; }, ); // 交给运行时 provider 读取后剥离 CDN 头 response.headers.delete(CDN-Cache-Control); response.headers.delete(Cache-Tag);这段实现印证了变更记录中的描述并透露了几个关键细节标签统一为cache。调用时把日志级别方法分别转发到state.logger.info(cache, msg)等cache作为模块标签出现在日志里方便过滤复用运行时 logger。state.logger是 Astro 在请求处理链中使用的同一个运行时日志实例因此它在 Astro 中配置的日志级别与 destination 会原样生效。例如你在astro.config里配置了 JSON log handlerprovider 的warn输出同样会以 JSON 结构化日志的形式到达该 destinationprovider 内部无需感知输出细节。新增 provider 代码时只需要logger.warn(...)可观测策略完全由宿主Astro/适配器统一决定。作为对照Astro 内部还提供了一个把完整AstroLogger转成AstroRuntimeLogger的工具函数astroToRuntimeLogger()见 packages/astro/src/core/logger/core.ts说明AstroRuntimeLogger正是AstroLogger在公开 API 边界上的精简投影。自定义 provider 怎么用 logger结合 .changeset/plenty-moons-repeat.md 中的示例一个接收 logger 的自定义 provider 骨架如下import type { CacheProvider } from astro; const provider: CacheProvider { name: my-cache, async onRequest({ request, url, logger }, next) { logger.warn(Skipping cache for ${url.pathname} because the response sets a cookie.); return next(); }, // 其余实现setHeaders / invalidate 等 };需要提醒的实现要点logger是从 context 解构得到的可选的onRequest与setHeaders同时存在也不冲突——setHeaders负责为 CDN 型 provider 生成响应头onRequest则接管请求级缓存逻辑见 CacheProvider 中两个方法均可选的定义日志语义上warn适合“本可以缓存但被策略性跳过”的场景如 set-cookie、Vary: *error适合缓存流程本身抛错的场景info适合命中/未命中等普通状态由于url已从 context 解构提供日志里拼接url.pathname无需自己 new URL。内置 memoryCache 的两个接入案例变更记录说明内置的memoryCache()provider 是最先采用新 logger 的代码。在 packages/astro/src/core/cache/memory-provider.ts 中可以看到三处真实调用场景一响应携带 Set-Cookie 时跳过缓存并警告。provider 通过辅助函数hasSetCookieHeader(response)探测响应是否带 cookie随后调用warnSkippedSetCookie(context.logger, requestUrl)其实现第 275-279 行为function warnSkippedSetCookie(logger: AstroRuntimeLogger, url: URL): void { logger.warn( Skipping cache for ${url.pathname}${url.search} because response includes Set-Cookie., ); }注意实际警告文案是because response includes Set-Cookie.比 changeset 里的示例更贴近 memoryCache 的真实输出。场景二Vary头不可缓存时警告。当响应带Vary: Cookie或Vary: *时provider 判定无法按 URL 区分缓存条目删除对应条目并输出警告warnSkippedVary第 281-285 行。场景三SWR 后台重新验证失败。在 stale 命中且触发后台 revalidation 的路径上如果next()返回的 promise 被 reject会在 catch 中通过 logger 输出第 487-493 行.catch((error) { context.logger.warn( Background revalidation failed for ${requestUrl.pathname}${requestUrl.search}: ${String( error, )}, ); });这三个场景正好覆盖了“需要向开发者说明但又不足以抛错”的运行期事件是logger.warn语义的绝佳示范。想理解这些警告在何种缓存状态下被触发可以阅读 provider 的缓存状态机isExpired新鲜期内直接命中、isStale超过 max-age 但仍在 SWR 窗口内命中时返回 stale 并触发后台刷新、以及 miss 路径上的响应序列化逻辑memory-provider.ts。把这一切接到配置上这些 logger 调用要真正生效前提是你启用了 Astro 的缓存 provider。基于 packages/astro/src/types/public/config.ts 中cache与routeRules的类型注释一个最小可运行配置如下// astro.config.mjs import { defineConfig, memoryCache } from astro/config; export default defineConfig({ cache: { provider: memoryCache(), }, routeRules: { /api/[...path]: { swr: 600 }, /products/[...slug]: { maxAge: 3600, tags: [products] }, }, });cache.provider负责控制响应如何被缓存类型为CacheProviderConfig含name、entrypoint、config见 types.tsrouteRules用与文件路由相同的[param]/[...rest]语法按路径声明缓存规则maxAge/swr/tags单位为秒运行时也可以细粒度控制例如在中间件或路由里调用Astro.cache.set()/context.cache.set()未配置 provider 或处于 dev 模式时缓存会退化为 noop/disabled 实现这一点由 packages/astro/src/core/cache/handler.ts 的provideCache负责provider 的日志也因此只在真正启用缓存的 SSR 运行环境中出现。另外由于 memoryCache 的缓存键默认会排序并剔除常见追踪参数若你的页面 URL 带utm_*、fbclid、gclid等参数也更容易命中缓存、减少无效日志噪音——相关默认排除项同样定义在 memory-provider.ts。小结这次向 cache provider context 注入logger的变更实质是让“自定义缓存层”与 Astro 的日志基础设施打通类型上收敛为AstroRuntimeLoggerinfo/warn/error实现上由handleCache统一注入并打上cache标签方向上受astro.config的logger与日志级别约束。内置的memoryCache()已率先迁移到该 logger为跳过 Set-Cookie、Vary 不可缓存、SWR 后台刷新失败三类事件输出了结构化、可过滤的警告。对希望排查“为什么我的响应没被缓存”的开发者配置启用memoryCache()后观察带cache标签的 warn 日志就是最快的切入点对计划实现私有 provider如对接 Redis、CDN API的团队则可以直接把该 logger 作为 provider 与宿主之间的日志契约。【免费下载链接】astroThe web framework for content-driven websites. ⭐️ Star to support our work!项目地址: https://gitcode.com/GitHub_Trending/as/astro创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

最新新闻

日新闻

周新闻

月新闻