This commit is contained in:
2026-09-13 02:28:46 +08:00
parent df5492a48a
commit 42f9530a59
27 changed files with 979 additions and 149 deletions
@@ -0,0 +1,211 @@
---
name: 全项目日志补全 + debug/info/warn 分级
overview: 新建 utils/logger.ts 实现 DEBUG/INFO/WARN/ERROR/SILENT 分级(按 envVersion 自动判定 + config 手动覆盖 + 双输出 console 与 wx.getRealtimeLogManager),然后把 19 个页面、utils、组件、custom-tab-bar 的静默 catch 全部补上分级日志。
todos:
- id: logger-core
content: 新建 utils/logger.ts 实现四级过滤与双通道输出,并在 config.ts 追加 LogLevel 枚举与 LOG_LEVEL 配置
status: completed
- id: migrate-kernel
content: 迁移 request.ts 与 auth.ts 内核日志,补全请求发起/成功/失败/401刷新/登录态失效各节点
status: completed
dependencies:
- logger-core
- id: migrate-existing
content: 迁移 login.ts 与 closet-share-detail.ts 现有 24 处 console.log 为分级 logger 调用
status: completed
dependencies:
- logger-core
- id: explore-pages
content: 用 [subagent:code-explorer] 梳理 17 个页面的生命周期、请求点与静默 catch 精确位置
status: completed
- id: pages-tabcmp
content: 为 wardrobe/outfit/horoscope/closet-share/profile 五个 tab 页补全日志
status: completed
dependencies:
- logger-core
- explore-pages
- id: pages-rest
content: 为其余 12 个页面补全日志,并清除全部 13 处静默 catch
status: completed
dependencies:
- logger-core
- explore-pages
- id: bar-components
content: 为 custom-tab-bar 与 navigation-bar/clothes-card/empty-state 组件补日志
status: completed
dependencies:
- logger-core
- id: verify
content: 校验 lint 零错误,并确认全项目无遗留裸 console.log
status: completed
dependencies:
- migrate-kernel
- migrate-existing
- pages-tabcmp
- pages-rest
- bar-components
---
## 产品概述
为微信小程序「知途衣橱」全项目接入统一的分级日志系统,使开发、体验、生产三种环境下的可观测性可控可调。
## 核心功能
- **分级日志模块**:提供 debug / info / warn / error 四级(外加 SILENT 静默),统一输出格式 `[级别][模块名] 消息`
- **配置化级别控制**:在配置文件中定义日志级别,支持「按环境自动」与「手动写死覆盖」两种模式
- **环境自动映射**:develop(开发版)= DEBUG,trial(体验版)= INFO,release(正式版)= WARN
- **双通道输出**:console 输出(开发者工具可见)+ 微信实时日志(真机后台「实时日志」可查线上问题)
- **全项目覆盖**:17 个页面、请求内核、token 模块、自定义 tab-bar、3 个公共组件,覆盖生命周期、请求成败、用户操作、跳转失败
- **消除静默失败**:全部 13 处 `.catch(() => {})` 改为 `.catch((e) => logger.warn(...))`
## 技术栈
- 微信小程序原生框架 + TypeScript(`miniprogram-api-typings`)
- 现有工具层:`utils/config.ts`(纯常量)、`utils/request.ts`(请求内核)、`utils/auth.ts`(token)
- 无构建脚本、无本地 TS 编译器,仅依赖 IDE lint 校验
## 实现方案
### 核心策略
新建单一日志模块 `utils/logger.ts` 作为全项目唯一日志出口,所有页面通过 `logger.xxx('模块名', ...)` 调用;级别策略通过 `config.ts` 中的 `LOG_LEVEL` 常量控制。
### 关键技术决策
**决策 1:LogLevel 枚举定义在 config.ts 而非 logger.ts**
- 原因:`logger.ts` 需要 import `config.ts` 读取 `LOG_LEVEL`,若枚举定义在 logger 而 config 又要引用它,会形成 `config → logger → config` 循环依赖。
- 方案:枚举与配置常量都放 `config.ts`(本身零依赖的纯常量文件),依赖方向保持单向 `logger → config`。
- 收益:既满足「在配置里分级」的要求,又彻底避免循环依赖。
**决策 2:级别用 `LogLevel | null` 表示,null 代表自动**
- `LOG_LEVEL = null`(默认)→ 运行时调 `wx.getAccountInfoSync().miniProgram.envVersion` 判定环境
- 需要临时调级时改写为 `LogLevel.DEBUG` 等具体值即可,不改代码逻辑
**决策 3:实时日志用 `wx.getRealtimeLogManager()`**
- 相比 `wx.getLogManager()`,实时日志可在小程序后台「实时日志」秒级查询,更适合线上排障
- 单例惰性初始化,取不到时(低版本基础库/开发者工具)降级为仅 console,不抛错
- 实时日志有单条长度限制,参数序列化时截断保护
**决策 4:实时日志写入范围限制在 WARN 及以上**
- 实时日志有频率与体积配额,DEBUG/INFO 全量上报会击穿配额并产生噪声
- 故:console 输出按级别过滤;实时日志仅 WARN/ERROR 写入
### 性能与可靠性
- **热路径控制**:`request.ts` 的请求日志放到 debug 级,生产环境(WARN)自动零开销——级别判断前置,不做字符串拼接
- **参数序列化成本**:日志消息用 `...args` 原样透传,不主动 `JSON.stringify` 大对象;仅在实时日志通道对超长内容截断
- **无额外依赖**:不引入任何第三方库,包体积影响可忽略
- **降级安全**:`getRealtimeLogManager` 不可用时静默降级,绝不因日志抛错影响业务
## 架构设计
```mermaid
graph TD
A[config.ts<br/>LogLevel 枚举 + LOG_LEVEL 配置] --> B[logger.ts<br/>级别过滤 / 格式化 / 双通道输出]
B --> C[console 输出<br/>DEBUG 及以上]
B --> D[wx.getRealtimeLogManager<br/>仅 WARN 及以上]
E[request.ts 请求内核] --> B
F[auth.ts token 模块] --> B
G[17 个页面] --> B
H[custom-tab-bar] --> B
I[3 个公共组件] --> B
```
依赖方向严格单向:所有业务模块 → logger → config,无反向依赖、无循环依赖。
### 日志级别语义约定
| 级别 | 用途 | 典型场景 |
| --- | --- | --- |
| DEBUG | 开发期流程细节 | 页面 onLoad/onShow 及入参、请求发起、请求成功、数据条数 |
| INFO | 关键流程节点 | 登录成功、token 刷新成功、下单/支付发起、上传成功、分享创建成功 |
| WARN | 可恢复异常 / 静默降级 | 静默 catch、跳转失败、额度查询失败、非关键请求失败 |
| ERROR | 真正的错误 | 网络异常、业务错误码、账号禁用、登录态失效跳转 |
## 目录结构
```
miniprogram/
├── utils/
│ ├── config.ts # [MODIFY] 末尾追加日志配置区块:LogLevel 枚举(DEBUG/INFO/WARN/ERROR/SILENT)、
│ │ # LOG_LEVEL 主开关(null=按环境自动)、LOG_TO_REALTIME 实时日志开关、
│ │ # LOG_MODULE_MAX_LEN 等常量。注意此文件零依赖,不得 import 任何模块。
│ ├── logger.ts # [NEW] 全项目唯一日志出口。实现级别过滤、模块名格式化、双通道输出。
│ │ # 导出 logger.debug/info/warn/error 与 setLevel 运行时调级接口。
│ ├── request.ts # [MODIFY] 迁移现有 10 处 console.log;补全 request/uploadFile 生命周期日志:
│ │ # 请求发起(debug)/成功(debug)/业务错误(warn)/网络异常(error)/
│ │ # 401 刷新(info)/刷新失败(warn)/登录态失效跳转(error)。
│ └── auth.ts # [MODIFY] token 存取关键节点补 debug/warn 日志。
├── pages/ # [MODIFY] 17 个页面全部接入,详见下方任务拆分
├── custom-tab-bar/
│ └── index.ts # [MODIFY] 未读红点轮询、switchTab 跳转、节流命中补日志
└── components/ # [MODIFY] navigation-bar / clothes-card / empty-state 关键回调补日志
```
## 关键代码结构
`utils/config.ts` 追加(零依赖,供 logger 单向引用):
```ts
// ===== 日志配置 =====
// 日志级别:数值越大越严重,低于当前级别的日志不输出
export enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3,
SILENT = 4, // 全部关闭
}
// 全局日志级别。null = 按运行环境自动判定(develop=DEBUG / trial=INFO / release=WARN)
// 需要临时调级时直接改写为具体值,例如 LogLevel.DEBUG
export const LOG_LEVEL: LogLevel | null = null
// 是否写入微信实时日志(真机可在后台「实时日志」查看)
export const LOG_TO_REALTIME = true
```
`utils/logger.ts` 对外接口(实现体不含):
```ts
import { LogLevel, LOG_LEVEL, LOG_TO_REALTIME } from './config'
// 运行时生效级别(LOG_LEVEL 为 null 时按 envVersion 自动推导)
export function getLevel(): LogLevel
export function setLevel(level: LogLevel | null): void
export const logger: {
debug(module: string, ...args: any[]): void
info(module: string, ...args: any[]): void
warn(module: string, ...args: any[]): void
error(module: string, ...args: any[]): void
}
```
## 实施注意事项
- **循环依赖红线**:`config.ts` 必须保持零 import,任何需要 `LogLevel` 的地方统一从 `config.ts` 引入
- **迁移而非新增**:现有 24 处 `console.log` 全部改为 `logger.*`,不得遗留裸 `console.log`(保持项目可 grep 性)
- **静默 catch 全清**:13 处 `.catch(() => {})` 逐个补 `logger.warn`,保留原有降级行为不变,只加观测
- **不动业务逻辑**:本次只加观测点与级别控制,不修改任何请求/跳转/状态逻辑,控制变更半径
- **模块名规范**:统一用页面目录名或文件名,如 `wardrobe`、`request`、`custom-tab-bar`
- **不打印敏感信息**:token、code 等只打长度或存在性,不打印完整值
## 工作量分布
- 基础模块(config + logger):2 个文件
- 内核层(request + auth):2 个文件,约 20+ 个日志点
- 页面层:17 个页面,每页 4-10 个日志点(含 13 处静默 catch)
- 组件与 tab-bar:4 个文件
## SubAgent
- **code-explorer**
- 用途:批量梳理 17 个页面的生命周期方法、请求调用点、跳转 fail 回调与静默 catch 的精确行号,避免逐文件全量读取造成的上下文浪费
- 预期结果:产出各页面待加日志的精确位置清单,作为批量改造的执行依据