log-center/docs/integration_guide.md
zyc 637c479818
All checks were successful
Build and Deploy Log Center / build-and-deploy (push) Successful in 1m30s
feat: initial log center with k8s deployment
2026-01-30 11:49:47 +08:00

300 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Log Center 接入指南
## 概述
Log Center 是一个集中式错误日志收集平台,提供 REST API 供各项目接入,实现运行时错误的统一收集、去重、追踪和分析。
---
## 快速开始
### 服务地址
| 环境 | API 地址 | 仪表盘 |
|------|----------|--------|
| 本地开发 | `http://localhost:8002` | `http://localhost:8003` |
| 生产环境 | `https://log.yourcompany.com` | `https://log.yourcompany.com` |
---
## API 接口
### 上报错误日志
**POST** `/api/v1/logs/report`
#### 请求体 (JSON)
```json
{
"project_id": "rtc_backend",
"environment": "production",
"level": "ERROR",
"timestamp": "2026-01-30T10:30:00Z",
"version": "1.2.3",
"commit_hash": "abc1234",
"error": {
"type": "ValueError",
"message": "invalid literal for int() with base 10: 'abc'",
"file_path": "apps/users/views.py",
"line_number": 42,
"stack_trace": [
"Traceback (most recent call last):",
" File \"apps/users/views.py\", line 42, in get_user",
" user_id = int(request.GET['id'])",
"ValueError: invalid literal for int() with base 10: 'abc'"
]
},
"context": {
"url": "/api/users/123",
"method": "GET",
"user_id": "u_12345",
"request_id": "req_abc123"
}
}
```
#### 字段说明
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `project_id` | string | ✅ | 项目标识,如 `rtc_backend`, `rtc_web` |
| `environment` | string | ✅ | 环境:`development`, `staging`, `production` |
| `level` | string | ✅ | 日志级别:`ERROR`, `WARNING`, `CRITICAL` |
| `timestamp` | string | ❌ | ISO 8601 格式,不传则使用服务器时间 |
| `version` | string | ❌ | 应用版本号 |
| `commit_hash` | string | ❌ | Git commit hash |
| `error.type` | string | ✅ | 异常类型,如 `ValueError`, `TypeError` |
| `error.message` | string | ✅ | 错误消息 |
| `error.file_path` | string | ✅ | 出错文件路径 |
| `error.line_number` | int | ✅ | 出错行号 |
| `error.stack_trace` | array | ✅ | 堆栈信息(数组或字符串) |
| `context` | object | ❌ | 额外上下文信息URL、用户ID等 |
#### 响应
**成功 (200)**
```json
{
"status": "ok",
"id": 123,
"fingerprint": "a1b2c3d4e5f6",
"is_new": true
}
```
**已存在 (200)** - 重复错误自动去重
```json
{
"status": "duplicate",
"id": 123,
"fingerprint": "a1b2c3d4e5f6",
"is_new": false
}
```
---
## 接入示例
### Python (Django / FastAPI)
```python
import requests
import traceback
import os
LOG_CENTER_URL = os.getenv("LOG_CENTER_URL", "http://localhost:8002")
def report_error(exc, context=None):
"""上报错误到 Log Center"""
tb = traceback.extract_tb(exc.__traceback__)
last_frame = tb[-1] if tb else None
payload = {
"project_id": "rtc_backend",
"environment": os.getenv("ENVIRONMENT", "development"),
"level": "ERROR",
"error": {
"type": type(exc).__name__,
"message": str(exc),
"file_path": last_frame.filename if last_frame else "unknown",
"line_number": last_frame.lineno if last_frame else 0,
"stack_trace": traceback.format_exception(exc)
},
"context": context or {}
}
try:
requests.post(
f"{LOG_CENTER_URL}/api/v1/logs/report",
json=payload,
timeout=3 # 快速失败,不影响主业务
)
except Exception:
pass # 静默失败,不影响主业务
```
#### Django 集成位置
修改 `utils/exceptions.py``custom_exception_handler`:
```python
def custom_exception_handler(exc, context):
# 上报到 Log Center (异步,不阻塞响应)
report_error(exc, {
"view": str(context.get("view")),
"request_path": context.get("request").path if context.get("request") else None,
})
# ... 原有逻辑不变 ...
```
---
### JavaScript / TypeScript (React / Vue)
```typescript
const LOG_CENTER_URL = import.meta.env.VITE_LOG_CENTER_URL || 'http://localhost:8002';
interface ErrorPayload {
project_id: string;
environment: string;
level: string;
error: {
type: string;
message: string;
file_path: string;
line_number: number;
stack_trace: string[];
};
context?: Record<string, unknown>;
}
export function reportError(error: Error, context?: Record<string, unknown>) {
// 解析堆栈信息
const stackLines = error.stack?.split('\n') || [];
const match = stackLines[1]?.match(/at\s+.*\s+\((.+):(\d+):\d+\)/);
const payload: ErrorPayload = {
project_id: 'rtc_web',
environment: import.meta.env.MODE,
level: 'ERROR',
error: {
type: error.name,
message: error.message,
file_path: match?.[1] || 'unknown',
line_number: parseInt(match?.[2] || '0'),
stack_trace: stackLines,
},
context: {
url: window.location.href,
userAgent: navigator.userAgent,
...context,
},
};
// 使用 sendBeacon 确保页面关闭时也能发送
if (navigator.sendBeacon) {
navigator.sendBeacon(
`${LOG_CENTER_URL}/api/v1/logs/report`,
JSON.stringify(payload)
);
} else {
fetch(`${LOG_CENTER_URL}/api/v1/logs/report`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
keepalive: true,
}).catch(() => {});
}
}
```
#### Axios 拦截器集成
修改 `src/api/request.ts`:
```typescript
request.interceptors.response.use(
(response) => { /* ... */ },
(error: AxiosError) => {
// 上报到 Log Center
reportError(error, {
url: error.config?.url,
method: error.config?.method,
status: error.response?.status,
});
// ... 原有逻辑不变 ...
}
);
```
---
## 错误去重机制
Log Center 使用 **指纹(fingerprint)** 对错误进行去重:
```
fingerprint = MD5(project_id + error_type + file_path + line_number)
```
相同指纹的错误只会记录一次,后续只更新计数和最后出现时间。
---
## 错误状态流转
```
NEW → VERIFYING → PENDING_FIX → FIXING → FIXED → VERIFIED → DEPLOYED
↓ ↓
CANNOT_REPRODUCE FIX_FAILED
```
| 状态 | 说明 |
|------|------|
| `NEW` | 新上报的错误 |
| `VERIFYING` | 正在验证复现 |
| `CANNOT_REPRODUCE` | 无法复现 |
| `PENDING_FIX` | 等待修复 |
| `FIXING` | 正在修复中 |
| `FIXED` | 已修复,待验证 |
| `VERIFIED` | 已验证修复 |
| `DEPLOYED` | 已部署上线 |
| `FIX_FAILED` | 修复失败 |
---
## 最佳实践
1. **设置超时**: 上报请求设置 3 秒超时,避免影响主业务
2. **静默失败**: 上报失败不应影响用户体验
3. **异步上报**: 使用异步方式上报,不阻塞主流程
4. **添加上下文**: 尽量添加有用的上下文信息(用户ID、请求URL等)
5. **环境区分**: 正确设置 `environment` 字段区分开发/生产
---
## 环境变量配置
### Python 项目
```bash
# .env
LOG_CENTER_URL=http://localhost:8002
ENVIRONMENT=development
```
### JavaScript 项目
```bash
# .env
VITE_LOG_CENTER_URL=http://localhost:8002
```
---
## API 文档
完整 API 文档请访问: [http://localhost:8002/docs](http://localhost:8002/docs)