
Remix logger-middleware 完全指南请求/响应访问日志、Token 格式化与 context.logger【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remixremix-run/logger-middleware是 Remix 框架内置的 HTTP 请求/响应日志中间件它记录请求元数据与响应细节支持 token 化自定义输出格式并把配置好的日志函数暴露到请求上下文上。本文以该包的 CHANGELOG 为脉络结合 README 与 logger.ts 源码完整讲解它的能力、演进历史与底层实现。一、这是什么一个函数即可接入的访问日志中间件logger-middleware 是一个面向 Fetch API 中间件链的请求/响应日志器。在createRouter的middleware数组中挂载logger()后每个经过它的请求都会在响应返回时输出一行结构化访问日志同时把日志函数以context.logger或context.get(Logger)的形式注入上下文供业务代码复用同一个日志通道。核心能力一览源自 README请求/响应日志记录 method、path、status 与响应元数据上下文日志器暴露context.logger或context.get(Logger)Token 化格式用内置占位符自由定制输出模板结构化计时数据包含请求耗时与时间戳彩色输出在 TTY 输出中高亮 method、status、duration、contentLength二、快速上手两行代码接入访问日志安装后本包作为remix的组成部分npm i remix即可从remix/middleware/logger导入import { createRouter } from remix/router import { logger } from remix/middleware/logger let router createRouter({ middleware: [logger()], }) router.get(/users/:id, (context) { context.logger(Loading user ${context.params.id}) return Response.json(loadUser(context.params.id)) }) // 输出示例: [19/Nov/2025:14:32:10 -0800] GET /users/123 200 1234默认输出格式即[%date] %method %path %status %contentLength与 Apache/nginx 的访问日志风格一致。%date具体由formatApacheDate生成形如23/Sep/2025:11:34:12 -0700dd/Mon/yyyy:HH:mm:ss ±zzzz实现见 logger.ts。按环境启用仓库内多个 demo 的通用做法是仅在开发环境挂载日志中间件例如 demos/bookstore/app/router.ts、demos/frames/app/router.tslet middleware [] if (process.env.NODE_ENV development) { middleware.push(logger()) } middleware.push(compression()) // createRouter({ middleware })三、Token 格式化18 个占位符自由组合format选项决定了日志输出模板。完整的 token 列表来自 logger.ts 与 READMEToken含义%dateApache/nginx 格式日期时间dd/Mon/yyyy:HH:mm:ss ±zzzz%dateISOISO 8601 格式时间%duration请求耗时毫秒%contentLength响应Content-Length头%contentType响应Content-Type头%host请求 URL 的 host%hostname请求 URL 的 hostname%method请求方法%pathpathname search%pathname仅 pathname%port请求端口%query查询字符串search%referer请求Referer头%search请求 search 字符串%status响应状态码%statusText响应状态文本%url完整请求 URL%userAgent请求User-Agent头源码中还额外注册了%protocolurl.protocoltoken虽然未列入文档但可以直接使用。自定义示例let router createRouter({ middleware: [ logger({ format: %method %path - %status (%duration ms), }), ], }) // 输出: GET /users/123 - 200 (42 ms)Apache combined 格式便于接入access.log分析工具链let router createRouter({ middleware: [ logger({ format: %host - - [%date] %method %path %status %contentLength %referer %userAgent, }), ], })底层替换规则日志渲染的核心逻辑只有一行logger.tslet message format.replace(/%(\w)/g, (_, key) tokens[key]?.() ?? -)所有 token 都是惰性求值的函数只有出现在 format 中才会被调用未识别的 token 一律渲染为-缺头字段如无Referer也统一输出-保证日志行格式稳定、可解析。四、v0.2.0 核心特性高信号 token 的彩色输出v0.2.0 是功能演进的重要节点见 CHANGELOG 对应条目Colorize high-signal logger tokens when terminal color detection allows it by default, with acolorsoption to force colorized output on or off and support forCI,NO_COLOR,FORCE_COLOR,TERMdumb, and TTY output streams when theprocessglobal is defined.也就是说终端颜色检测允许时默认开启着色同时提供colors选项强制开/关当定义了process全局时颜色检测会尊重CI、NO_COLOR、FORCE_COLOR、TERMdumb以及 TTY 输出流等因素。colors 选项用法let router createRouter({ middleware: [ logger({ colors: false, // 或 true 强制开启 }), ], })colors默认值为undefined自动检测底层通过remix-run/terminal的createStyles({ colors: option })实现logger.ts因此检测逻辑与 terminal 包一致。彩色 token 与配色规则开启着色后以下 4 类 token 会按严重程度分级着色源码 getColorizer%methodGET/HEAD 绿、POST 青、PUT/PATCH 黄、DELETE 红、OPTIONS 品红%status≥500 红、≥400 黄、≥300 青、≥200 绿%duration≥1000ms 红、≥500ms 品红、≥100ms 黄、其余绿%contentLength≥1MB 红、≥100KB 黄、≥1KB 青、其余不着色非法/缺失的 Content-Length 不着色parseContentLength要求必须是安全的非负整数否则视为undefinedlogger.ts测试用例leaves invalid content lengths uncolored验证了这一点。自动检测的边界条件logger.test.ts 用一整套环境模拟用例锁定了行为设置NO_COLOR1时默认关闭颜色respects NO_COLORcolors: true可无视NO_COLOR强制开启forces colors onTTY 输出流下默认开启enables colors in TTY非 TTY 下默认关闭leaves colors off outside TTY实际应用中这意味着开发终端里日志是彩色的、一目了然管道重定向或 CI 中则自动退化为纯文本便于 grep 和落盘。五、v0.3.0 核心特性context.logger 上下文日志器v0.3.0 的 Minor 变更logger()now installs the configured log function ascontext.loggerin addition to using it for request/response access logs.即logger()现在除了把 log 函数用于访问日志外还会将其安装为context.logger。实现位置在中间件入口的第一行logger.tsreturn async (context, next) { context.set(Logger, log, { property: logger }) ... }context.set的property: logger让日志函数可以直接以context.logger(...)访问同时导出的Loggercontext keyindex.ts 重新导出支持类型安全地context.get(Logger)读取// 两种等价写法 context.logger(direct) context.get(Logger)(keyed)测试用例provides the configured logger on request context验证了两者输出完全一致且业务日志与访问日志走同一个log函数顺序为业务日志在前、访问日志在后。六、自定义 Logger写文件、接流、进收集系统log选项接受任意(message: string) void函数默认console.log。把它替换掉即可把日志写到任意目标import { createWriteStream } from node:fs let logStream createWriteStream(access.log, { flags: a }) let router createRouter({ middleware: [ logger({ log(message) { logStream.write(message \n) }, }), ], })结合上一节可知自定义log不仅接管访问日志也会接管业务侧context.logger(...)的输出因此可以做到一套输出通道、两类日志统一收集——无论是落文件、接 stdout、还是投递给日志聚合服务都只需替换这一个函数。七、其他配置要点与默认值速查完整的LoggerOptions定义见 logger.ts三个选项及默认值汇总选项类型默认值说明formatstring[%date] %method %path %status %contentLength日志模板token 见上文表格log(message: string) voidconsole.log实际输出函数同时注入context.loggercolorsboolean \| undefinedundefined自动检测true强制着色false强制关闭此外 CHANGELOG 中还有两条与依赖形态相关的记录v0.1.1把remix-run/*的 peer dependencies 改为 regular dependencies安装时不再需要手工配对版本package.json 中remix-run/fetch-router、remix-run/terminal均为普通依赖。v0.1.02025-11-19初始版本从remix-run/fetch-routerv0.9.0 中提取独立成包。八、包结构与版本演进时间线包结构packages/logger-middleware/ ├── src/ │ ├── index.ts # 重导出 logger / Logger / 类型 │ └── lib/ │ ├── logger.ts # 中间件与格式化、着色实现 │ └── logger.test.ts # 行为测试上下文注入/格式/颜色/环境检测 ├── README.md # 使用文档 ├── CHANGELOG.md # 版本演进记录 └── package.jsonremix-run/logger-middleware通过 packages/remix/manifest.json 映射为remix/middleware/logger入口这正是所有 demo 与文档统一使用import { logger } from remix/middleware/logger的原因。版本演进v0.1.0 → v0.3.5从 CHANGELOG 可以清晰看到两条主线功能主线v0.1.0 从 fetch-router 独立 → v0.1.1 依赖形态调整 →v0.2.0 引入彩色输出与 colors 选项→v0.3.0 引入 context.logger依赖主线v0.1.2 至 v0.3.5 的多数 Patch 版本均为同步remix-run/fetch-routerv0.16.0 → v0.21.0与remix-run/terminalv0.1.0、v0.1.1的升级跟随主路由框架的版本节奏这也提示了升级时的注意点由于fetch-router是普通依赖升级remix全家桶时logger-middleware会随 workspace 版本一起联动无需单独处理。九、在中间件链中的定位通常放最前文档 03-request-handling.md 对logger()的定位说明是Logs the request and downstream response and providescontext.logger(...). Usually first so early responses and404s are logged.从源码实现也能印证logger中间件在await next()之前只做两件事设置 context key、记录起始时间随后等待下游中间件与路由处理完成再统一渲染日志行logger.ts。因此放在中间件链最前面时即使下游提前短路返回如静态资源命中、权限校验失败、404 未匹配日志仍然会输出——这正是推荐用法。let router createRouter({ middleware: [logger(), compression(), formData(), session(), render()], })十、小结logger-middleware 用极小的 API 表面一个logger(options)函数、三个选项覆盖了访问日志的常见诉求token 化格式对齐 Apache/nginx 生态、终端彩色分级提示高信号字段、context.logger打通业务日志通道、自定义log函数任意落盘。结合 logger.test.ts 的完整用例集可以放心地将它作为中间件链的第一环接入在开发调试与生产可观测性之间获得一致的体验。【免费下载链接】remixThe fully-stacked web framework项目地址: https://gitcode.com/GitHub_Trending/re/remix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考