# Light-Sentry 日志分析系统设计文档 ## 1. 项目概述 ### 1.1 背景 基于用户需求,需要构建一个日志分析系统,支持接收 Sentry 前后端 SDK 的上报,并在 **2核2G ECS + 阿里云OSS** 的资源限制下稳定运行。 ### 1.2 核心目标 - **兼容性**:完全兼容 Sentry SDK 的上报协议(DSN、事件格式) - **轻量级**:适配 2核2G 服务器资源 - **低成本**:利用阿里云 OSS 进行冷存储,降低成本 - **可视化**:提供友好的日志查询和可视化界面 --- ## 2. 系统架构 ### 2.1 整体架构图 ``` ┌─────────────────────────────────────────────────────────────────────┐ │ 客户端 SDK 层 │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Browser SDK │ │ Node SDK │ │ Python SDK │ │ │ │ @sentry/browser │ @sentry/node │ @sentry/python │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ └─────────────────┼─────────────────┘ │ │ ▼ │ │ ┌───────────────────────┐ │ │ │ Sentry API 网关 │ │ │ │ /api/{project}/store │ │ │ └───────────┬───────────┘ │ └───────────────────────────┼─────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 服务端处理层 │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ 事件处理器 │──▶│ 事件转换器 │ │ │ │ (Event Handler)│ │ (Event Converter)│ │ │ └──────────────────┘ └──────────┬───────┘ │ │ │ │ │ ┌───────────────────────┼───────────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │ │ │ Loki 索引 │ │ Loki 存储 │ │ OSS 持久化 │ │ │ │ (索引元数据) │ │ (近期日志) │ │ (历史归档) │ │ │ └───────────────┘ └───────────────┘ └───────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 可视化查询层 │ │ ┌───────────────┐ │ │ │ Grafana │ │ │ │ (查询/图表) │ │ │ └───────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ ``` ### 2.2 核心组件说明 | 组件 | 技术选型 | 角色 | 资源占用 | |------|---------|------|---------| | **API网关** | Express/FastAPI | 接收Sentry协议上报 | ~100MB | | **日志存储** | Loki | 索引和近期日志存储 | ~500MB | | **持久化层** | 阿里云OSS | 历史日志归档 | 按需扩展 | | **可视化** | Grafana | 日志查询和图表展示 | ~300MB | **总内存预估**:~1GB(保留1GB给系统和缓冲) --- ## 3. 技术方案 ### 3.1 Sentry 协议兼容层 #### 3.1.1 协议说明 Sentry SDK 使用 DSN (Data Source Name) 配置上报地址: ``` {PROTOCOL}://{PUBLIC_KEY}@{HOST}/{PATH}/{PROJECT_ID} ``` SDK 向 `/api/{PROJECT_ID}/store/` 端点发送 POST 请求,数据格式为 JSON。 #### 3.1.2 事件数据结构(简化版) ```json { "event_id": "abc123...", "timestamp": "2024-01-01T00:00:00Z", "level": "error", "logger": "javascript", "platform": "javascript", "message": "Uncaught TypeError: Cannot read property", "exception": { "values": [{ "type": "TypeError", "value": "Cannot read property 'x' of undefined", "stacktrace": { "frames": [{ "filename": "app.js", "lineno": 42, "function": "doSomething" }] } }] }, "tags": { "environment": "production", "release": "v1.0.0" }, "contexts": { "request": { "url": "https://example.com/page", "method": "GET" }, "user": { "id": "12345", "email": "user@example.com" } } } ``` #### 3.1.3 API 网关设计 **技术选型**:Node.js + Express(轻量级,内存占用低) **核心端点**: | 端点 | 方法 | 功能 | |------|------|------| | `/api/:projectId/store/` | POST | 接收 Sentry SDK 上报事件 | | `/health` | GET | 健康检查 | **设计要点**: - 支持 Sentry 的 DSN 认证(通过 `X-Sentry-Auth` 头或查询参数) - 异步处理,不阻塞请求响应 - 事件格式校验和标准化 - 支持批量上报 ### 3.2 日志存储方案 #### 3.2.1 Loki 配置 **为什么选择 Loki**: - 轻量级,内存占用远低于 ELK(Elasticsearch 需要至少 4GB) - 基于标签索引,查询效率高 - 与 Grafana 无缝集成 - 支持 OSS 作为后端存储 **关键配置**: ```yaml auth_enabled: false server: http_listen_port: 3100 ingester: lifecycler: address: 127.0.0.1 ring: kvstore: store: inmemory replication_factor: 1 final_sleep: 0s chunk_idle_period: 1h chunk_retain_period: 30s max_transfer_retries: 0 schema_config: configs: - from: 2024-01-01 store: boltdb-shipper object_store: aws schema: v11 index: prefix: loki_index_ period: 24h storage_config: aws: s3: s3://{AK}:{SK}@{REGION}/{BUCKET} s3forcepathstyle: true boltdb_shipper: active_index_directory: /data/loki/index cache_location: /data/loki/cache shared_store: s3 limits_config: reject_old_samples: true reject_old_samples_max_age: 168h chunk_store_config: max_look_back_period: 0s table_manager: retention_deletes_enabled: true retention_period: 30d ``` #### 3.2.2 OSS 存储策略 **存储层级**: | 层级 | 用途 | 存储类型 | 成本 | |------|------|---------|------| | **标准存储** | 近期日志(30天内) | OSS标准 | 0.12元/GB/月 | | **低频存储** | 中期日志(30-90天) | OSS低频 | 0.07元/GB/月 | | **归档存储** | 历史日志(90天以上) | OSS归档 | 0.014元/GB/月 | **生命周期管理**: ```xml transition-to-infrequent-access loki/ Enabled 30 IA 90 Archive 365 ``` ### 3.3 事件处理流程 ``` SDK上报 → API网关 → 格式校验 → 标签提取 → Loki写入 → OSS持久化 ↓ 索引元数据存储 ``` **标签提取策略**(用于 Loki 查询): | 标签名 | 来源字段 | 用途 | |--------|---------|------| | `project` | `project_id` | 项目隔离 | | `environment` | `tags.environment` | 环境区分 | | `level` | `level` | 日志级别过滤 | | `platform` | `platform` | 平台分类 | | `release` | `tags.release` | 版本追踪 | | `logger` | `logger` | 日志来源 | ### 3.4 可视化方案 #### 3.4.1 Grafana 配置 **数据源配置**: - 类型:Loki - URL:`http://localhost:3100` - 认证:无 **查询示例**: ```logql // 查询所有 error 级别日志 {level="error"} |= "error" // 查询特定项目的日志 {project="my-project", environment="production"} // 查询包含特定错误信息的日志 {level="error"} |= "TypeError" // 统计错误数量 count_over_time({level="error"}[1m]) ``` **仪表盘设计**: | 面板 | 功能 | 查询 | |------|------|------| | 错误趋势 | 实时错误数量折线图 | `count_over_time({level="error"}[1m])` | | 环境分布 | 各环境错误占比饼图 | `sum(count_over_time({level="error"}[1h])) by (environment)` | | 平台分布 | 各平台错误占比饼图 | `sum(count_over_time({level="error"}[1h])) by (platform)` | | 最新错误 | 最近错误列表 | `{level="error"} | tail 10` | | Top错误类型 | 错误类型排名 | `topk(5, count by (exception_type) (count_over_time({level="error"}[1h])))` | --- ## 4. 部署方案 ### 4.1 服务器配置 **ECS 规格**:2核2G(阿里云 ecs.g6.large 或同等规格) **操作系统**:Ubuntu 22.04 LTS **磁盘配置**: - 系统盘:40GB SSD - 数据盘:20GB SSD(用于 Loki 索引缓存) ### 4.2 资源分配 | 组件 | CPU | 内存 | |------|-----|------| | 系统预留 | 0.5核 | 512MB | | API网关 (Node.js) | 0.5核 | 256MB | | Loki | 1核 | 768MB | | Grafana | 0.5核 | 512MB | ### 4.3 Docker Compose 部署 ```yaml version: '3.8' services: light-sentry-api: image: light-sentry/api:latest ports: - "9000:9000" environment: - LOKI_URL=http://loki:3100 - OSS_ENDPOINT=${OSS_ENDPOINT} - OSS_ACCESS_KEY=${OSS_ACCESS_KEY} - OSS_SECRET_KEY=${OSS_SECRET_KEY} - OSS_BUCKET=${OSS_BUCKET} depends_on: - loki restart: unless-stopped deploy: resources: limits: cpus: '0.5' memory: 256M loki: image: grafana/loki:2.9.0 ports: - "3100:3100" volumes: - ./loki/config:/etc/loki - ./loki/data:/data/loki environment: - AWS_ACCESS_KEY_ID=${OSS_ACCESS_KEY} - AWS_SECRET_ACCESS_KEY=${OSS_SECRET_KEY} restart: unless-stopped deploy: resources: limits: cpus: '1' memory: 768M grafana: image: grafana/grafana:10.2.0 ports: - "3000:3000" volumes: - ./grafana/data:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning environment: - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} depends_on: - loki restart: unless-stopped deploy: resources: limits: cpus: '0.5' memory: 512M ``` ### 4.4 Nginx 反向代理 ```nginx server { listen 80; server_name logs.example.com; location /api/ { proxy_pass http://localhost:9000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; client_max_body_size 10m; } location /grafana/ { proxy_pass http://localhost:3000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } ``` --- ## 5. SDK 接入指南 ### 5.1 前端 SDK 配置 ```javascript import * as Sentry from '@sentry/browser'; Sentry.init({ dsn: 'https://public_key@logs.example.com/api/1/store/', environment: 'production', release: 'v1.0.0', tracesSampleRate: 1.0, }); ``` ### 5.2 后端 SDK 配置(Node.js) ```javascript import * as Sentry from '@sentry/node'; Sentry.init({ dsn: 'https://public_key@logs.example.com/api/2/store/', environment: 'production', release: 'v1.0.0', tracesSampleRate: 1.0, }); ``` ### 5.3 后端 SDK 配置(Python) ```python import sentry_sdk sentry_sdk.init( dsn="https://public_key@logs.example.com/api/3/store/", environment="production", release="v1.0.0", traces_sample_rate=1.0, ) ``` --- ## 6. 性能优化策略 ### 6.1 内存优化 | 策略 | 说明 | |------|------| | Loki 使用 OSS 作为后端 | 减少本地磁盘和内存占用 | | API网关使用流处理 | 避免一次性加载大请求 | | 限制并发连接数 | 使用 Nginx 限流 | ### 6.2 存储优化 | 策略 | 说明 | |------|------| | OSS 生命周期管理 | 自动降级存储类型 | | Loki 压缩 | 启用 Snappy 压缩 | | 日志采样 | 高频日志采样处理 | ### 6.3 查询优化 | 策略 | 说明 | |------|------| | 标签索引 | 使用标签过滤而非全文搜索 | | 查询缓存 | Grafana 缓存查询结果 | | 时间范围限制 | 默认查询最近24小时 | --- ## 7. 监控与告警 ### 7.1 健康检查 | 检查项 | 端点 | 频率 | |--------|------|------| | API网关 | `/health` | 30秒 | | Loki | `/ready` | 30秒 | | Grafana | `/api/health` | 30秒 | ### 7.2 告警规则 | 告警项 | 条件 | 通知方式 | |--------|------|---------| | API错误率 | 错误率 > 5% | 钉钉/邮件 | | 服务不可用 | 健康检查失败 | 钉钉/邮件 | | 内存使用率 | 内存 > 85% | 钉钉/邮件 | | OSS存储告警 | 存储 > 80% | 阿里云告警 | --- ## 8. 安全策略 ### 8.1 认证授权 - API 网关支持 Sentry DSN 认证 - Grafana 启用基础认证 - Nginx 配置访问控制列表 ### 8.2 数据加密 - 传输层:HTTPS/TLS 1.2+ - 存储层:OSS 服务端加密(SSE-KMS) ### 8.3 访问日志 - Nginx 访问日志记录 - API 网关请求日志 --- ## 9. 成本预估 ### 9.1 服务器成本 | 资源 | 规格 | 月费用 | |------|------|--------| | ECS | 2核2G | ~80元 | | 数据盘 | 20GB SSD | ~10元 | | **合计** | - | **~90元/月** | ### 9.2 OSS 存储成本 假设日日志量:1GB | 存储类型 | 容量 | 月费用 | |----------|------|--------| | 标准存储 | 30GB | ~3.6元 | | 低频存储 | 60GB | ~4.2元 | | 归档存储 | 275GB | ~3.85元 | | **合计** | - | **~11.65元/月** | ### 9.3 总成本 **~100元/月**(含服务器和存储) --- ## 10. 扩展规划 ### 10.1 短期(3个月内) - 完成核心功能开发 - 集成 Sentry 协议 - 部署上线 ### 10.2 中期(6个月内) - 增加日志采样功能 - 优化查询性能 - 增加告警功能 ### 10.3 长期(1年内) - 支持更多日志来源 - 增加分布式追踪 - 考虑升级到更强配置 --- ## 附录:组件版本建议 | 组件 | 推荐版本 | 备注 | |------|---------|------| | Node.js | 20.x LTS | API网关运行环境 | | Express | 4.x | API框架 | | Loki | 2.9.x | 日志存储 | | Grafana | 10.x | 可视化 | | Docker | 24.x | 容器化部署 | --- **文档版本**: v1.0 **创建日期**: 2026-06-16 **适用场景**: 2核2G ECS + 阿里云OSS 资源受限环境