# 可观测性文档 (Crawlful Hub) > **定位**:Crawlful Hub 可观测性设计文档 - 确保系统的可观测性,便于问题排查和系统优化。 > **更新日期**: 2026-03-18 > **最高优先级参考**: [Service_Design.md](./Service_Design.md) --- ## 1. 可观测性概述 ### 1.1 定义 可观测性是指通过系统的外部输出(如日志、指标、追踪)来了解系统内部状态的能力。 ### 1.2 重要性 良好的可观测性可以: - 快速定位和解决问题 - 预测和预防系统故障 - 优化系统性能 - 提高系统可靠性 - 降低运维成本 ### 1.3 核心组成 - **业务日志**:记录业务操作的详细信息 - **链路追踪**:追踪请求在系统中的完整路径 - **指标监控**:监控系统的各种指标 --- ## 2. 业务日志 ### 2.1 定义 业务日志是指记录业务操作的详细信息,包括操作人、操作时间、操作类型、操作对象、操作结果等。 ### 2.2 实现方法 #### 2.2.1 日志级别 - **DEBUG**:详细的调试信息 - **INFO**:一般的信息 - **WARN**:警告信息 - **ERROR**:错误信息 - **FATAL**:致命错误信息 #### 2.2.2 日志格式 ```json { "timestamp": "2026-03-18T10:00:00Z", "level": "INFO", "service": "ProductService", "method": "updatePrice", "traceId": "1234567890", "tenantId": "tenant-001", "shopId": "shop-001", "businessType": "TOC", "message": "Updating price for product 123 to 99.99", "data": { "productId": "123", "oldPrice": 89.99, "newPrice": 99.99, "roi": 1.5 } } ``` #### 2.2.3 日志框架 **推荐**: - Node.js:winston, bunyan - Java:log4j, logback - Python:logging, structlog **示例**: ```typescript // Node.js/winston 示例 import winston from 'winston'; const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', format: winston.format.json(), transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }) ] }); // 使用 logger.info('Updating price for product', { productId: '123', oldPrice: 89.99, newPrice: 99.99, traceId: '1234567890', tenantId: 'tenant-001', shopId: 'shop-001', businessType: 'TOC' }); ``` ### 2.3 最佳实践 - **结构化日志**:使用 JSON 格式,便于分析和查询 - **统一日志格式**:所有服务使用相同的日志格式 - **包含必要字段**:时间戳、级别、服务名、方法名、追踪ID、租户ID、店铺ID、业务类型等 - **适当的日志级别**:根据信息的重要性选择合适的级别 - **日志轮转**:定期轮转日志文件,防止日志文件过大 - **日志存储**:使用 ELK Stack、Splunk 等工具存储和分析日志 --- ## 3. 链路追踪 ### 3.1 定义 链路追踪是指追踪请求在系统中的完整路径,包括请求经过的所有服务和操作。 ### 3.2 实现方法 #### 3.2.1 追踪ID **定义**:一个唯一的标识符,用于关联同一个请求的所有操作 **实现**: - 生成唯一的 `traceId` - 在请求开始时创建 `traceId` - 在所有相关操作中传递 `traceId` **示例**: ```typescript // 中间件生成 traceId const traceMiddleware = (req, res, next) => { const traceId = req.headers['x-trace-id'] || uuidv4(); req.traceId = traceId; res.setHeader('x-trace-id', traceId); next(); }; // 使用 app.use(traceMiddleware); // 在服务中使用 async updatePrice(productId: string, price: number, traceId: string): Promise { logger.info('Updating price', { traceId, productId, price }); // 业务逻辑 return product; } ``` #### 3.2.2 分布式追踪系统 **推荐**: - Jaeger - Zipkin - OpenTelemetry **示例**: ```typescript // 使用 OpenTelemetry import { trace } from '@opentelemetry/api'; import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { JaegerExporter } from '@opentelemetry/exporter-jaeger'; // 初始化追踪器 const provider = new NodeTracerProvider(); const exporter = new JaegerExporter({ serviceName: 'product-service' }); provider.addSpanProcessor(new SimpleSpanProcessor(exporter)); provider.register(); // 创建 span const tracer = trace.getTracer('product-service'); async updatePrice(productId: string, price: number): Promise { const span = tracer.startSpan('updatePrice'); try { // 业务逻辑 const product = await this.productRepository.findById(productId); // 创建子 span const calculateRoiSpan = tracer.startSpan('calculateROI', { parent: span }); const roi = await this.pricingService.calculateROI(product, price); calculateRoiSpan.end(); product.price = price; product.roi = roi; const updatedProduct = await this.productRepository.save(product); return updatedProduct; } finally { span.end(); } } ``` ### 3.3 最佳实践 - **统一的追踪ID**:所有服务使用相同的追踪ID格式 - **完整的链路**:追踪请求的完整路径,包括所有服务和操作 - **适当的 span**:为重要操作创建 span - **添加上下文信息**:在 span 中添加业务相关的上下文信息 - **集成监控系统**:将追踪数据与监控系统集成 --- ## 4. 指标监控 ### 4.1 定义 指标监控是指监控系统的各种指标,如响应时间、调用次数、错误率等。 ### 4.2 实现方法 #### 4.2.1 核心指标 - **响应时间**:请求的处理时间 - **调用次数**:服务的调用次数 - **错误率**:错误请求的比例 - **资源使用**:CPU、内存、磁盘、网络等资源的使用情况 - **业务指标**:订单量、销售额、利润率等 #### 4.2.2 监控系统 **推荐**: - Prometheus - Grafana - Datadog - New Relic **示例**: ```typescript // 使用 Prometheus import prometheus from 'prom-client'; // 定义指标 const requestCounter = new prometheus.Counter({ name: 'http_requests_total', help: 'Total number of HTTP requests', labelNames: ['method', 'endpoint', 'status'] }); const requestDuration = new prometheus.Histogram({ name: 'http_request_duration_seconds', help: 'HTTP request duration in seconds', labelNames: ['method', 'endpoint'], buckets: [0.1, 0.5, 1, 2, 5] }); // 中间件 const metricsMiddleware = (req, res, next) => { const start = process.hrtime(); res.on('finish', () => { const duration = process.hrtime(start); const seconds = duration[0] + duration[1] / 1e9; requestCounter.inc({ method: req.method, endpoint: req.path, status: res.statusCode }); requestDuration.observe({ method: req.method, endpoint: req.path }, seconds); }); next(); }; // 使用 app.use(metricsMiddleware); app.get('/metrics', (req, res) => { res.set('Content-Type', prometheus.register.contentType); res.end(prometheus.register.metrics()); }); ``` ### 4.3 最佳实践 - **定义关键指标**:根据业务需求定义关键指标 - **设置合理的告警**:为重要指标设置告警 - **可视化**:使用 Grafana 等工具可视化指标 - **定期分析**:定期分析指标数据,发现问题和优化机会 - **集成业务指标**:将业务指标与技术指标结合 --- ## 5. 可观测性集成 ### 5.1 日志、追踪和指标的关联 - **使用相同的 traceId**:将日志、追踪和指标关联起来 - **统一的上下文**:在所有可观测性数据中包含相同的上下文信息 - **集成平台**:使用 ELK Stack、Grafana 等平台集成所有可观测性数据 ### 5.2 监控仪表盘 **推荐仪表盘**: - **系统健康仪表盘**:显示系统的整体健康状态 - **服务性能仪表盘**:显示各个服务的性能指标 - **业务指标仪表盘**:显示业务相关的指标 - **告警仪表盘**:显示当前的告警状态 ### 5.3 告警策略 - **设置合理的阈值**:根据业务需求设置合理的告警阈值 - **分级告警**:根据问题的严重程度设置不同级别的告警 - **告警通知**:通过邮件、短信、Slack 等渠道发送告警通知 - **告警抑制**:避免告警风暴 --- ## 6. 最佳实践 ### 6.1 设计原则 - **可观测性优先**:在系统设计阶段就考虑可观测性 - **统一标准**:所有服务使用相同的可观测性标准 - **适度采集**:采集足够的数据,但不过度采集 - **数据保留**:设置合理的数据保留策略 ### 6.2 实现建议 - **使用开源工具**:如 ELK Stack、Prometheus、Grafana、Jaeger 等 - **自动化部署**:自动化可观测性工具的部署和配置 - **定期演练**:定期演练故障排查和恢复流程 - **持续优化**:根据实际情况持续优化可观测性方案 --- ## 7. 相关文档 - [Service_Design.md](./Service_Design.md) - [Data_Consistency.md](./Data_Consistency.md) - [Architecture_Overview.md](./Architecture_Overview.md) --- *本文档基于服务设计文档,最后更新: 2026-03-18*