<!-- 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** | 最细粒度的调试信息，用于跟踪代码执行路径:（生产环境默认关闭） | `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`                             | 业务数据相关预期异常（不影响主流程）。例：查询结果为空、数据状态不满足条件    |
| **YmBizException**     | WARN  | `extends YmException`                                | 业务流程中的可控异常（需明确处理流程）。例：参数校验失败、权限不足、业务规则限制 |
| **YmException**        | ERROR | `extends RuntimeException`                           | 系统级不可恢复异常（需立即介入）。例：基础设施故障、关键依赖服务不可用      |
| **自定义业务异常**            | 继承父类  | `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 系统健康度仪表盘）

## 九、改造规划
### 第一阶段（改造阶段）
1. 核心包支撑（2025-05-07 前完成）
2. 服务日志规范化改造（2025-06-31 前完成）
3. 改造进度表：[日志规范改造进度表](https://doc.weixin.qq.com/smartsheet/s3_ARsAJgb9AE0CNf4BpvcLWS2OKw4wg?scode=AE0Auwd4ACgQBF9AHNARsAJgb9AE0&tab=sarhly&viewId=vXVVmV)

### 第二阶段（维护阶段）
1. 日常告警跟进及修复
   - 告警列表导出及跟进情况
2. 告警看板及监控
   - Warning 统计看板
   - Error 统计看板
