错误处理与日志系统技能
概述
错误处理和日志记录是构建可靠、可维护系统的基础设施。不当的错误处理会导致系统崩溃、调试困难;不合理的日志记录会影响性能并浪费存储空间。需要建立完善的错误处理和日志体系。
核心原则: 好的错误处理应该优雅地处理异常,提供有用的错误信息;好的日志系统应该记录关键信息,便于问题排查和性能分析。
何时使用
始终:
- 设计新系统架构时
- 处理异常和错误时
- 实现日志记录系统时
- 设计监控告警时
- 调试生产问题时
- 进行系统审计时
触发短语:
- "系统出错了怎么处理?"
- "如何设计日志系统?"
- "异常应该怎么捕获?"
- "日志级别怎么设置?"
- "如何快速定位问题?"
- "监控告警怎么配置?"
错误处理技能功能
异常处理策略
- 全局异常捕获
- 分层异常处理
- 异常分类和映射
- 错误码标准化
- 异常恢复机制
日志记录模式
- 结构化日志
- 日志级别管理
- 日志聚合和索引
- 日志轮转和归档
- 实时日志分析
监控告警检查
- 错误率监控
- 性能指标监控
- 业务指标监控
- 告警规则配置
- 自动化响应
常见错误处理问题
异常吞噬问题
问题:
捕获异常但不处理,直接忽略
后果:
- 问题被掩盖
- 调试困难
- 系统状态异常
- 用户体验差
解决方案:
- 记录异常信息
- 分类处理不同异常
- 提供用户友好的错误信息
- 实现适当的恢复机制
日志过度记录
问题:
记录过多无用日志信息
后果:
- 存储空间浪费
- 查找困难
- 性能影响
- 成本增加
解决方案:
- 合理设置日志级别
- 结构化日志格式
- 日志采样策略
- 敏感信息过滤
错误信息泄露
问题:
向用户暴露技术细节
后果:
- 安全漏洞
- 用户体验差
- 系统信息泄露
- 攻击面增加
解决方案:
- 错误信息脱敏
- 用户友好提示
- 技术详情记录到日志
- 统一错误响应格式
错误处理架构设计
分层错误处理
架构: 控制器层 -> 服务层 -> 数据层
处理策略:
- 控制器层: 参数验证、用户错误
- 服务层: 业务逻辑错误
- 数据层: 数据库、网络错误
实现要点:
- 每层定义自己的异常类型
- 上层捕获下层异常并转换
- 统一错误响应格式
- 记录完整的错误链路
全局异常处理
架构: 统一异常处理器 -> 错误分类 -> 响应生成
适用场景:
- Web应用全局错误处理
- API服务错误响应
- 批量任务异常处理
实现要点:
- 异常捕获机制
- 错误分类映射
- 日志记录集成
- 监控告警触发
日志系统设计
日志级别规范
| 级别 | 用途 | 示例 |
|---|---|---|
| ERROR | 系统错误、异常 | 数据库连接失败、空指针异常 |
| WARN | 警告信息 | 配置项缺失、性能问题 |
| INFO | 重要业务信息 | 用户登录、订单创建 |
| DEBUG | 调试信息 | 方法调用、参数值 |
| TRACE | 详细跟踪信息 | 循环执行、状态变化 |
结构化日志格式
{
"timestamp": "2024-01-01T12:00:00.000Z",
"level": "ERROR",
"service": "user-service",
"trace_id": "abc123",
"user_id": "user456",
"message": "User login failed",
"context": {
"ip": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
"error_code": "INVALID_PASSWORD"
},
"stack_trace": "java.lang.IllegalArgumentException..."
}
代码实现示例
Python错误处理
import logging
import traceback
from functools import wraps
from typing import Optional
import json
# 配置日志系统
def setup_logging():
"""配置结构化日志"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('app.log'),
logging.StreamHandler()
]
)
# 自定义异常类
class BusinessException(Exception):
"""业务异常"""
def __init__(self, message: str, error_code: str = None, context: dict = None):
self.message = message
self.error_code = error_code
self.context = context or {}
super().__init__(message)
class SystemException(Exception):
"""系统异常"""
def __init__(self, message: str, original_error: Exception = None):
self.message = message
self.original_error = original_error
super().__init__(message)
# 错误处理装饰器
def handle_errors(logger: logging.Logger):
"""统一错误处理装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except BusinessException as e:
logger.error(f"Business error in {func.__name__}: {e.message}",
extra={'error_code': e.error_code, 'context': e.context})
raise
except SystemException as e:
logger.error(f"System error in {func.__name__}: {e.message}",
exc_info=e.original_error)
raise
except Exception as e:
logger.error(f"Unexpected error in {func.__name__}: {str(e)}",
exc_info=True)
raise SystemException("系统内部错误", e)
return wrapper
return decorator
# 结构化日志记录
class StructuredLogger:
"""结构化日志记录器"""
def __init__(self, name: str):
self.logger = logging.getLogger(name)
def log_event(self, level: str, event: str, **context):
"""记录事件日志"""
log_data = {
'event': event,
'timestamp': datetime.utcnow().isoformat(),
**context
}
getattr(self.logger, level.lower())(json.dumps(log_data))
def log_error(self, error: Exception, **context):
"""记录错误日志"""
error_data = {
'error_type': type(error).__name__,
'error_message': str(error),
'stack_trace': traceback.format_exc(),
**context
}
self.logger.error(json.dumps(error_data))
# 使用示例
logger = StructuredLogger('user-service')
@handle_errors(logger.logger)
def create_user(user_data: dict):
"""创建用户"""
if not user_data.get('email'):
raise BusinessException("邮箱不能为空",
error_code="MISSING_EMAIL",
context={'user_data': user_data})
try:
# 创建用户逻辑
user_id = save_user_to_db(user_data)
logger.log_event('INFO', 'user_created',
user_id=user_id, email=user_data['email'])
return user_id
except DatabaseError as e:
raise SystemException("数据库操作失败", e)
# 统一错误响应
def create_error_response(error: Exception) -> dict:
"""创建统一错误响应"""
if isinstance(error, BusinessException):
return {
'error': 'business_error',
'message': error.message,
'error_code': error.error_code,
'context': error.context
}
else:
return {
'error': 'system_error',
'message': '系统内部错误,请稍后重试'
}
Java错误处理
// 自定义异常类
public class BusinessException extends RuntimeException {
private String errorCode;
private Map<String, Object> context;
public BusinessException(String message, String errorCode) {
super(message);
this.errorCode = errorCode;
this.context = new HashMap<>();
}
// getters and setters
}
// 全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
logger.error("Business error: {}", e.getMessage(), e);
ErrorResponse response = ErrorResponse.builder()
.error("business_error")
.message(e.getMessage())
.errorCode(e.getErrorCode())
.context(e.getContext())
.timestamp(Instant.now())
.build();
return ResponseEntity.badRequest().body(response);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(Exception e) {
logger.error("Unexpected error: {}", e.getMessage(), e);
ErrorResponse response = ErrorResponse.builder()
.error("system_error")
.message("系统内部错误")
.timestamp(Instant.now())
.build();
return ResponseEntity.status(500).body(response);
}
}
// 结构化日志
@Component
public class StructuredLogger {
private final Logger logger;
public StructuredLogger() {
this.logger = LoggerFactory.getLogger(StructuredLogger.class);
}
public void logEvent(String level, String event, Map<String, Object> context) {
Map<String, Object> logData = new HashMap<>();
logData.put("event", event);
logData.put("timestamp", Instant.now());
logData.putAll(context);
String logMessage = JsonUtils.toJson(logData);
switch (level.toUpperCase()) {
case "ERROR":
logger.error(logMessage);
break;
case "WARN":
logger.warn(logMessage);
break;
case "INFO":
logger.info(logMessage);
break;
default:
logger.debug(logMessage);
}
}
}
监控和告警
关键监控指标
- 错误率: ERROR级别日志数量/总请求数
- 响应时间: API响应时间分布
- 吞吐量: 每秒处理请求数
- 资源使用: CPU、内存、磁盘使用率
- 业务指标: 订单量、用户活跃度等
告警规则配置
# Prometheus告警规则示例
groups:
- name: error_alerts
rules:
- alert: HighErrorRate
expr: rate(error_logs_total[5m]) > 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "错误率过高"
description: "5分钟内错误率超过10%"
- alert: DatabaseConnectionFailed
expr: increase(db_connection_errors_total[1m]) > 0
for: 0m
labels:
severity: critical
annotations:
summary: "数据库连接失败"
description: "检测到数据库连接错误"
日志管理最佳实践
日志记录原则
- 适量原则: 记录必要信息,避免过度记录
- 结构化: 使用统一格式,便于解析和查询
- 安全原则: 避免记录敏感信息
- 性能考虑: 异步记录,避免影响主业务
- 可追溯性: 包含足够的上下文信息
日志分析策略
- 实时监控: 关键指标实时告警
- 趋势分析: 长期趋势分析
- 异常检测: 自动异常模式识别
- 根因分析: 多维度关联分析
- 容量规划: 基于日志数据的容量预测
相关技能
- api-validator - API接口验证和错误处理
- security-scanner - 安全漏洞扫描和告警
- performance-profiler - 性能分析和监控
- monitoring-alerting - 监控告警系统