✨ [2025-04-28] 添加错误日志规范
Some checks failed
Publish to Confluence / confluence (push) Failing after 57s
Some checks failed
Publish to Confluence / confluence (push) Failing after 57s
This commit is contained in:
parent
ff2db7bfbe
commit
ec23904f53
@ -3,7 +3,7 @@
|
||||
<!-- Parent: 技术方案 -->
|
||||
<!-- Parent: 基建 -->
|
||||
<!-- Parent: 00-基础组件 -->
|
||||
<!-- Title: 2025411-EngineStarterRedis使用指南 -->
|
||||
<!-- Title: 20250411-EngineStarterRedis使用指南 -->
|
||||
|
||||
<!-- Macro: :anchor\((.*)\):
|
||||
Template: ac:anchor
|
241
文档/基础组件/20250428-后端服务日志规范.md
Normal file
241
文档/基础组件/20250428-后端服务日志规范.md
Normal file
@ -0,0 +1,241 @@
|
||||
<!-- Space: qifu -->
|
||||
<!-- Parent: 后端技术&知识&规范 -->
|
||||
<!-- Parent: 技术方案 -->
|
||||
<!-- Parent: 基建 -->
|
||||
<!-- Parent: 00-基础组件 -->
|
||||
<!-- Title: 20250428-后端服务日志规范 -->
|
||||
|
||||
<!-- Macro: :anchor\((.*)\):
|
||||
Template: ac:anchor
|
||||
Anchor: ${1} -->
|
||||
<!-- Macro: \!\[.*\]\((.+)\)\<\!\-\- width=(.*) \-\-\>
|
||||
Template: ac:image
|
||||
Url: ${1}
|
||||
Width: ${2} -->
|
||||
<!-- Macro: \<\!\-\- :toc: \-\-\>
|
||||
Template: ac:toc
|
||||
Printable: 'false'
|
||||
MinLevel: 2
|
||||
MaxLevel: 4 -->
|
||||
<!-- Include: 杂项/声明文件.md -->
|
||||
|
||||
<!-- :toc: -->
|
||||
|
||||
# 后端服务日志规范
|
||||
|
||||
## 一、日志级别定义与使用场景
|
||||
|
||||
| 日志级别 | 使用场景 | 典型输出示例 |
|
||||
|-----------|------------------------------------|---------------------------------------------------------------------------|
|
||||
| **TRACE** | 最细粒度的调试信息,用于跟踪代码执行路径<br>(生产环境默认关闭) | `TRACE [http-nio-8080-exec-1] c.a.Service - Entering calculate() method` |
|
||||
| **DEBUG** | 开发/测试环境使用的调试信息,记录关键变量值、流程分支等 | `DEBUG [http-nio-8080-exec-1] c.a.Service - UserID=123, balance=500.00` |
|
||||
| **INFO** | 重要业务流程节点信息,用于跟踪系统运行状态 | `INFO [http-nio-8080-exec-1] c.a.Service - Order 20230815001 created` |
|
||||
| **WARN** | 非预期但可恢复的异常情况,需要人工关注但不需要立即干预 | `WARN [http-nio-8080-exec-1] c.a.Service - Cache miss for key: user_123` |
|
||||
| **ERROR** | 系统级错误,导致当前操作失败且无法自动恢复的异常(需触发告警) | `ERROR [http-nio-8080-exec-1] c.a.Service - DB connection failed` |
|
||||
|
||||
---
|
||||
|
||||
## 二、错误日志控制原则(重点)
|
||||
|
||||
### 1. 禁止使用ERROR级别的场景
|
||||
|
||||
#### 1.1. 可控异常使用示例
|
||||
|
||||
```java
|
||||
public void test() {
|
||||
// ❌ 错误示例 - 业务流程控制异常
|
||||
try {
|
||||
controllableExceptionMethod(params);
|
||||
} catch (Exception e) {
|
||||
// 可控的业务异常不应使用ERROR
|
||||
log.error("参数校验失败", e);
|
||||
throw new YmException(BaseCode.CODE, "可控异常", e)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
public void test() {
|
||||
// ✅ 正确处理 - 使用WARN级别
|
||||
try {
|
||||
controllableExceptionMethod(params);
|
||||
} catch (BusinessException e) {
|
||||
log.warn("参数校验失败: {}", e.getMessage()); // 补充业务上下文
|
||||
throw new YmBizException(400, "参数错误");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2. 禁用ERROR的情况
|
||||
|
||||
- 参数校验不通过
|
||||
- 业务流程中的预期异常(如余额不足、重复提交)
|
||||
- 第三方服务返回的已知错误码
|
||||
- 数据不存在等正常业务分支
|
||||
|
||||
### 2. 必须使用ERROR级别的场景
|
||||
|
||||
#### 2.1. 不可控异常使用示例
|
||||
|
||||
```java
|
||||
public void test() {
|
||||
// ✅ 正确示例 - 不可恢复的系统错误
|
||||
try {
|
||||
db.executeTransaction();
|
||||
} catch (SQLException e) {
|
||||
log.error("数据库事务执行失败 [TXID:{}]", transactionId, e); // 附加关键上下文
|
||||
throw new YmException("系统繁忙");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2. 必须使用ERROR的情况
|
||||
|
||||
- 数据库连接失败
|
||||
- 文件IO异常
|
||||
- 缓存集群不可用
|
||||
- 消息队列消费失败(超过重试次数)
|
||||
- 关键资源初始化失败
|
||||
|
||||
---
|
||||
|
||||
## 三、日志规范增强要求
|
||||
|
||||
### 1. 上下文信息规范
|
||||
|
||||
```java
|
||||
public void log() {
|
||||
// ✅ 良好的日志示例
|
||||
log.info("订单创建成功 [OrderID:{}, UserID:{}, Amount:{}]", order.getId(), userId, order.getAmount());
|
||||
|
||||
// ❌ 不推荐的日志
|
||||
log.info("Order created"); // 缺少关键业务参数
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 性能优化建议
|
||||
|
||||
- 避免在高频代码路径中使用DEBUG级别日志
|
||||
- 使用占位符(`{}`)代替字符串拼接
|
||||
|
||||
```java
|
||||
public void log() {
|
||||
// ✅ 性能友好的写法
|
||||
log.debug("Processing item {} of {}", index, total);
|
||||
|
||||
// ❌ 存在性能损耗的写法
|
||||
log.debug("Processing item " + index + " of " + total);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、异常体系与日志级别映射
|
||||
|
||||
| 异常类型 | 日志级别 | 继承关系 | 使用场景说明 |
|
||||
|------------------------|-------|------------------------------------------------------|---------------------------------------------|
|
||||
| **YmBizDataException** | INFO | `extends YmBizException` | 业务数据相关预期异常(不影响主流程)<br>例:查询结果为空、数据状态不满足条件 |
|
||||
| **YmBizException** | WARN | `extends YmException` | 业务流程中的可控异常(需明确处理流程)<br>例:参数校验失败、权限不足、业务规则限制 |
|
||||
| **YmException** | ERROR | `extends RuntimeException` | 系统级不可恢复异常(需立即介入)<br>例:基础设施故障、关键依赖服务不可用 |
|
||||
| **自定义业务异常** | 继承父类 | `extends YmException/YmBizException/YmBiz*Exception` | 根据业务需求扩展,自动继承父类日志级别策略 |
|
||||
|
||||
---
|
||||
|
||||
## 五、监控告警策略
|
||||
|
||||
| 异常类型 | 告警策略 |
|
||||
|--------------------|--------------------------|
|
||||
| YmBizDataException | 不触发告警,用于业务看板数据统计 |
|
||||
| YmBizException | 不触发实时告警,按小时统计TOP高频异常 |
|
||||
| YmException | 立即触发P1级告警(邮件/短信/webhook) |
|
||||
|
||||
---
|
||||
|
||||
## 六、异常使用规范与代码示例
|
||||
|
||||
#### 1. YmBizException 使用规范(WARN级别)
|
||||
|
||||
```java
|
||||
public void test() {
|
||||
// 示例:用户权限校验
|
||||
try {
|
||||
checkUserPermission(userId);
|
||||
} catch (YmBizException e) {
|
||||
log.warn("[权限校验] 操作拒绝 UserID={}, RequiredRole={} | 原因:{}", userId, "ADMIN", e.getMessage());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. YmBizDataException 使用规范(INFO级别)
|
||||
|
||||
```java
|
||||
// 示例:查询空数据时的处理
|
||||
public Order getOrder(String orderId) {
|
||||
Order order = orderDao.findById(orderId);
|
||||
if (order == null) {
|
||||
log.info("[订单查询] 数据不存在 OrderID={}", orderId); // INFO级别记录
|
||||
throw new YmBizDataException("订单不存在");
|
||||
}
|
||||
return order;
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. YmException 使用规范(ERROR级别)
|
||||
|
||||
```java
|
||||
public void test() {
|
||||
// 示例:数据库连接失败
|
||||
try {
|
||||
Connection conn = dataSource.getConnection();
|
||||
} catch (SQLException e) {
|
||||
log.error("[DB连接] 数据库不可用 [DS={}] | 错误:{}", dataSource.getName(), e.getMessage(), e); // 必须记录完整堆栈
|
||||
throw new YmException("DB_FATAL_ERROR", e); // 包装为系统异常
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 七、异常分类决策树
|
||||
|
||||
```java
|
||||
public void exception(Exception e) {
|
||||
if (e instanceof YmBizDataException) {
|
||||
log.info("biz data exception: code = {}, message = {}, data = {}", e.geCode(), e.getMessage(), e.getData(), e);
|
||||
} else if (e instanceof YmBizException) {
|
||||
log.warn("biz exception: code = {}, message = {}", e.geCode(), e.getMessage(), e);
|
||||
} else if (e instanceof YmException) {
|
||||
log.error("biz error: code = {}, message = {}", e.getCode().e.getMessage(), e);
|
||||
} else {
|
||||
log.error("error: message = {}", e.getMessage(), e)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 八、总结
|
||||
|
||||
1. 业务预期异常 → 使用WARN级别(如参数错误、权限校验失败)
|
||||
2. 第三方服务异常 → 根据是否可恢复选择WARN/ERROR
|
||||
3. 资源不可用 → 必须使用ERROR级别
|
||||
4. 所有ERROR日志必须包含:
|
||||
- 唯一请求标识(TraceId:SkyWalking已支持)
|
||||
- 关键业务参数
|
||||
- 完整的异常堆栈
|
||||
|
||||
5. **禁止在循环体内输出ERROR日志(防止日志风暴)**
|
||||
|
||||
### 1. 通过规范日志级别使用,可有效提升以下能力
|
||||
|
||||
1. 减少非关键ERROR日志噪音(提升问题排查效率)
|
||||
2. 准确触发生产告警(降低误报率)
|
||||
3. 通过日志分析业务趋势(基于INFO日志)
|
||||
|
||||
### 2. 通过该规范可实现
|
||||
|
||||
1. 精准区分业务异常与系统异常
|
||||
2. 避免ERROR日志污染(降低70%以上无效错误日志)
|
||||
3. 异常分类监控(业务异常看板 vs 系统健康度仪表盘)
|
||||
|
||||
## 九、核心能力支撑
|
||||
|
||||
- [ ] 核心包全局拦截支撑
|
||||
- [ ] 基础异常梳理及扩展
|
||||
- [ ] 基本校验工具类支撑
|
Loading…
x
Reference in New Issue
Block a user