chore: remove GitHub Actions workflows, use Woodpecker CI exclusively
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
# 联系方式配置说明
|
||||
|
||||
## 📋 联系方式总结
|
||||
|
||||
### 实际联系方式(对外)
|
||||
|
||||
| 联系类型 | 邮箱 | 用途 |
|
||||
|----------|------|------|
|
||||
| **运维告警** | ops@novalon.cn | 监控告警、系统故障通知 |
|
||||
| **业务咨询** | contact@novalon.cn | 用户联系、业务咨询、表单提交 |
|
||||
|
||||
### 系统内部配置(不对)
|
||||
|
||||
| 配置项 | 邮箱 | 用途 |
|
||||
|--------|------|------|
|
||||
| **管理员账号** | contact@novalon.cn | CMS后台登录、系统管理 |
|
||||
| **公司邮箱** | contact@novalon.cn | 接收联系表单邮件 |
|
||||
| **Resend API** | re_72PzbVrr_DiwTnB1ZDT7TyqCsgLoAfKfU | 邮件发送服务 |
|
||||
|
||||
## 📧 配置文件更新
|
||||
|
||||
### 1. 生产环境配置
|
||||
|
||||
文件: `.env.production`
|
||||
|
||||
```env
|
||||
# 管理员账号(CMS后台登录)
|
||||
ADMIN_EMAIL=contact@novalon.cn
|
||||
|
||||
# 公司邮箱(接收联系表单邮件)
|
||||
COMPANY_EMAIL=contact@novalon.cn
|
||||
|
||||
# Resend API(邮件发送服务)
|
||||
RESEND_API_KEY=re_72PzbVrr_DiwTnB1ZDT7TyqCsgLoAfKfU
|
||||
```
|
||||
|
||||
### 2. 测试配置更新
|
||||
|
||||
文件: `e2e/global-setup.ts`
|
||||
|
||||
```typescript
|
||||
// 测试登录账号
|
||||
await page.locator('#email').fill('contact@novalon.cn');
|
||||
```
|
||||
|
||||
### 3. 文档更新
|
||||
|
||||
所有文档已更新,移除了不存在的"技术支持"联系方式。
|
||||
|
||||
## 📊 监控和告警配置
|
||||
|
||||
### Sentry 错误监控
|
||||
- **告警邮箱**: ops@novalon.cn
|
||||
- **告警类型**: Critical Errors
|
||||
- **响应时间**: 立即
|
||||
|
||||
### UptimeRobot 可用性监控
|
||||
- **告警邮箱**: ops@novalon.cn
|
||||
- **告警类型**: Down, Up, SSL Expiry
|
||||
- **监控频率**: 5分钟
|
||||
|
||||
### Google Analytics 访问统计
|
||||
- **测量 ID**: G-LGTLCR15KM
|
||||
- **追踪类型**: 用户行为、页面浏览、事件追踪
|
||||
|
||||
## 📝 业务流程
|
||||
|
||||
### 用户联系流程
|
||||
|
||||
1. **用户访问联系页面**
|
||||
- 填写联系表单
|
||||
- 提交表单
|
||||
|
||||
2. **系统处理**
|
||||
- 表单提交到 `/api/contact`
|
||||
- 使用 Resend API 发送邮件
|
||||
- 邮件发送到: contact@novalon.cn
|
||||
|
||||
3. **管理员处理**
|
||||
- 管理员登录: contact@novalon.cn
|
||||
- 查看收到的邮件
|
||||
- 回复用户咨询
|
||||
|
||||
### 系统监控流程
|
||||
|
||||
1. **错误发生**
|
||||
- Sentry 捕获错误
|
||||
- 发送告警到: ops@novalon.cn
|
||||
|
||||
2. **网站故障**
|
||||
- UptimeRobot 检测到故障
|
||||
- 发送告警到: ops@novalon.cn
|
||||
|
||||
3. **运维响应**
|
||||
- 运维团队收到告警
|
||||
- 检查系统状态
|
||||
- 修复问题
|
||||
- 通知相关人员
|
||||
|
||||
## 🔐 安全考虑
|
||||
|
||||
### 账号分离
|
||||
- **管理员账号**: contact@novalon.cn(仅用于系统管理)
|
||||
- **运维告警**: ops@novalon.cn(用于系统监控)
|
||||
- **业务咨询**: contact@novalon.cn(用于用户联系)
|
||||
|
||||
### 权限控制
|
||||
- 管理员账号仅限内部使用
|
||||
- 不对外公开管理员登录信息
|
||||
- 定期更换密码
|
||||
|
||||
## 📞 联系方式使用指南
|
||||
|
||||
### 对于用户
|
||||
- **业务咨询**: contact@novalon.cn
|
||||
- 通过网站联系表单提交
|
||||
- 邮件会在 24 小时内回复
|
||||
|
||||
### 对于运维团队
|
||||
- **系统告警**: ops@novalon.cn
|
||||
- 监控系统自动发送告警
|
||||
- 需要立即响应和处理
|
||||
|
||||
### 对于管理员
|
||||
- **系统登录**: contact@novalon.cn
|
||||
- 访问 CMS 管理后台
|
||||
- 管理网站内容和用户
|
||||
|
||||
## ✅ 配置检查清单
|
||||
|
||||
- [x] 生产环境配置更新
|
||||
- [x] 测试配置更新
|
||||
- [x] 文档联系方式统一
|
||||
- [x] 监控告警配置
|
||||
- [x] 邮件服务配置
|
||||
- [x] 账号权限分离
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [轻量级监控配置](LIGHTWEIGHT_MONITORING.md)
|
||||
- [生产部署指南](PRODUCTION_DEPLOYMENT_LIGHTWEIGHT.md)
|
||||
- [Google Analytics 集成](GOOGLE_ANALYTICS_SETUP.md)
|
||||
- [项目 README](../README.md)
|
||||
|
||||
## 🎯 总结
|
||||
|
||||
现在所有联系方式已经统一配置完成:
|
||||
|
||||
1. **对外联系**: contact@novalon.cn
|
||||
- 用户联系表单
|
||||
- 业务咨询
|
||||
- 管理员登录
|
||||
|
||||
2. **运维告警**: ops@novalon.cn
|
||||
- Sentry 错误告警
|
||||
- UptimeRobot 可用性告警
|
||||
- 系统故障通知
|
||||
|
||||
3. **邮件服务**: Resend API
|
||||
- API Key: re_72PzbVrr_DiwTnB1ZDT7TyqCsgLoAfKfU
|
||||
- 发件人: alertmanager@novalon.cn / contact@novalon.cn
|
||||
- SMTP: smtp.resend.com:587
|
||||
|
||||
所有配置文件和文档都已经更新完成,联系方式现在统一且准确!
|
||||
@@ -0,0 +1,309 @@
|
||||
# Google Analytics 4 集成指南
|
||||
|
||||
## ✅ 配置状态
|
||||
|
||||
**GA4 测量 ID**: `G-LGTLCR15KM`
|
||||
|
||||
**配置文件**: `.env.production`
|
||||
```env
|
||||
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-LGTLCR15KM
|
||||
```
|
||||
|
||||
## 📋 集成组件
|
||||
|
||||
### 1. Analytics 工具库
|
||||
|
||||
文件位置: `src/lib/analytics.ts`
|
||||
|
||||
**提供的功能:**
|
||||
- `pageview(url)` - 页面浏览追踪
|
||||
- `event(action, category, label?, value?)` - 事件追踪
|
||||
- `trackContactForm(formData)` - 联系表单提交追踪
|
||||
- `trackButtonClick(buttonName, location)` - 按钮点击追踪
|
||||
- `trackPageView(pageTitle, pagePath)` - 页面视图追踪
|
||||
|
||||
### 2. Google Analytics 组件
|
||||
|
||||
文件位置: `src/components/analytics/GoogleAnalytics.tsx`
|
||||
|
||||
**功能:**
|
||||
- 自动初始化 GA4
|
||||
- 配置全局追踪
|
||||
- 在所有页面启用追踪
|
||||
|
||||
### 3. 根布局集成
|
||||
|
||||
文件位置: `src/app/layout.tsx`
|
||||
|
||||
**已集成:**
|
||||
```typescript
|
||||
import { GoogleAnalytics } from "@/components/analytics/GoogleAnalytics";
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html>
|
||||
<body>
|
||||
<GoogleAnalytics />
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 使用示例
|
||||
|
||||
### 1. 联系表单追踪
|
||||
|
||||
```typescript
|
||||
import { trackContactForm } from '@/lib/analytics';
|
||||
|
||||
function ContactForm() {
|
||||
const handleSubmit = async (formData: FormData) => {
|
||||
// 追踪表单提交
|
||||
trackContactForm({
|
||||
name: formData.get('name'),
|
||||
email: formData.get('email'),
|
||||
phone: formData.get('phone'),
|
||||
company: formData.get('company'),
|
||||
message: formData.get('message')
|
||||
});
|
||||
|
||||
// 提交表单...
|
||||
};
|
||||
|
||||
return <form onSubmit={handleSubmit}>...</form>;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 按钮点击追踪
|
||||
|
||||
```typescript
|
||||
import { trackButtonClick } from '@/lib/analytics';
|
||||
|
||||
function CTAButton() {
|
||||
const handleClick = () => {
|
||||
// 追踪按钮点击
|
||||
trackButtonClick('get_started', 'hero_section');
|
||||
};
|
||||
|
||||
return <button onClick={handleClick}>开始使用</button>;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 页面浏览追踪
|
||||
|
||||
```typescript
|
||||
import { pageview } from '@/lib/analytics';
|
||||
|
||||
function MyPage() {
|
||||
useEffect(() => {
|
||||
// 追踪页面浏览
|
||||
pageview('/my-page');
|
||||
}, []);
|
||||
|
||||
return <div>My Page</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 自定义事件追踪
|
||||
|
||||
```typescript
|
||||
import { event } from '@/lib/analytics';
|
||||
|
||||
function ProductCard({ product }) {
|
||||
const handleAddToCart = () => {
|
||||
// 追踪添加到购物车事件
|
||||
event('add_to_cart', 'ecommerce', product.name, product.price);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3>{product.name}</h3>
|
||||
<button onClick={handleAddToCart}>添加到购物车</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 可追踪的指标
|
||||
|
||||
### 自动追踪
|
||||
- ✅ 页面浏览(自动)
|
||||
- ✅ 页面标题(自动)
|
||||
- ✅ 用户会话(自动)
|
||||
- ✅ 地理位置(自动)
|
||||
|
||||
### 手动追踪
|
||||
- 📧 联系表单提交
|
||||
- 🔘 按钮点击
|
||||
- 📄 自定义页面视图
|
||||
- 🎯 自定义事件
|
||||
- 💰 交易/转化
|
||||
|
||||
## 🔧 配置选项
|
||||
|
||||
### 环境变量
|
||||
|
||||
```env
|
||||
# 必需配置
|
||||
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-LGTLCR15KM
|
||||
|
||||
# 可选配置(在 GoogleAnalytics 组件中)
|
||||
# NEXT_PUBLIC_GA_DEBUG=true # 启用调试模式
|
||||
```
|
||||
|
||||
### 调试模式
|
||||
|
||||
启用调试模式查看实时数据:
|
||||
|
||||
```typescript
|
||||
// 在 src/components/analytics/GoogleAnalytics.tsx 中
|
||||
const isDebug = process.env.NEXT_PUBLIC_GA_DEBUG === 'true';
|
||||
|
||||
if (isDebug) {
|
||||
console.log('GA Debug Mode Enabled');
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 数据查看
|
||||
|
||||
### 访问 Google Analytics
|
||||
|
||||
1. 访问 https://analytics.google.com/
|
||||
2. 选择你的 GA4 属性
|
||||
3. 查看实时数据
|
||||
4. 分析报告和趋势
|
||||
|
||||
### 关键报告
|
||||
|
||||
#### **实时报告**
|
||||
- 当前在线用户
|
||||
- 实时事件
|
||||
- 实时页面浏览
|
||||
- 地理位置
|
||||
|
||||
#### **受众报告**
|
||||
- 用户数量
|
||||
- 新用户 vs 回访用户
|
||||
- 用户地理位置
|
||||
- 设备和浏览器
|
||||
|
||||
#### **获取报告**
|
||||
- 用户获取渠道
|
||||
- 流量来源
|
||||
- 营销活动效果
|
||||
- 转化路径
|
||||
|
||||
#### **参与度报告**
|
||||
- 平均会话时长
|
||||
- 每会话页面浏览
|
||||
- 跳出率
|
||||
- 事件追踪
|
||||
|
||||
## 🧪 测试追踪
|
||||
|
||||
### 1. 本地测试
|
||||
|
||||
```bash
|
||||
# 启用调试模式
|
||||
NEXT_PUBLIC_GA_DEBUG=true npm run dev
|
||||
```
|
||||
|
||||
### 2. 实时验证
|
||||
|
||||
1. 访问 Google Analytics 实时报告
|
||||
2. 在你的网站上执行操作
|
||||
3. 查看实时数据更新
|
||||
|
||||
### 3. 调试扩展
|
||||
|
||||
使用 Google Analytics Debugger 扩展:
|
||||
- Chrome 扩展: Google Analytics Debugger
|
||||
- Firefox 扩展: Google Analytics Debugger
|
||||
|
||||
## 🔒 隐私和合规
|
||||
|
||||
### GDPR 合规
|
||||
|
||||
```typescript
|
||||
// 添加用户同意管理
|
||||
function CookieConsent() {
|
||||
const [consent, setConsent] = useState(false);
|
||||
|
||||
const handleAccept = () => {
|
||||
setConsent(true);
|
||||
// 用户同意后初始化 GA
|
||||
if (consent) {
|
||||
// GA 会自动初始化
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!consent && (
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-gray-900 text-white p-4">
|
||||
<p>我们使用 Google Analytics 来改进网站体验。</p>
|
||||
<button onClick={handleAccept}>接受</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Cookie 设置
|
||||
|
||||
在 Google Analytics 中配置:
|
||||
- 数据保留: 14个月
|
||||
- 用户数据删除: 支持用户删除请求
|
||||
- IP 匿名化: 启用
|
||||
|
||||
## 📞 故障排查
|
||||
|
||||
### 问题 1: 数据不显示
|
||||
|
||||
**解决方案:**
|
||||
1. 检查 GA4 ID 是否正确
|
||||
2. 确认环境变量已设置
|
||||
3. 检查网络连接
|
||||
4. 查看浏览器控制台错误
|
||||
|
||||
### 问题 2: 实时数据延迟
|
||||
|
||||
**解决方案:**
|
||||
1. GA4 实时数据有 5-10 分钟延迟
|
||||
2. 等待一段时间后查看
|
||||
3. 检查时区设置
|
||||
|
||||
### 问题 3: 事件不追踪
|
||||
|
||||
**解决方案:**
|
||||
1. 确认调用了正确的追踪函数
|
||||
2. 检查事件参数是否正确
|
||||
3. 启用调试模式验证
|
||||
|
||||
## 📚 相关资源
|
||||
|
||||
- [Google Analytics 4 文档](https://support.google.com/analytics/answer/9304153)
|
||||
- [GA4 迁移指南](https://support.google.com/analytics/answer/10110506)
|
||||
- [事件追踪最佳实践](https://support.google.com/analytics/answer/10089681)
|
||||
|
||||
## 🎁 示例代码
|
||||
|
||||
完整示例代码: `src/components/examples/ContactFormAnalyticsExample.tsx`
|
||||
|
||||
这个示例展示了如何在联系表单中集成 Google Analytics 追踪。
|
||||
|
||||
## ✅ 集成检查清单
|
||||
|
||||
- [x] GA4 测量 ID 配置
|
||||
- [x] Analytics 工具库创建
|
||||
- [x] Google Analytics 组件创建
|
||||
- [x] 根布局集成
|
||||
- [x] 联系表单示例创建
|
||||
- [x] 文档更新
|
||||
|
||||
**状态**: ✅ 完全集成
|
||||
|
||||
Google Analytics 4 已经完全集成到项目中,现在可以追踪用户行为和访问数据了!
|
||||
@@ -0,0 +1,252 @@
|
||||
# 轻量级监控配置指南
|
||||
|
||||
## 📋 监控架构
|
||||
|
||||
### 核心组件
|
||||
|
||||
1. **Sentry** - 错误监控和性能追踪
|
||||
2. **UptimeRobot** - 外部可用性监控
|
||||
3. **Google Analytics** - 用户行为和访问统计
|
||||
4. **健康检查API** - 内部服务状态
|
||||
5. **邮件告警** - 关键问题通知
|
||||
|
||||
## 🔧 配置步骤
|
||||
|
||||
### 1. Sentry 错误监控(已完成)
|
||||
|
||||
Sentry 已经集成在项目中,配置文件:
|
||||
|
||||
- `src/lib/sentry.ts` - Sentry 初始化
|
||||
- `.env.production` - Sentry DSN 配置
|
||||
|
||||
**功能:**
|
||||
|
||||
- JavaScript 错误捕获
|
||||
- 性能监控
|
||||
- 用户会话回放
|
||||
- 错误告警
|
||||
|
||||
### 2. UptimeRobot 可用性监控
|
||||
|
||||
#### 注册和配置
|
||||
|
||||
1. 访问 https://uptimerobot.com/
|
||||
2. 注册免费账号
|
||||
3. 创建新的 Monitor:
|
||||
- **Monitor Type**: HTTP(s)
|
||||
- **URL**: https://www.novalon.cn
|
||||
- **Monitoring Interval**: 5 minutes
|
||||
- **Alert Contacts**: ops@novalon.cn
|
||||
|
||||
#### 配置告警
|
||||
|
||||
在 UptimeRobot 中设置:
|
||||
|
||||
- **Down Alert**: 网站不可用时发送邮件
|
||||
- **Up Alert**: 网站恢复时发送邮件
|
||||
- **SSL Expiry**: SSL 证书过期提醒
|
||||
|
||||
#### 高级配置
|
||||
|
||||
```yaml
|
||||
# 推荐的监控端点
|
||||
- 主页: https://www.novalon.cn
|
||||
- 健康检查: https://www.novalon.cn/api/health
|
||||
- 管理后台: https://www.novalon.cn/admin
|
||||
```
|
||||
|
||||
### 3. Google Analytics 访问统计
|
||||
|
||||
#### 获取跟踪 ID
|
||||
|
||||
1. 访问 https://analytics.google.com/
|
||||
2. 创建新的 GA4 属性
|
||||
3. 复制测量 ID(格式:G-XXXXXXXXXX)
|
||||
|
||||
#### 配置 Next.js
|
||||
|
||||
更新 `.env.production`:
|
||||
|
||||
```env
|
||||
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX
|
||||
```
|
||||
|
||||
#### 集成到应用
|
||||
|
||||
创建 `src/lib/analytics.ts`:
|
||||
|
||||
```typescript
|
||||
export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;
|
||||
|
||||
export const pageview = (url: string) => {
|
||||
if (typeof window !== "undefined" && GA_MEASUREMENT_ID) {
|
||||
window.gtag("config", GA_MEASUREMENT_ID, {
|
||||
page_path: url,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const event = (action: string, category: string, label?: string) => {
|
||||
if (typeof window !== "undefined" && GA_MEASUREMENT_ID) {
|
||||
window.gtag("event", action, {
|
||||
event_category: category,
|
||||
event_label: label,
|
||||
});
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
在 `src/app/layout.tsx` 中添加:
|
||||
|
||||
```typescript
|
||||
import Script from 'next/script';
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
{process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID && (
|
||||
<Script
|
||||
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID}`}
|
||||
strategy="afterInteractive"
|
||||
/>
|
||||
)}
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 健康检查 API(已实现)
|
||||
|
||||
健康检查端点:`/api/health`
|
||||
|
||||
**返回数据:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2024-01-01T00:00:00Z",
|
||||
"version": "1.0.0",
|
||||
"checks": {
|
||||
"database": "connected",
|
||||
"uptime": 123456
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 邮件告警配置
|
||||
|
||||
#### 简化告警策略
|
||||
|
||||
只监控关键问题:
|
||||
|
||||
- **服务不可用**(通过 UptimeRobot)
|
||||
- **严重错误**(通过 Sentry)
|
||||
- **数据库连接失败**(通过健康检查)
|
||||
|
||||
#### 配置邮件通知
|
||||
|
||||
**Sentry 告警配置:**
|
||||
|
||||
1. 登录 Sentry Dashboard
|
||||
2. 进入 Settings → Alerts
|
||||
3. 创建新的 Alert Rule:
|
||||
- **Issue**: Critical Errors
|
||||
- **Environment**: Production
|
||||
- **Frequency**: Immediately
|
||||
- **Email**: ops@novalon.cn
|
||||
|
||||
**UptimeRobot 告警配置:**
|
||||
|
||||
- 添加邮件联系人:ops@novalon.cn
|
||||
- 设置告警频率:立即通知
|
||||
|
||||
## 📊 监控指标
|
||||
|
||||
### 关键指标
|
||||
|
||||
#### 可用性指标
|
||||
|
||||
- 网站正常运行时间(目标:> 99.9%)
|
||||
- 响应时间(目标:< 2秒)
|
||||
- SSL 证书状态
|
||||
|
||||
#### 错误指标
|
||||
|
||||
- JavaScript 错误数量
|
||||
- API 错误率
|
||||
- 数据库错误
|
||||
|
||||
#### 用户指标
|
||||
|
||||
- 日活跃用户
|
||||
- 页面浏览量
|
||||
- 平均会话时长
|
||||
- 跳出率
|
||||
|
||||
### 告警阈值
|
||||
|
||||
| 指标 | 阈值 | 告警级别 |
|
||||
| ---------- | ------- | -------- |
|
||||
| 网站可用性 | < 99.9% | Critical |
|
||||
| 响应时间 | > 3秒 | Warning |
|
||||
| 错误率 | > 5% | Critical |
|
||||
| 数据库连接 | 失败 | Critical |
|
||||
|
||||
## 🔧 维护和运维
|
||||
|
||||
### 日常检查
|
||||
|
||||
#### 每日检查
|
||||
|
||||
- [ ] 查看 Sentry 错误报告
|
||||
- [ ] 检查 UptimeRobot 状态
|
||||
- [ ] 查看关键日志
|
||||
|
||||
#### 每周检查
|
||||
|
||||
- [ ] 分析 Google Analytics 数据
|
||||
- [ ] 检查性能趋势
|
||||
- [ ] 审查安全日志
|
||||
|
||||
#### 每月检查
|
||||
|
||||
- [ ] 更新依赖包
|
||||
- [ ] 备份数据库
|
||||
- [ ] 审查监控配置
|
||||
|
||||
### 故障处理流程
|
||||
|
||||
#### 1. 网站不可用
|
||||
|
||||
1. 检查服务器状态
|
||||
2. 查看应用日志
|
||||
3. 重启服务
|
||||
4. 通知相关人员
|
||||
|
||||
#### 2. 错误激增
|
||||
|
||||
1. 查看 Sentry 错误详情
|
||||
2. 分析错误模式
|
||||
3. 修复关键问题
|
||||
4. 部署热修复
|
||||
|
||||
#### 3. 性能下降
|
||||
|
||||
1. 检查服务器资源
|
||||
2. 分析慢查询
|
||||
3. 优化数据库
|
||||
4. 清理缓存
|
||||
|
||||
## 📞 联系方式
|
||||
|
||||
- **运维告警**: ops@novalon.cn
|
||||
- **业务咨询**: contact@novalon.cn
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [生产部署指南](PRODUCTION_DEPLOYMENT.md)
|
||||
- [错误监控配置](SENTRY_SETUP.md)
|
||||
- [性能优化指南](PERFORMANCE_OPTIMIZATION.md)
|
||||
@@ -0,0 +1,223 @@
|
||||
# 监控和告警系统快速配置示例
|
||||
|
||||
## 🎯 三步快速启动
|
||||
|
||||
### 步骤 1: 运行环境检查
|
||||
|
||||
```bash
|
||||
chmod +x scripts/check-monitoring-env.sh
|
||||
./scripts/check-monitoring-env.sh
|
||||
```
|
||||
|
||||
### 步骤 2: 运行快速启动脚本
|
||||
|
||||
```bash
|
||||
chmod +x scripts/start-monitoring.sh
|
||||
./scripts/start-monitoring.sh
|
||||
```
|
||||
|
||||
脚本会自动:
|
||||
- 检查 Docker 环境
|
||||
- 检查端口占用
|
||||
- 创建必要目录
|
||||
- 询问邮件配置(可选)
|
||||
- 启动所有监控服务
|
||||
- 等待服务就绪
|
||||
|
||||
### 步骤 3: 访问监控界面
|
||||
|
||||
- **Prometheus**: http://localhost:9090
|
||||
- **Grafana**: http://localhost:3001 (admin/admin)
|
||||
- **Alertmanager**: http://localhost:9093
|
||||
|
||||
## 📧 邮件配置示例
|
||||
|
||||
### 使用 Resend 邮件服务
|
||||
|
||||
```yaml
|
||||
# monitoring/alertmanager.yml
|
||||
receivers:
|
||||
- name: 'critical-alerts'
|
||||
email_configs:
|
||||
- to: 'admin@novalon.cn,ops@novalon.cn'
|
||||
from: 'alertmanager@novalon.cn'
|
||||
smarthost: 'smtp.resend.com:587'
|
||||
auth_username: 'resend'
|
||||
auth_password: 're_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
||||
require_tls: true
|
||||
```
|
||||
|
||||
### 获取 Resend API Key
|
||||
|
||||
1. 访问 https://resend.com/
|
||||
2. 注册账号
|
||||
3. 进入 API Keys 页面
|
||||
4. 创建新的 API Key
|
||||
5. 复制 API Key(以 `re_` 开头)
|
||||
|
||||
### 使用其他邮件服务
|
||||
|
||||
#### Gmail
|
||||
```yaml
|
||||
email_configs:
|
||||
- to: 'admin@novalon.cn'
|
||||
from: 'alertmanager@novalon.cn'
|
||||
smarthost: 'smtp.gmail.com:587'
|
||||
auth_username: 'your-email@gmail.com'
|
||||
auth_password: 'your-app-password'
|
||||
require_tls: true
|
||||
```
|
||||
|
||||
#### QQ 邮箱
|
||||
```yaml
|
||||
email_configs:
|
||||
- to: 'admin@novalon.cn'
|
||||
from: 'alertmanager@novalon.cn'
|
||||
smarthost: 'smtp.qq.com:587'
|
||||
auth_username: 'your-email@qq.com'
|
||||
auth_password: 'your-authorization-code'
|
||||
require_tls: true
|
||||
```
|
||||
|
||||
## 🔔 告警规则示例
|
||||
|
||||
### 基础告警规则
|
||||
|
||||
```yaml
|
||||
# monitoring/alerts.yml
|
||||
groups:
|
||||
- name: novalon-website
|
||||
rules:
|
||||
# 服务不可用
|
||||
- alert: ServiceDown
|
||||
expr: up{job="novalon-website"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "服务不可用"
|
||||
description: "Novalon 网站服务已停止响应"
|
||||
|
||||
# 高错误率
|
||||
- alert: HighErrorRate
|
||||
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "高错误率"
|
||||
description: "5xx 错误率超过 5%"
|
||||
|
||||
# 高响应时间
|
||||
- alert: HighResponseTime
|
||||
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "高响应时间"
|
||||
description: "P95 响应时间超过 1 秒"
|
||||
```
|
||||
|
||||
## 📊 Grafana 数据源配置
|
||||
|
||||
### 添加 Prometheus 数据源
|
||||
|
||||
1. 访问 http://localhost:3001
|
||||
2. 登录 (admin/admin)
|
||||
3. 进入 Configuration → Data Sources
|
||||
4. 点击 "Add data source"
|
||||
5. 选择 "Prometheus"
|
||||
6. 配置:
|
||||
- Name: Prometheus
|
||||
- URL: http://prometheus:9090
|
||||
- Access: Server (default)
|
||||
7. 点击 "Save & Test"
|
||||
|
||||
### 导入仪表板
|
||||
|
||||
1. 进入 Dashboards → Import
|
||||
2. 上传 `monitoring/grafana-dashboard.json`
|
||||
3. 选择 Prometheus 数据源
|
||||
4. 点击 "Import"
|
||||
|
||||
## 🧪 测试告警
|
||||
|
||||
### 发送测试告警
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:9093/api/v1/alerts \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '[
|
||||
{
|
||||
"labels": {
|
||||
"alertname": "TestAlert",
|
||||
"severity": "warning"
|
||||
},
|
||||
"annotations": {
|
||||
"description": "这是一个测试告警"
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
### 查看告警状态
|
||||
|
||||
```bash
|
||||
# 查看 Alertmanager 告警
|
||||
curl http://localhost:9093/api/v1/alerts
|
||||
|
||||
# 查看 Prometheus 告警
|
||||
curl http://localhost:9090/api/v1/alerts
|
||||
```
|
||||
|
||||
## 🔧 常用命令
|
||||
|
||||
### 查看服务状态
|
||||
```bash
|
||||
docker-compose -f docker-compose.monitoring.yml ps
|
||||
```
|
||||
|
||||
### 查看服务日志
|
||||
```bash
|
||||
# Prometheus 日志
|
||||
docker-compose -f docker-compose.monitoring.yml logs prometheus
|
||||
|
||||
# Grafana 日志
|
||||
docker-compose -f docker-compose.monitoring.yml logs grafana
|
||||
|
||||
# Alertmanager 日志
|
||||
docker-compose -f docker-compose.monitoring.yml logs alertmanager
|
||||
```
|
||||
|
||||
### 重启服务
|
||||
```bash
|
||||
# 重启所有服务
|
||||
docker-compose -f docker-compose.monitoring.yml restart
|
||||
|
||||
# 重启单个服务
|
||||
docker-compose -f docker-compose.monitoring.yml restart prometheus
|
||||
```
|
||||
|
||||
### 停止服务
|
||||
```bash
|
||||
docker-compose -f docker-compose.monitoring.yml down
|
||||
```
|
||||
|
||||
## 📚 更多文档
|
||||
|
||||
- 详细配置指南: [docs/MONITORING_SETUP.md](file:///Users/zhangxiang/Codes/Gitee/home-page/novalon-website/docs/MONITORING_SETUP.md)
|
||||
- 生产部署指南: [docs/PRODUCTION_DEPLOYMENT.md](file:///Users/zhangxiang/Codes/Gitee/home-page/novalon-website/docs/PRODUCTION_DEPLOYMENT.md)
|
||||
|
||||
## 🆘 遇到问题?
|
||||
|
||||
1. 检查 Docker 是否正常运行
|
||||
2. 查看服务日志排查错误
|
||||
3. 确认端口没有被占用
|
||||
4. 验证配置文件语法正确
|
||||
5. 查看详细文档获取更多帮助
|
||||
|
||||
## 📞 联系支持
|
||||
|
||||
- 运维团队: ops@novalon.cn
|
||||
- 业务咨询: contact@novalon.cn
|
||||
@@ -0,0 +1,412 @@
|
||||
# 监控和告警系统配置指南
|
||||
|
||||
## 📋 目录
|
||||
1. [快速开始](#快速开始)
|
||||
2. [详细配置](#详细配置)
|
||||
3. [告警配置](#告警配置)
|
||||
4. [监控面板配置](#监控面板配置)
|
||||
5. [故障排查](#故障排查)
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 步骤 1: 环境检查
|
||||
|
||||
```bash
|
||||
# 运行环境检查脚本
|
||||
chmod +x scripts/check-monitoring-env.sh
|
||||
./scripts/check-monitoring-env.sh
|
||||
```
|
||||
|
||||
### 步骤 2: 配置邮件服务
|
||||
|
||||
编辑 `monitoring/alertmanager.yml`,更新邮件配置:
|
||||
|
||||
```yaml
|
||||
receivers:
|
||||
- name: 'default'
|
||||
email_configs:
|
||||
- to: 'admin@novalon.cn' # 接收告警的邮箱
|
||||
from: 'alertmanager@novalon.cn' # 发送告警的邮箱
|
||||
smarthost: 'smtp.resend.com:587' # SMTP 服务器
|
||||
auth_username: 'resend' # SMTP 用户名
|
||||
auth_password: 're_xxxxxxxxxxxxxx' # Resend API 密钥
|
||||
require_tls: true # 启用 TLS
|
||||
```
|
||||
|
||||
### 步骤 3: 启动监控服务
|
||||
|
||||
```bash
|
||||
# 启动所有监控服务
|
||||
docker-compose -f docker-compose.monitoring.yml up -d
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose -f docker-compose.monitoring.yml ps
|
||||
```
|
||||
|
||||
### 步骤 4: 访问监控界面
|
||||
|
||||
- **Prometheus**: http://localhost:9090
|
||||
- **Grafana**: http://localhost:3001 (admin/admin)
|
||||
- **Alertmanager**: http://localhost:9093
|
||||
|
||||
## 🔧 详细配置
|
||||
|
||||
### 1. Prometheus 配置
|
||||
|
||||
文件位置: `monitoring/prometheus.yml`
|
||||
|
||||
#### 基础配置
|
||||
|
||||
```yaml
|
||||
global:
|
||||
scrape_interval: 15s # 数据采集间隔
|
||||
evaluation_interval: 15s # 规则评估间隔
|
||||
|
||||
scrape_configs:
|
||||
- job_name: 'novalon-website'
|
||||
static_configs:
|
||||
- targets: ['localhost:3000'] # 应用服务地址
|
||||
metrics_path: '/api/health' # 健康检查端点
|
||||
```
|
||||
|
||||
#### 添加更多监控目标
|
||||
|
||||
```yaml
|
||||
scrape_configs:
|
||||
- job_name: 'novalon-website'
|
||||
static_configs:
|
||||
- targets: ['localhost:3000']
|
||||
metrics_path: '/api/health'
|
||||
|
||||
- job_name: 'node-exporter' # 系统指标
|
||||
static_configs:
|
||||
- targets: ['localhost:9100']
|
||||
|
||||
- job_name: 'postgres-exporter' # 数据库指标
|
||||
static_configs:
|
||||
- targets: ['localhost:9187']
|
||||
```
|
||||
|
||||
### 2. 告警规则配置
|
||||
|
||||
文件位置: `monitoring/alerts.yml`
|
||||
|
||||
#### 服务可用性告警
|
||||
|
||||
```yaml
|
||||
- alert: ServiceDown
|
||||
expr: up{job="novalon-website"} == 0
|
||||
for: 1m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "服务不可用"
|
||||
description: "Novalon 网站服务已停止响应超过 1 分钟"
|
||||
```
|
||||
|
||||
#### 错误率告警
|
||||
|
||||
```yaml
|
||||
- alert: HighErrorRate
|
||||
expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
annotations:
|
||||
summary: "高错误率"
|
||||
description: "5xx 错误率在过去 5 分钟内超过 5%: {{ $value }}"
|
||||
```
|
||||
|
||||
#### 响应时间告警
|
||||
|
||||
```yaml
|
||||
- alert: HighResponseTime
|
||||
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "高响应时间"
|
||||
description: "P95 响应时间超过 1 秒: {{ $value }}s"
|
||||
```
|
||||
|
||||
#### 资源使用告警
|
||||
|
||||
```yaml
|
||||
- alert: HighCPUUsage
|
||||
expr: rate(process_cpu_seconds_total[5m]) > 0.8
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "CPU 使用率过高"
|
||||
description: "CPU 使用率超过 80%: {{ $value }}"
|
||||
|
||||
- alert: HighMemoryUsage
|
||||
expr: process_resident_memory_bytes / 1024 / 1024 / 1024 > 1
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
annotations:
|
||||
summary: "内存使用率过高"
|
||||
description: "内存使用超过 1GB: {{ $value }}GB"
|
||||
```
|
||||
|
||||
### 3. Alertmanager 配置
|
||||
|
||||
#### 邮件通知配置
|
||||
|
||||
```yaml
|
||||
receivers:
|
||||
- name: 'critical-alerts'
|
||||
email_configs:
|
||||
- to: 'admin@novalon.cn,ops@novalon.cn'
|
||||
from: 'alertmanager@novalon.cn'
|
||||
smarthost: 'smtp.resend.com:587'
|
||||
auth_username: 'resend'
|
||||
auth_password: 're_xxxxxxxxxxxxxx'
|
||||
require_tls: true
|
||||
headers:
|
||||
Subject: '🚨 CRITICAL: Novalon Website Alert'
|
||||
X-Priority: '1' # 高优先级邮件
|
||||
```
|
||||
|
||||
#### 告警路由配置
|
||||
|
||||
```yaml
|
||||
route:
|
||||
group_by: ['alertname', 'cluster', 'service']
|
||||
group_wait: 10s # 等待更多告警分组
|
||||
group_interval: 10s # 发送告警的间隔
|
||||
repeat_interval: 12h # 重复告警的间隔
|
||||
|
||||
routes:
|
||||
- match:
|
||||
severity: critical
|
||||
receiver: 'critical-alerts'
|
||||
continue: true # 继续匹配其他规则
|
||||
|
||||
- match:
|
||||
severity: warning
|
||||
receiver: 'warning-alerts'
|
||||
```
|
||||
|
||||
#### 静默规则(维护期间)
|
||||
|
||||
```yaml
|
||||
# 临时静默告警(维护期间)
|
||||
inhibit_rules:
|
||||
- source_match:
|
||||
severity: 'critical'
|
||||
target_match:
|
||||
alertname: 'ServiceDown'
|
||||
equal: ['instance']
|
||||
```
|
||||
|
||||
## 📊 监控面板配置
|
||||
|
||||
### Grafana 仪表板配置
|
||||
|
||||
#### 1. 登录 Grafana
|
||||
|
||||
访问 http://localhost:3001
|
||||
- 用户名: admin
|
||||
- 密码: admin
|
||||
|
||||
#### 2. 添加 Prometheus 数据源
|
||||
|
||||
1. 进入 Configuration → Data Sources
|
||||
2. 点击 "Add data source"
|
||||
3. 选择 "Prometheus"
|
||||
4. 配置:
|
||||
- Name: Prometheus
|
||||
- URL: http://prometheus:9090
|
||||
- Access: Server (default)
|
||||
5. 点击 "Save & Test"
|
||||
|
||||
#### 3. 导入仪表板
|
||||
|
||||
1. 进入 Dashboards → Import
|
||||
2. 上传 `monitoring/grafana-dashboard.json`
|
||||
3. 选择 Prometheus 数据源
|
||||
4. 点击 "Import"
|
||||
|
||||
#### 4. 自定义仪表板
|
||||
|
||||
创建关键指标面板:
|
||||
|
||||
**HTTP 请求面板**
|
||||
```json
|
||||
{
|
||||
"title": "HTTP Requests",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(http_requests_total[5m])",
|
||||
"legendFormat": "{{ method }} {{ status }}"
|
||||
}
|
||||
],
|
||||
"type": "graph"
|
||||
}
|
||||
```
|
||||
|
||||
**响应时间面板**
|
||||
```json
|
||||
{
|
||||
"title": "Response Time (P95)",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
|
||||
"legendFormat": "P95"
|
||||
}
|
||||
],
|
||||
"type": "graph"
|
||||
}
|
||||
```
|
||||
|
||||
**错误率面板**
|
||||
```json
|
||||
{
|
||||
"title": "Error Rate",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "rate(http_requests_total{status=~\"5..\"}[5m])",
|
||||
"legendFormat": "5xx Errors"
|
||||
}
|
||||
],
|
||||
"type": "graph"
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 测试告警
|
||||
|
||||
### 1. 测试服务不可用告警
|
||||
|
||||
```bash
|
||||
# 停止应用服务
|
||||
npm stop
|
||||
|
||||
# 等待 1 分钟后,检查 Alertmanager
|
||||
curl http://localhost:9093/api/v1/alerts
|
||||
|
||||
# 恢复服务
|
||||
npm start
|
||||
```
|
||||
|
||||
### 2. 测试高错误率告警
|
||||
|
||||
```bash
|
||||
# 模拟高错误率
|
||||
for i in {1..100}; do
|
||||
curl -X POST http://localhost:3000/api/test/error
|
||||
done
|
||||
|
||||
# 检查 Prometheus
|
||||
curl http://localhost:9090/api/v1/query?query=rate(http_requests_total%7Bstatus%3D~%225..%22%7D%5B5m%5D
|
||||
```
|
||||
|
||||
### 3. 测试邮件通知
|
||||
|
||||
```bash
|
||||
# 发送测试告警
|
||||
curl -X POST http://localhost:9093/api/v1/alerts \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '[
|
||||
{
|
||||
"labels": {
|
||||
"alertname": "TestAlert",
|
||||
"severity": "warning"
|
||||
},
|
||||
"annotations": {
|
||||
"description": "这是一个测试告警"
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
## 🔧 故障排查
|
||||
|
||||
### 问题 1: 服务无法启动
|
||||
|
||||
```bash
|
||||
# 检查 Docker 日志
|
||||
docker-compose -f docker-compose.monitoring.yml logs
|
||||
|
||||
# 检查端口占用
|
||||
netstat -tulpn | grep -E '3000|9090|3001|9093'
|
||||
|
||||
# 重启服务
|
||||
docker-compose -f docker-compose.monitoring.yml restart
|
||||
```
|
||||
|
||||
### 问题 2: 告警不发送
|
||||
|
||||
```bash
|
||||
# 检查 Alertmanager 配置
|
||||
docker-compose -f docker-compose.monitoring.yml exec alertmanager \
|
||||
cat /etc/alertmanager/alertmanager.yml
|
||||
|
||||
# 检查 Alertmanager 日志
|
||||
docker-compose -f docker-compose.monitoring.yml logs alertmanager
|
||||
|
||||
# 测试 SMTP 连接
|
||||
telnet smtp.resend.com 587
|
||||
```
|
||||
|
||||
### 问题 3: Grafana 无法连接 Prometheus
|
||||
|
||||
```bash
|
||||
# 检查 Prometheus 是否运行
|
||||
docker-compose -f docker-compose.monitoring.yml ps prometheus
|
||||
|
||||
# 测试 Prometheus API
|
||||
curl http://localhost:9090/api/v1/status/config
|
||||
|
||||
# 检查网络连接
|
||||
docker-compose -f docker-compose.monitoring.yml exec grafana \
|
||||
ping prometheus
|
||||
```
|
||||
|
||||
### 问题 4: 数据采集失败
|
||||
|
||||
```bash
|
||||
# 检查应用健康检查端点
|
||||
curl http://localhost:3000/api/health
|
||||
|
||||
# 检查 Prometheus targets
|
||||
curl http://localhost:9090/api/v1/targets
|
||||
|
||||
# 查看 Prometheus 日志
|
||||
docker-compose -f docker-compose.monitoring.yml logs prometheus
|
||||
```
|
||||
|
||||
## 📈 最佳实践
|
||||
|
||||
### 1. 告警级别设置
|
||||
|
||||
- **Critical**: 立即需要处理,影响用户体验
|
||||
- **Warning**: 需要关注,但不影响主要功能
|
||||
- **Info**: 信息性告警,用于记录
|
||||
|
||||
### 2. 告警频率控制
|
||||
|
||||
- 避免告警风暴
|
||||
- 使用合理的 `for` 参数
|
||||
- 设置合适的 `repeat_interval`
|
||||
|
||||
### 3. 监控指标选择
|
||||
|
||||
- **关键指标**: 必须监控
|
||||
- **重要指标**: 建议监控
|
||||
- **辅助指标**: 可选监控
|
||||
|
||||
### 4. 性能优化
|
||||
|
||||
- 调整 Prometheus 采集间隔
|
||||
- 配置数据保留策略
|
||||
- 使用 PromQL 优化查询
|
||||
|
||||
## 📞 联系支持
|
||||
|
||||
如遇到问题,请联系:
|
||||
- 运维团队: ops@novalon.cn
|
||||
- 业务咨询: contact@novalon.cn
|
||||
@@ -335,9 +335,8 @@ docker-compose -f docker-compose.monitoring.yml up -d
|
||||
|
||||
## 联系方式
|
||||
|
||||
- **技术支持**: admin@novalon.cn
|
||||
- **运维团队**: ops@novalon.cn
|
||||
- **开发团队**: dev@novalon.cn
|
||||
- **运维告警**: ops@novalon.cn
|
||||
- **业务咨询**: contact@novalon.cn
|
||||
|
||||
## 附录
|
||||
|
||||
|
||||
@@ -0,0 +1,505 @@
|
||||
# 生产环境部署和监控指南(轻量级版本)
|
||||
|
||||
## 目录
|
||||
1. [环境准备](#环境准备)
|
||||
2. [部署流程](#部署流程)
|
||||
3. [轻量级监控配置](#轻量级监控配置)
|
||||
4. [告警配置](#告警配置)
|
||||
5. [维护和运维](#维护和运维)
|
||||
|
||||
## 环境准备
|
||||
|
||||
### 系统要求
|
||||
- Linux/Unix 服务器(推荐 Ubuntu 22.04+)
|
||||
- Node.js 18+
|
||||
- 至少 1GB RAM
|
||||
- 至少 5GB 磁盘空间
|
||||
|
||||
### 必需的软件
|
||||
```bash
|
||||
# 安装 Node.js
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
|
||||
sudo apt-get install -y nodejs
|
||||
|
||||
# 安装 PM2(进程管理器)
|
||||
npm install -g pm2
|
||||
```
|
||||
|
||||
## 部署流程
|
||||
|
||||
### 1. 配置环境变量
|
||||
|
||||
复制并编辑生产环境配置:
|
||||
```bash
|
||||
cp .env.production .env.local
|
||||
```
|
||||
|
||||
更新以下关键配置:
|
||||
- `RESEND_API_KEY`: Resend API 密钥
|
||||
- `NEXT_PUBLIC_SENTRY_DSN`: Sentry DSN
|
||||
- `NEXTAUTH_SECRET`: 认证密钥
|
||||
- `ADMIN_PASSWORD`: 管理员密码
|
||||
- `NEXT_PUBLIC_GA_MEASUREMENT_ID`: Google Analytics ID(可选)
|
||||
|
||||
### 2. 安装依赖
|
||||
|
||||
```bash
|
||||
npm ci --production=false
|
||||
```
|
||||
|
||||
### 3. 运行测试
|
||||
|
||||
```bash
|
||||
cd e2e
|
||||
TEST_ENV=development npx playwright test --reporter=list
|
||||
cd ..
|
||||
```
|
||||
|
||||
### 4. 构建生产版本
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 5. 启动生产服务器
|
||||
|
||||
使用 PM2 启动服务:
|
||||
```bash
|
||||
pm2 start npm --name "novalon-website" -- start
|
||||
```
|
||||
|
||||
### 6. 验证部署
|
||||
|
||||
访问以下URL验证部署:
|
||||
- 网站: http://localhost:3000
|
||||
- 健康检查: http://localhost:3000/api/health
|
||||
- 管理后台: http://localhost:3000/admin
|
||||
|
||||
## 轻量级监控配置
|
||||
|
||||
### 监控架构
|
||||
|
||||
采用轻量级监控方案,包含以下组件:
|
||||
|
||||
1. **Sentry** - 错误监控和性能追踪
|
||||
2. **UptimeRobot** - 外部可用性监控
|
||||
3. **Google Analytics** - 用户行为和访问统计
|
||||
4. **健康检查API** - 内部服务状态
|
||||
5. **邮件告警** - 关键问题通知
|
||||
|
||||
### 1. Sentry 错误监控
|
||||
|
||||
#### 配置步骤
|
||||
|
||||
Sentry 已经集成在项目中,只需配置环境变量:
|
||||
|
||||
```env
|
||||
NEXT_PUBLIC_SENTRY_DSN=https://xxxxxxxxxxxxx@o4507xxxxx.ingest.sentry.io/xxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
#### 配置告警
|
||||
|
||||
1. 登录 Sentry Dashboard
|
||||
2. 进入 Settings → Alerts
|
||||
3. 创建新的 Alert Rule:
|
||||
- **Issue**: Critical Errors
|
||||
- **Environment**: Production
|
||||
- **Frequency**: Immediately
|
||||
- **Email**: ops@novalon.cn
|
||||
|
||||
#### 功能特性
|
||||
|
||||
- JavaScript 错误捕获
|
||||
- 性能监控
|
||||
- 用户会话回放
|
||||
- 错误告警
|
||||
|
||||
### 2. UptimeRobot 可用性监控
|
||||
|
||||
#### 注册和配置
|
||||
|
||||
1. 访问 https://uptimerobot.com/
|
||||
2. 注册免费账号
|
||||
3. 创建新的 Monitor:
|
||||
- **Monitor Type**: HTTP(s)
|
||||
- **URL**: https://www.novalon.cn
|
||||
- **Monitoring Interval**: 5 minutes
|
||||
- **Alert Contacts**: ops@novalon.cn
|
||||
|
||||
#### 配置告警
|
||||
|
||||
在 UptimeRobot 中设置:
|
||||
- **Down Alert**: 网站不可用时发送邮件
|
||||
- **Up Alert**: 网站恢复时发送邮件
|
||||
- **SSL Expiry**: SSL 证书过期提醒
|
||||
|
||||
#### 推荐监控端点
|
||||
|
||||
```yaml
|
||||
- 主页: https://www.novalon.cn
|
||||
- 健康检查: https://www.novalon.cn/api/health
|
||||
- 管理后台: https://www.novalon.cn/admin
|
||||
```
|
||||
|
||||
### 3. Google Analytics 访问统计
|
||||
|
||||
#### 获取跟踪 ID
|
||||
|
||||
1. 访问 https://analytics.google.com/
|
||||
2. 创建新的 GA4 属性
|
||||
3. 复制测量 ID(格式:G-XXXXXXXXXX)
|
||||
|
||||
#### 配置环境变量
|
||||
|
||||
```env
|
||||
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX
|
||||
```
|
||||
|
||||
#### 集成到应用
|
||||
|
||||
创建 `src/lib/analytics.ts`:
|
||||
```typescript
|
||||
export const GA_MEASUREMENT_ID = process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID;
|
||||
|
||||
export const pageview = (url: string) => {
|
||||
if (typeof window !== 'undefined' && GA_MEASUREMENT_ID) {
|
||||
window.gtag('config', GA_MEASUREMENT_ID, {
|
||||
page_path: url,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const event = (action: string, category: string, label?: string) => {
|
||||
if (typeof window !== 'undefined' && GA_MEASUREMENT_ID) {
|
||||
window.gtag('event', action, {
|
||||
event_category: category,
|
||||
event_label: label,
|
||||
});
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
在 `src/app/layout.tsx` 中添加:
|
||||
```typescript
|
||||
import Script from 'next/script';
|
||||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html>
|
||||
<head>
|
||||
{process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID && (
|
||||
<Script
|
||||
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_MEASUREMENT_ID}`}
|
||||
strategy="afterInteractive"
|
||||
/>
|
||||
)}
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 健康检查 API
|
||||
|
||||
健康检查端点:`/api/health`
|
||||
|
||||
**返回数据:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2024-01-01T00:00:00Z",
|
||||
"version": "1.0.0",
|
||||
"checks": {
|
||||
"database": "connected",
|
||||
"uptime": 123456
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 告警配置
|
||||
|
||||
### 告警策略
|
||||
|
||||
只监控关键问题:
|
||||
- **服务不可用**(通过 UptimeRobot)
|
||||
- **严重错误**(通过 Sentry)
|
||||
- **数据库连接失败**(通过健康检查)
|
||||
|
||||
### 告警阈值
|
||||
|
||||
| 指标 | 阈值 | 告警级别 | 通知方式 |
|
||||
|--------|--------|----------|----------|
|
||||
| 网站可用性 | < 99.9% | Critical | UptimeRobot 邮件 |
|
||||
| 响应时间 | > 3秒 | Warning | UptimeRobot 邮件 |
|
||||
| JavaScript 错误 | > 10次/小时 | Critical | Sentry 邮件 |
|
||||
| 数据库连接 | 失败 | Critical | 手动检查 |
|
||||
|
||||
### 邮件通知
|
||||
|
||||
**Sentry 告警:**
|
||||
- 接收邮箱: ops@novalon.cn
|
||||
- 告警级别: Critical
|
||||
- 响应时间: 立即
|
||||
|
||||
**UptimeRobot 告警:**
|
||||
- 接收邮箱: ops@novalon.cn
|
||||
- 告警类型: Down, Up, SSL Expiry
|
||||
- 响应时间: 立即
|
||||
|
||||
## 维护和运维
|
||||
|
||||
### 日常维护
|
||||
|
||||
#### 每日检查
|
||||
- [ ] 查看 Sentry 错误报告
|
||||
- [ ] 检查 UptimeRobot 状态
|
||||
- [ ] 查看关键日志
|
||||
|
||||
#### 每周检查
|
||||
- [ ] 分析 Google Analytics 数据
|
||||
- [ ] 检查性能趋势
|
||||
- [ ] 审查安全日志
|
||||
|
||||
#### 每月检查
|
||||
- [ ] 更新依赖包
|
||||
- [ ] 备份数据库
|
||||
- [ ] 审查监控配置
|
||||
|
||||
### 日志管理
|
||||
|
||||
```bash
|
||||
# 查看应用日志
|
||||
pm2 logs novalon-website
|
||||
|
||||
# 查看错误日志
|
||||
pm2 logs novalon-website --err
|
||||
|
||||
# 清理旧日志
|
||||
pm2 flush
|
||||
```
|
||||
|
||||
### 数据库备份
|
||||
|
||||
```bash
|
||||
# 手动备份
|
||||
./scripts/backup.sh
|
||||
|
||||
# 设置定时备份
|
||||
crontab -e
|
||||
# 添加以下行(每天凌晨 2 点备份)
|
||||
0 2 * * * /path/to/scripts/backup.sh
|
||||
```
|
||||
|
||||
### 故障处理
|
||||
|
||||
#### 1. 服务无法启动
|
||||
```bash
|
||||
# 检查 PM2 状态
|
||||
pm2 status
|
||||
|
||||
# 查看错误日志
|
||||
pm2 logs novalon-website --err
|
||||
|
||||
# 重启服务
|
||||
pm2 restart novalon-website
|
||||
```
|
||||
|
||||
#### 2. 网站不可用
|
||||
1. 检查 UptimeRobot 告警
|
||||
2. 查看服务器状态
|
||||
3. 检查应用日志
|
||||
4. 重启服务
|
||||
|
||||
#### 3. 错误激增
|
||||
1. 查看 Sentry 错误详情
|
||||
2. 分析错误模式
|
||||
3. 修复关键问题
|
||||
4. 部署热修复
|
||||
|
||||
### 更新部署
|
||||
|
||||
#### 零停机部署
|
||||
```bash
|
||||
# 1. 构建新版本
|
||||
npm run build
|
||||
|
||||
# 2. 备份当前版本
|
||||
cp -r dist dist_backup
|
||||
|
||||
# 3. 替换新版本
|
||||
rm -rf dist
|
||||
mv dist_new dist
|
||||
|
||||
# 4. 重启服务(优雅重启)
|
||||
pm2 reload novalon-website
|
||||
```
|
||||
|
||||
#### 回滚
|
||||
```bash
|
||||
# 回滚到上一个版本
|
||||
rm -rf dist
|
||||
mv dist_backup dist
|
||||
|
||||
# 重启服务
|
||||
pm2 restart novalon-website
|
||||
```
|
||||
|
||||
### 安全加固
|
||||
|
||||
#### 防火墙配置
|
||||
```bash
|
||||
# 只允许必要端口
|
||||
ufw allow 22/tcp # SSH
|
||||
ufw allow 80/tcp # HTTP
|
||||
ufw allow 443/tcp # HTTPS
|
||||
ufw enable
|
||||
```
|
||||
|
||||
#### SSL/TLS 配置
|
||||
```bash
|
||||
# 使用 Let's Encrypt 获取免费证书
|
||||
certbot certonly --webroot -w /var/www/html -d www.novalon.cn
|
||||
|
||||
# 配置 Nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name www.novalon.cn;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/www.novalon.cn/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/www.novalon.cn/privkey.pem;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 定期更新
|
||||
```bash
|
||||
# 更新系统包
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
# 更新 Node.js 依赖
|
||||
npm audit fix
|
||||
npm update
|
||||
|
||||
# 更新 PM2
|
||||
pm2 update
|
||||
```
|
||||
|
||||
## 性能优化
|
||||
|
||||
### 1. 应用优化
|
||||
- 启用 gzip 压缩
|
||||
- 优化图片和静态资源
|
||||
- 使用 CDN 加速
|
||||
|
||||
### 2. 数据库优化
|
||||
- 创建适当的索引
|
||||
- 定期清理旧数据
|
||||
- 优化查询语句
|
||||
|
||||
### 3. 服务器优化
|
||||
- 调整 PM2 配置
|
||||
- 配置 swap
|
||||
- 优化文件系统
|
||||
|
||||
## 应急预案
|
||||
|
||||
### 1. 服务完全不可用
|
||||
1. 检查 UptimeRobot 告警
|
||||
2. 检查服务器状态
|
||||
3. 查看应用日志
|
||||
4. 尝试重启服务
|
||||
5. 如果无法恢复,切换到备用服务器
|
||||
|
||||
### 2. 数据丢失
|
||||
1. 立即停止写入操作
|
||||
2. 从最近的备份恢复
|
||||
3. 验证数据完整性
|
||||
4. 分析丢失原因,防止再次发生
|
||||
|
||||
### 3. 安全事件
|
||||
1. 立即隔离受影响系统
|
||||
2. 收集日志和证据
|
||||
3. 评估影响范围
|
||||
4. 修复安全漏洞
|
||||
5. 恢复服务
|
||||
6. 事后分析
|
||||
|
||||
## 联系方式
|
||||
|
||||
- **运维告警**: ops@novalon.cn
|
||||
- **业务咨询**: contact@novalon.cn
|
||||
|
||||
## 附录
|
||||
|
||||
### A. 常用命令
|
||||
```bash
|
||||
# 查看服务状态
|
||||
pm2 status
|
||||
|
||||
# 重启服务
|
||||
pm2 restart novalon-website
|
||||
|
||||
# 查看日志
|
||||
pm2 logs novalon-website
|
||||
|
||||
# 检查磁盘空间
|
||||
df -h
|
||||
|
||||
# 检查内存使用
|
||||
free -h
|
||||
|
||||
# 检查进程
|
||||
ps aux | grep node
|
||||
```
|
||||
|
||||
### B. 配置文件位置
|
||||
- 应用配置: `/etc/novalon-website/`
|
||||
- 日志文件: `~/.pm2/logs/`
|
||||
- 数据文件: `/var/lib/novalon-website/`
|
||||
- 备份文件: `/var/backups/novalon-website/`
|
||||
|
||||
### C. 监控服务
|
||||
- **Sentry**: https://sentry.io/
|
||||
- **UptimeRobot**: https://uptimerobot.com/
|
||||
- **Google Analytics**: https://analytics.google.com/
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 一键配置脚本
|
||||
|
||||
```bash
|
||||
# 运行轻量级监控配置脚本
|
||||
chmod +x scripts/setup-lightweight-monitoring.sh
|
||||
./scripts/setup-lightweight-monitoring.sh
|
||||
```
|
||||
|
||||
这个脚本会:
|
||||
- 检查 Sentry 配置
|
||||
- 配置 Google Analytics(可选)
|
||||
- 提供 UptimeRobot 配置指导
|
||||
- 创建健康检查端点
|
||||
- 配置 Sentry 告警
|
||||
|
||||
### 部署脚本
|
||||
|
||||
```bash
|
||||
# 运行生产部署脚本
|
||||
chmod +x scripts/deploy-production.sh
|
||||
./scripts/deploy-production.sh
|
||||
```
|
||||
|
||||
这个脚本会:
|
||||
- 安装依赖
|
||||
- 运行测试
|
||||
- 构建生产版本
|
||||
- 启动服务
|
||||
- 健康检查
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,579 @@
|
||||
# 渐进式测试覆盖率提升计划
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 建立可持续的测试覆盖率提升体系,从当前29.5%逐步提升到更高水平,同时保证开发效率和代码质量。
|
||||
|
||||
**Architecture:** 采用分层覆盖率策略,核心业务逻辑层高覆盖(70-80%),UI组件层中覆盖(60-70%),页面展示层适度覆盖(40-50%)。
|
||||
|
||||
**Tech Stack:** Jest, React Testing Library, Next.js, TypeScript, GitHub Actions
|
||||
|
||||
---
|
||||
|
||||
## 已完成任务
|
||||
|
||||
### Task 1: 调整Jest配置覆盖率阈值
|
||||
|
||||
**Files:**
|
||||
- Modify: `jest.config.js:12-18`
|
||||
|
||||
**Step 1: 修改覆盖率阈值为合理水平**
|
||||
|
||||
```javascript
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 20,
|
||||
functions: 25,
|
||||
lines: 25,
|
||||
statements: 25,
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
**Step 2: 运行测试验证配置**
|
||||
|
||||
Run: `npm run test:unit -- --coverage --coverageReporters=text-summary`
|
||||
|
||||
Expected: PASS with coverage above 25%
|
||||
|
||||
**Step 3: 提交配置修改**
|
||||
|
||||
```bash
|
||||
git add jest.config.js
|
||||
git commit -m "test: adjust coverage threshold to reasonable level (25%)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第一阶段:稳定当前覆盖率(1-2周)
|
||||
|
||||
### Task 2: 补充核心业务逻辑测试
|
||||
|
||||
**Files:**
|
||||
- Create: `src/lib/auth/session.test.ts`
|
||||
- Create: `src/lib/auth/token.test.ts`
|
||||
- Create: `src/lib/validation.test.ts`
|
||||
|
||||
**Step 1: 为session管理编写测试**
|
||||
|
||||
```typescript
|
||||
describe('session management', () => {
|
||||
it('should create session with user data', () => {
|
||||
const session = createSession({ userId: '123', role: 'admin' });
|
||||
expect(session).toBeDefined();
|
||||
expect(session.userId).toBe('123');
|
||||
});
|
||||
|
||||
it('should validate session expiration', () => {
|
||||
const expiredSession = createSession({ userId: '123', expiresIn: -1 });
|
||||
expect(isSessionValid(expiredSession)).toBe(false);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: 运行测试验证失败**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="session.test.ts"`
|
||||
|
||||
Expected: FAIL with "createSession not defined"
|
||||
|
||||
**Step 3: 实现session管理功能**
|
||||
|
||||
```typescript
|
||||
export function createSession(userData: SessionData): Session {
|
||||
return {
|
||||
...userData,
|
||||
createdAt: Date.now(),
|
||||
expiresAt: Date.now() + (24 * 60 * 60 * 1000), // 24小时
|
||||
};
|
||||
}
|
||||
|
||||
export function isSessionValid(session: Session): boolean {
|
||||
return Date.now() < session.expiresAt;
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 运行测试验证通过**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="session.test.ts"`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: 提交**
|
||||
|
||||
```bash
|
||||
git add src/lib/auth/session.test.ts src/lib/auth/session.ts
|
||||
git commit -m "test: add session management tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: 补充数据验证测试
|
||||
|
||||
**Files:**
|
||||
- Create: `src/lib/validation.test.ts`
|
||||
- Modify: `src/lib/validation.ts`
|
||||
|
||||
**Step 1: 编写数据验证测试**
|
||||
|
||||
```typescript
|
||||
describe('validation', () => {
|
||||
describe('email validation', () => {
|
||||
it('should accept valid email', () => {
|
||||
expect(validateEmail('test@example.com')).toBe(true);
|
||||
});
|
||||
|
||||
it('should reject invalid email', () => {
|
||||
expect(validateEmail('invalid')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('phone validation', () => {
|
||||
it('should accept valid phone', () => {
|
||||
expect(validatePhone('13800138000')).toBe(true);
|
||||
});
|
||||
|
||||
it('should reject invalid phone', () => {
|
||||
expect(validatePhone('123')).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: 运行测试验证失败**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="validation.test.ts"`
|
||||
|
||||
Expected: FAIL with validation functions not defined
|
||||
|
||||
**Step 3: 实现验证函数**
|
||||
|
||||
```typescript
|
||||
export function validateEmail(email: string): boolean {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
}
|
||||
|
||||
export function validatePhone(phone: string): boolean {
|
||||
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||
return phoneRegex.test(phone);
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 运行测试验证通过**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="validation.test.ts"`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: 提交**
|
||||
|
||||
```bash
|
||||
git add src/lib/validation.test.ts src/lib/validation.ts
|
||||
git commit -m "test: add data validation tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: 优化测试执行性能
|
||||
|
||||
**Files:**
|
||||
- Modify: `jest.config.js`
|
||||
- Create: `.github/workflows/test-optimized.yml`
|
||||
|
||||
**Step 1: 配置并行测试执行**
|
||||
|
||||
```javascript
|
||||
// jest.config.js
|
||||
module.exports = {
|
||||
// ... existing config
|
||||
maxWorkers: '50%',
|
||||
};
|
||||
```
|
||||
|
||||
**Step 2: 创建优化后的CI工作流**
|
||||
|
||||
```yaml
|
||||
# .github/workflows/test-optimized.yml
|
||||
name: Optimized Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
shard: [1, 2, 3, 4]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests (shard ${{ matrix.shard }})
|
||||
run: npm run test:unit -- --shard=${{ matrix.shard }}/4
|
||||
|
||||
- name: Upload coverage
|
||||
if: matrix.shard == 4
|
||||
uses: codecov/codecov-action@v4
|
||||
```
|
||||
|
||||
**Step 3: 提交配置**
|
||||
|
||||
```bash
|
||||
git add jest.config.js .github/workflows/test-optimized.yml
|
||||
git commit -m "ci: optimize test execution with parallelization"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第二阶段:提升覆盖率到35%(1-2个月)
|
||||
|
||||
### Task 5: 补充API路由测试
|
||||
|
||||
**Files:**
|
||||
- Create: `src/app/api/contact/route.test.ts`
|
||||
- Create: `src/app/api/auth/route.test.ts`
|
||||
|
||||
**Step 1: 编写API路由测试**
|
||||
|
||||
```typescript
|
||||
describe('/api/contact', () => {
|
||||
it('should handle POST request', async () => {
|
||||
const response = await POST(new Request('http://localhost/api/contact', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ name: 'Test', email: 'test@example.com' }),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
it('should validate required fields', async () => {
|
||||
const response = await POST(new Request('http://localhost/api/contact', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
}));
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: 运行测试验证失败**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="api/contact/route.test.ts"`
|
||||
|
||||
Expected: FAIL with API route not tested
|
||||
|
||||
**Step 3: 实现API路由验证逻辑**
|
||||
|
||||
```typescript
|
||||
// 确保API路由有适当的验证和错误处理
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
|
||||
if (!body.name || !body.email) {
|
||||
return Response.json({ error: 'Missing required fields' }, { status: 400 });
|
||||
}
|
||||
|
||||
// 处理逻辑...
|
||||
return Response.json({ success: true }, { status: 200 });
|
||||
} catch (error) {
|
||||
return Response.json({ error: 'Internal server error' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 运行测试验证通过**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="api/contact/route.test.ts"`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: 提交**
|
||||
|
||||
```bash
|
||||
git add src/app/api/contact/route.test.ts src/app/api/contact/route.ts
|
||||
git commit -m "test: add API route tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 6: 补充数据库操作测试
|
||||
|
||||
**Files:**
|
||||
- Create: `src/db/queries.test.ts`
|
||||
- Create: `src/db/mutations.test.ts`
|
||||
|
||||
**Step 1: 编写数据库查询测试**
|
||||
|
||||
```typescript
|
||||
describe('database queries', () => {
|
||||
it('should query user by id', async () => {
|
||||
const user = await getUserById('123');
|
||||
expect(user).toBeDefined();
|
||||
expect(user.id).toBe('123');
|
||||
});
|
||||
|
||||
it('should return null for non-existent user', async () => {
|
||||
const user = await getUserById('non-existent');
|
||||
expect(user).toBeNull();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: 运行测试验证失败**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="db/queries.test.ts"`
|
||||
|
||||
Expected: FAIL with database functions not tested
|
||||
|
||||
**Step 3: 实现数据库查询函数**
|
||||
|
||||
```typescript
|
||||
export async function getUserById(id: string): Promise<User | null> {
|
||||
const result = await db.select().from(users).where(eq(users.id, id)).limit(1);
|
||||
return result[0] || null;
|
||||
}
|
||||
```
|
||||
|
||||
**Step 4: 运行测试验证通过**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="db/queries.test.ts"`
|
||||
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: 提交**
|
||||
|
||||
```bash
|
||||
git add src/db/queries.test.ts src/db/queries.ts
|
||||
git commit -m "test: add database query tests"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 7: 提升分支覆盖率
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/lib/auth/permissions.test.ts`
|
||||
- Modify: `src/lib/upload.test.ts`
|
||||
|
||||
**Step 1: 添加边界条件测试**
|
||||
|
||||
```typescript
|
||||
describe('permissions edge cases', () => {
|
||||
it('should handle null role', () => {
|
||||
expect(hasPermission(null, 'content', 'read')).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle undefined resource', () => {
|
||||
expect(hasPermission('admin', undefined, 'read')).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle empty action string', () => {
|
||||
expect(hasPermission('admin', 'content', '')).toBe(false);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Step 2: 运行测试验证通过**
|
||||
|
||||
Run: `npm run test:unit -- --testPathPattern="permissions.test.ts"`
|
||||
|
||||
Expected: PASS with improved branch coverage
|
||||
|
||||
**Step 3: 提交**
|
||||
|
||||
```bash
|
||||
git add src/lib/auth/permissions.test.ts
|
||||
git commit -m "test: improve branch coverage with edge cases"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第三阶段:建立测试质量体系(2-3个月)
|
||||
|
||||
### Task 8: 创建测试指南文档
|
||||
|
||||
**Files:**
|
||||
- Create: `docs/testing-guide.md`
|
||||
|
||||
**Step 1: 编写测试指南**
|
||||
|
||||
```markdown
|
||||
# 测试指南
|
||||
|
||||
## 测试策略
|
||||
|
||||
本项目采用分层覆盖率策略:
|
||||
- 核心业务逻辑层:70-80%覆盖率
|
||||
- UI组件层:60-70%覆盖率
|
||||
- 页面展示层:40-50%覆盖率
|
||||
|
||||
## 测试编写规范
|
||||
|
||||
### 单元测试
|
||||
- 使用Jest和React Testing Library
|
||||
- 遵循AAA模式(Arrange-Act-Assert)
|
||||
- 每个测试只验证一个行为
|
||||
|
||||
### 集成测试
|
||||
- 测试组件间的交互
|
||||
- 使用真实的数据流
|
||||
- 避免过度mock
|
||||
|
||||
## 常见问题
|
||||
|
||||
**Q: 如何处理异步测试?**
|
||||
A: 使用async/await和waitFor函数。
|
||||
|
||||
**Q: 如何测试错误处理?**
|
||||
A: 使用toThrow和expect.assertions验证错误路径。
|
||||
```
|
||||
|
||||
**Step 2: 提交文档**
|
||||
|
||||
```bash
|
||||
git add docs/testing-guide.md
|
||||
git commit -m "docs: add testing guide"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 9: 建立覆盖率趋势监控
|
||||
|
||||
**Files:**
|
||||
- Create: `scripts/coverage-trend.js`
|
||||
- Create: `.github/workflows/coverage-report.yml`
|
||||
|
||||
**Step 1: 创建覆盖率趋势脚本**
|
||||
|
||||
```javascript
|
||||
// scripts/coverage-trend.js
|
||||
const fs = require('fs');
|
||||
const coverage = JSON.parse(fs.readFileSync('coverage/coverage-final.json', 'utf8'));
|
||||
|
||||
const metrics = {
|
||||
statements: coverage.total.statements.pct,
|
||||
branches: coverage.total.branches.pct,
|
||||
functions: coverage.total.functions.pct,
|
||||
lines: coverage.total.lines.pct,
|
||||
};
|
||||
|
||||
console.log(JSON.stringify(metrics, null, 2));
|
||||
```
|
||||
|
||||
**Step 2: 创建覆盖率报告工作流**
|
||||
|
||||
```yaml
|
||||
# .github/workflows/coverage-report.yml
|
||||
name: Coverage Report
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
report:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Generate coverage
|
||||
run: |
|
||||
npm run test:unit -- --coverage
|
||||
node scripts/coverage-trend.js > coverage-metrics.json
|
||||
|
||||
- name: Upload metrics
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-metrics
|
||||
path: coverage-metrics.json
|
||||
```
|
||||
|
||||
**Step 3: 提交**
|
||||
|
||||
```bash
|
||||
git add scripts/coverage-trend.js .github/workflows/coverage-report.yml
|
||||
git commit -m "ci: add coverage trend monitoring"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 10: 更新覆盖率目标
|
||||
|
||||
**Files:**
|
||||
- Modify: `jest.config.js`
|
||||
|
||||
**Step 1: 提升覆盖率目标到35%**
|
||||
|
||||
```javascript
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 25,
|
||||
functions: 35,
|
||||
lines: 35,
|
||||
statements: 35,
|
||||
},
|
||||
},
|
||||
```
|
||||
|
||||
**Step 2: 运行测试验证**
|
||||
|
||||
Run: `npm run test:unit -- --coverage --coverageReporters=text-summary`
|
||||
|
||||
Expected: PASS with coverage above 35%
|
||||
|
||||
**Step 3: 提交**
|
||||
|
||||
```bash
|
||||
git add jest.config.js
|
||||
git commit -m "test: increase coverage threshold to 35%"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验证步骤
|
||||
|
||||
### 验证1: 确认所有测试通过
|
||||
|
||||
Run: `npm run test:unit`
|
||||
|
||||
Expected: All tests pass
|
||||
|
||||
### 验证2: 确认覆盖率达标
|
||||
|
||||
Run: `npm run test:unit -- --coverage --coverageReporters=text-summary`
|
||||
|
||||
Expected: Coverage above 35%
|
||||
|
||||
### 验证3: 确认CI构建通过
|
||||
|
||||
Check: GitHub Actions workflow status
|
||||
|
||||
Expected: All workflows pass
|
||||
|
||||
---
|
||||
|
||||
## 回滚计划
|
||||
|
||||
如果出现问题,可以回滚到之前的配置:
|
||||
|
||||
```bash
|
||||
git log --oneline --all
|
||||
git checkout <commit-hash>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关资源
|
||||
|
||||
- [Jest文档](https://jestjs.io/docs/getting-started)
|
||||
- [React Testing Library](https://testing-library.com/docs/react-testing-library/intro)
|
||||
- [测试最佳实践](https://github.com/goldbergyoni/javascript-testing-best-practices)
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user