Files
AIclinicalresearch/docs/05-部署文档/14-Node.js后端-pino-pretty问题修复.md
HaHafeng b31255031e feat(iit-manager): Add WeChat Official Account integration for patient notifications
Features:
- PatientWechatCallbackController for URL verification and message handling
- PatientWechatService for template and customer messages
- Support for secure mode (message encryption/decryption)
- Simplified route /wechat/patient/callback for WeChat config
- Event handlers for subscribe/unsubscribe/text messages
- Template message for visit reminders

Technical details:
- Reuse @wecom/crypto for encryption (compatible with Official Account)
- Relaxed Fastify schema validation to prevent early request blocking
- Access token caching (7000s with 5min pre-refresh)
- Comprehensive logging for debugging

Testing: Local URL verification passed, ready for SAE deployment

Status: Code complete, waiting for WeChat platform configuration
2026-01-04 22:53:42 +08:00

6.1 KiB
Raw Blame History

Node.js 后端 - pino-pretty 问题修复记录

修复时间2025-12-24 问题原因生产环境使用了开发依赖pino-pretty 解决方案根据环境变量条件化使用pino-pretty


🐛 问题描述

错误信息

Error: unable to determine transport target for "pino-pretty"
    at fixTarget (/app/node_modules/pino/lib/transport.js:160:13)

根本原因

  1. pino-pretty 是一个devDependency(开发依赖)
  2. Dockerfile使用 npm ci --production 只安装生产依赖
  3. pino-pretty 不会被安装到生产环境
  4. src/index.ts 中硬编码了 pino-pretty 作为日志格式化工具
  5. 生产环境启动时找不到 pino-pretty,导致崩溃

解决方案

1. 修改代码 - 条件化使用pino-pretty

文件backend/src/index.ts

修改前第29-41行

const fastify = Fastify({
  logger: {
    level: config.logLevel,
    transport: {
      target: 'pino-pretty',  // ❌ 硬编码,生产环境会报错
      options: {
        colorize: true,
        translateTime: 'HH:MM:ss Z',
        ignore: 'pid,hostname',
      },
    },
  },
});

修改后

// 生产环境使用JSON格式日志性能更好开发环境使用pino-pretty易读
const fastify = Fastify({
  logger: config.nodeEnv === 'production' 
    ? {
        level: config.logLevel,
        // 生产环境简单的JSON日志适合日志收集系统
      }
    : {
        level: config.logLevel,
        // 开发环境使用pino-pretty美化输出
        transport: {
          target: 'pino-pretty',
          options: {
            colorize: true,
            translateTime: 'HH:MM:ss Z',
            ignore: 'pid,hostname',
          },
        },
      },
});

关键改进

  • 根据 NODE_ENV 条件化配置
  • 生产环境使用原生JSON日志性能更好适合ELK/Loki等日志系统
  • 开发环境使用pino-pretty易读便于调试

2. 重新编译TypeScript

cd backend
npm run build

编译结果 成功

3. 重新构建镜像 v1.2

docker build -t crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.2 .

构建结果

  • 构建成功
  • 耗时8.4秒(快速,大部分层使用缓存)

4. 推送到ACR

docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.2

推送结果

  • 推送成功
  • Digest: sha256:dd48750c5032681613776ea484a2194622e3926c6f49a1d7246105c090ecce35

📦 版本对比

项目 v1.0 v1.1 v1.2(最新)
问题 缺少config 修复 修复
问题 - pino-pretty 修复
状态 启动失败 启动失败 待验证
修改内容 - +config目录 +条件化日志配置
构建时间 ~5分钟 ~1分钟 ~8秒

🎯 下一步操作

步骤1登录SAE控制台

访问:https://sae.console.aliyun.com/

步骤2更新镜像版本为 v1.2

  1. 找到应用:nodejs-backend-test
  2. 配置管理 → 部署配置 → 镜像设置
  3. 修改镜像版本:
    backend-service:v1.1
    改为backend-service:v1.2  ✨
    

步骤3重新部署并验证

  1. 保存并重新部署
  2. 查看实时日志
  3. 成功标志

期望的日志格式JSON格式不是pretty格式

{"level":30,"time":1703472498828,"pid":1,"hostname":"xxx","msg":"Server listening at http://0.0.0.0:3001"}
{"level":30,"time":1703472498830,"pid":1,"hostname":"xxx","msg":"Config loaded: /app/config/agents.yaml"}
{"level":30,"time":1703472498832,"pid":1,"hostname":"xxx","msg":"Database connected successfully"}

不应该出现

  • Error: unable to determine transport target for "pino-pretty"
  • 任何关于pino-pretty的错误

📊 为什么生产环境不用pino-pretty

性能对比

指标 原生JSON pino-pretty
吞吐量 ~30,000 log/s ~3,000 log/s
CPU使用 高(格式化开销)
内存使用
适用场景 生产环境 开发环境

日志系统集成

生产环境最佳实践

应用输出JSON日志
    ↓
SAE/K8s收集stdout/stderr
    ↓
日志系统ELK/Loki/阿里云SLS
    ↓
可视化分析Kibana/Grafana

JSON格式日志更适合

  • 结构化查询(字段级搜索)
  • 日志聚合和分析
  • 告警规则配置
  • 性能监控

🔍 本地测试验证

如果想在本地验证修复,可以这样测试:

测试生产环境日志格式

# 设置生产环境变量
export NODE_ENV=production

# 启动应用
npm run dev

# 观察日志输出应该是JSON格式

测试开发环境日志格式

# 设置开发环境变量
export NODE_ENV=development

# 启动应用
npm run dev

# 观察日志输出应该是pretty格式彩色、易读

💡 经验教训

1. 开发依赖管理

  • DO将格式化工具如pino-pretty放在devDependencies
  • DO:生产环境使用原生日志格式
  • DON'T在生产环境依赖devDependencies

2. 环境适配

  • DO根据NODE_ENV配置不同的行为
  • DO:生产环境优先考虑性能
  • DO:开发环境优先考虑易用性

3. Docker镜像优化

  • DO:使用 npm ci --production 减小镜像体积
  • DO:在代码中适配生产环境
  • DON'T:为了方便在生产环境安装所有依赖

📝 修复总结

问题根源:代码未适配生产环境(硬编码开发工具)
修复方式:添加环境判断,条件化配置
影响范围:仅日志输出格式,不影响功能
修复时间约10分钟编译2分钟 + 构建8秒 + 推送1分钟
版本号v1.2


文档创建时间2025-12-24
维护人员:运维团队