# HTTP 日志记录方案 - 部署指南 ## 📋 方案概述 使用 **Express + morgan** 中间件在应用层记录所有 HTTP 请求日志,无需 Nginx。 ### 架构流程 ``` 用户请求 (51703-51707) ↓ PM2 启动 server.js (每个端口一个实例) ↓ Express 服务器 ↓ morgan 中间件(记录 HTTP 日志) ↓ Remix 应用处理 ↓ 返回响应 + 日志写入 PM2 日志文件 ``` ### 关键特性 - ✅ **记录所有 HTTP 请求**(页面、API、静态资源) - ✅ **不同地区独立日志文件**(logs/meizhou-out.log, logs/yunfu-out.log...) - ✅ **自定义日志格式**(开发环境彩色,生产环境详细) - ✅ **零性能损耗**(morgan 性能优化极佳) - ✅ **无需 Nginx**(简化架构) --- ## 🚀 部署步骤 ### 第 1 步:安装依赖 在项目根目录执行: ```bash npm install ``` 这会安装以下新增依赖: - `express` - Web 服务器框架 - `compression` - 响应压缩(提升性能) - `morgan` - HTTP 请求日志记录 - `chalk` - 控制台彩色输出(开发环境) - `@remix-run/express` - Remix Express 适配器 以及相关类型定义: - `@types/express` - `@types/compression` - `@types/morgan` ### 第 2 步:构建应用 ```bash # 测试环境 npm run build:test:multi # 或生产环境 npm run build:production:multi ``` ### 第 3 步:重启 PM2 服务 ```bash # 停止所有实例 pm2 stop all # 删除所有实例(可选,清理旧配置) pm2 delete all # 启动新配置 pm2 start ecosystem.config.cjs --env production # 查看状态 pm2 status ``` ### 第 4 步:验证日志记录 #### 4.1 访问应用 ```bash # 访问梅州实例 curl http://10.79.97.17:51703 # 访问云浮实例 curl http://10.79.97.17:51704 ``` #### 4.2 查看日志 ```bash # 实时查看梅州实例日志 pm2 logs docreview-main-meizhou # 查看所有实例日志 pm2 logs # 或直接查看日志文件 tail -f logs/meizhou-out.log ``` **预期日志格式(生产环境):** ``` [2025-01-10T15:30:45.123Z] 172.16.0.34 meizhou:51703 GET / HTTP/1.1 200 4567 bytes 150 ms "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" [2025-01-10T15:30:46.234Z] 172.16.0.34 meizhou:51703 POST /api/documents HTTP/1.1 201 234 bytes 85 ms "http://10.79.97.17:51703/documents" "Mozilla/5.0..." [2025-01-10T15:30:47.345Z] 172.16.0.34 meizhou:51703 GET /build/main.js HTTP/1.1 200 125678 bytes 5 ms "http://10.79.97.17:51703/" "Mozilla/5.0..." ``` **预期日志格式(开发环境,彩色):** ``` GET /documents 200 150 ms - 4567 bytes POST /api/documents 201 85 ms - 234 bytes GET /build/main.js 200 5 ms - 125678 bytes ``` --- ## 📊 日志格式说明 ### 生产环境日志格式 ``` [ISO时间] 客户端IP 客户端ID:端口 方法 URL HTTP版本 状态码 响应大小 响应时间 "来源" "User-Agent" ``` **字段说明:** | 字段 | 示例 | 说明 | |-----|------|------| | ISO时间 | [2025-01-10T15:30:45.123Z] | ISO 8601 格式的时间戳 | | 客户端IP | 172.16.0.34 | 发起请求的 IP 地址 | | 客户端ID:端口 | meizhou:51703 | 地区标识 + 服务端口 | | 方法 | GET | HTTP 方法 | | URL | /documents | 请求路径 | | HTTP版本 | HTTP/1.1 | 协议版本 | | 状态码 | 200 | HTTP 状态码 | | 响应大小 | 4567 bytes | 响应体大小 | | 响应时间 | 150 ms | 请求处理时间 | | 来源 | "-" | Referer 头 | | User-Agent | "Mozilla/5.0..." | 浏览器标识 | ### 开发环境日志格式 ``` 方法 URL 状态码 响应时间 - 响应大小 ``` - 状态码带颜色(绿色 2xx, 黄色 4xx, 红色 5xx) - HTTP 方法带颜色(蓝色 GET, 绿色 POST, 黄色 PUT, 红色 DELETE) --- ## 🔍 日志文件位置 所有日志文件位于 `logs/` 目录: ``` logs/ ├── meizhou-out.log ← 梅州实例的所有输出(包含 HTTP 日志) ├── meizhou-err.log ← 梅州实例的错误日志 ├── meizhou-combined.log ← 梅州实例的合并日志 ├── yunfu-out.log ← 云浮实例的所有输出 ├── yunfu-err.log ├── yunfu-combined.log ├── jieyang-out.log ← 揭阳实例的所有输出 ├── jieyang-err.log ├── jieyang-combined.log ├── chaozhou-out.log ← 潮州实例的所有输出 ├── chaozhou-err.log ├── chaozhou-combined.log ├── province-out.log ← 省局实例的所有输出 ├── province-err.log └── province-combined.log ``` --- ## 📝 日志分析示例 ### 查看访问量最高的 URL ```bash # 提取 URL 并统计 cat logs/meizhou-out.log | grep -oP 'GET \K/[^ ]+' | sort | uniq -c | sort -rn | head -10 ``` ### 统计 HTTP 状态码分布 ```bash # 提取状态码并统计 cat logs/meizhou-out.log | grep -oP 'HTTP/1\.\d \K\d{3}' | sort | uniq -c | sort -rn ``` ### 统计平均响应时间 ```bash # 提取响应时间并计算平均值 cat logs/meizhou-out.log | grep -oP '\K\d+ ms' | sed 's/ ms//' | awk '{sum+=$1; count++} END {print "平均响应时间:", sum/count, "ms"}' ``` ### 查找慢请求(>1秒) ```bash # 查找响应时间超过 1000ms 的请求 cat logs/meizhou-out.log | grep -P '\d{4,} ms' ``` ### 查找错误请求(4xx/5xx) ```bash # 查找 4xx 错误 cat logs/meizhou-out.log | grep -P 'HTTP/1\.\d [45]\d{2}' ``` --- ## 🔧 自定义配置 ### 修改日志格式 编辑 `server.js`,修改 `logFormat` 变量: ```javascript // 自定义日志格式 const logFormat = '[:date[iso]] :remote-addr :method :url :status :response-time ms'; ``` **可用的 morgan token:** | Token | 说明 | |-------|------| | `:method` | HTTP 方法 | | `:url` | 请求 URL | | `:status` | 状态码 | | `:response-time` | 响应时间(毫秒) | | `:res[content-length]` | 响应大小 | | `:remote-addr` | 客户端 IP | | `:http-version` | HTTP 版本 | | `:referrer` | Referer 头 | | `:user-agent` | User-Agent 头 | | `:date[format]` | 时间(支持 clf, iso, web 格式) | ### 跳过某些请求 编辑 `server.js`,修改 `skip` 函数: ```javascript app.use(morgan(logFormat, { skip: (req, res) => { // 跳过静态资源请求(减少日志噪音) if (req.url.startsWith('/build/')) return true; // 跳过健康检查 if (req.url === '/health') return true; return false; } })); ``` ### 添加日志轮转 使用 PM2 的日志轮转功能: ```bash # 安装 PM2 日志轮转模块 pm2 install pm2-logrotate # 配置每天轮转,保留 30 天 pm2 set pm2-logrotate:max_size 100M pm2 set pm2-logrotate:retain 30 pm2 set pm2-logrotate:rotateInterval '0 0 * * *' ``` --- ## 🐛 故障排查 ### 问题 1: 启动失败 **检查步骤:** ```bash # 查看 PM2 日志 pm2 logs --err # 查看具体实例日志 pm2 logs docreview-main-meizhou --err ``` **常见原因:** - 依赖未安装:`npm install` - 端口被占用:`netstat -tlnp | grep 51703` - 构建失败:`npm run build:production:multi` ### 问题 2: 日志没有记录 **检查步骤:** ```bash # 确认 server.js 被使用 pm2 info docreview-main-meizhou | grep script # 查看进程输出 pm2 logs docreview-main-meizhou --lines 100 ``` **验证:** ```bash # 发起测试请求 curl http://10.79.97.17:51703 # 立即查看日志 tail -n 5 logs/meizhou-out.log ``` ### 问题 3: 日志格式不正确 **检查 server.js 的 logFormat 配置:** ```bash # 查看 server.js 第 60-70 行 sed -n '60,70p' server.js ``` --- ## 📈 性能影响 ### morgan 性能测试 - **每请求开销**:< 0.1ms - **内存占用**:几乎可忽略 - **吞吐量影响**:< 1% ### 对比 Nginx 日志 | 指标 | morgan(应用层) | Nginx(代理层) | |-----|----------------|----------------| | 延迟增加 | ~0.05ms | ~0.5ms | | 额外端口 | 0 个 | 需要修改 PM2 端口 | | 配置复杂度 | 低 | 中 | | 日志详细程度 | 高(可访问应用数据) | 中 | | 架构复杂度 | 低 | 高(多一层代理) | --- ## ✅ 验收标准 部署成功后,应满足: - [ ] 所有 5 个实例(51703-51707)正常运行 - [ ] 访问任意实例,日志文件立即记录请求 - [ ] 日志包含:时间、IP、方法、URL、状态码、响应时间 - [ ] 不同实例的日志分别记录到对应文件 - [ ] 日志格式正确,信息完整 --- ## 📞 支持 如遇问题,请: 1. 查看 PM2 日志:`pm2 logs --err` 2. 查看应用日志:`tail -f logs/meizhou-out.log` 3. 检查 server.js 是否存在错误 4. 验证依赖是否正确安装:`npm list morgan express` --- **文档版本**: 1.0 **最后更新**: 2025-01-10 **适用环境**: Linux/Windows