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

7.2 KiB
Raw Blame History

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)

{
  "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)

{
  "status": "ok",
  "id": 123,
  "fingerprint": "a1b2c3d4e5f6",
  "is_new": true
}

已存在 (200) - 重复错误自动去重

{
  "status": "duplicate",
  "id": 123,
  "fingerprint": "a1b2c3d4e5f6",
  "is_new": false
}

接入示例

Python (Django / FastAPI)

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.pycustom_exception_handler:

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)

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:

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 项目

# .env
LOG_CENTER_URL=http://localhost:8002
ENVIRONMENT=development

JavaScript 项目

# .env
VITE_LOG_CENTER_URL=http://localhost:8002

API 文档

完整 API 文档请访问: http://localhost:8002/docs