# Log Analysis

> 日志分析技能：从日志中快速定位异常、统计错误分布、提取关键时间线。 支持各种日志格式（JSON、纯文本、结构化、非结构化）。 触发词：帮我看看日志、这段日志什么意思、找找报错、日志分析、error log。 触发场景：线上问题排查、错误日志分析、用户反馈复现、性能问题排查。 即使用户没有说"日志分析"，只要给了一段日志让你看，都应触发此技能。

- Skill: `312362115/log-analysis` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 312362115/log-analysis`
- Raw SKILL.md: https://api.skillmd.com/api/skills/312362115/log-analysis/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: 312362115 (https://skillmd.com/u/312362115)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/312362115/log-analysis

---


# 日志分析（Log Analysis）

> 日志是系统说的话。大部分时候它在说废话，但出问题时，答案就藏在那些废话里。

---

## 分析流程

```
拿到日志
  │
  ├─ 1. 识别日志格式和结构
  ├─ 2. 定位异常和错误
  ├─ 3. 构建时间线
  ├─ 4. 分析根因
  └─ 5. 给出结论和建议
```

---

## 第一步：识别日志格式

| 格式 | 特征 | 处理方式 |
|------|------|---------|
| **JSON 结构化** | 每行一个 JSON 对象 | 解析 JSON，按字段筛选 |
| **标准日志格式** | `[时间] [级别] [模块] 消息` | 正则提取字段 |
| **纯文本** | 无固定格式 | 按关键词和时间戳模式匹配 |
| **堆栈跟踪** | Error + at file:line | 识别错误类型和调用栈 |

如果日志太长（>500 行），先问用户：
- 大概什么时间段出的问题？
- 有没有相关的错误关键词？
- 受影响的用户/请求 ID？

---

## 第二步：定位异常

### 2.1 错误级别扫描

按优先级从高到低扫描：

```
FATAL / CRITICAL → ERROR → WARN → 异常模式（超时、重试、拒绝）
```

### 2.2 关键模式识别

| 模式 | 关键词 | 可能的问题 |
|------|--------|-----------|
| 异常/错误 | `Error`, `Exception`, `FATAL`, `panic` | 代码错误 |
| 超时 | `timeout`, `ETIMEDOUT`, `deadline exceeded` | 网络/依赖慢 |
| 连接失败 | `ECONNREFUSED`, `connection reset`, `ECONNRESET` | 服务不可达 |
| 资源耗尽 | `OOM`, `too many open files`, `pool exhausted` | 资源泄漏 |
| 权限问题 | `403`, `permission denied`, `unauthorized` | 权限配置 |
| 数据问题 | `null`, `undefined`, `NaN`, `invalid` | 数据质量 |
| 重试/降级 | `retry`, `fallback`, `circuit breaker` | 依赖不稳定 |

### 2.3 统计错误分布

```markdown
## 错误统计

| 错误类型 | 次数 | 首次出现 | 最后出现 |
|---------|------|---------|---------|
| ConnectionTimeout | 45 | 14:23:01 | 14:28:33 |
| NullPointerError | 3 | 14:25:12 | 14:25:14 |
| AuthTokenExpired | 12 | 14:20:00 | 14:30:00 |
```

---

## 第三步：构建时间线

将关键事件按时间排列，还原问题发生经过：

```markdown
## 事件时间线

14:20:00  [正常] 服务启动，连接数据库成功
14:23:01  [异常] 首次出现 ConnectionTimeout，目标：redis:6379
14:23:15  [异常] ConnectionTimeout 频率上升，10s 内 15 次
14:24:00  [告警] Redis 连接池耗尽，开始排队
14:25:12  [错误] NullPointerError — getUserSession() 返回 null
          ↑ 因为 Redis 不可用，session 查询失败
14:25:30  [降级] 熔断器触发，Redis 请求直接返回 fallback
14:28:33  [恢复] Redis 连接恢复，ConnectionTimeout 消失
14:30:00  [正常] 错误率归零
```

---

## 第四步：分析根因

### 分析方法

1. **从结果倒推**：用户看到的问题 → 直接原因 → 根本原因
2. **时间相关性**：问题开始时间前后，有没有部署/配置变更/流量突增？
3. **5 Whys**：连续追问"为什么"直到找到根因

### 输出格式

```markdown
## 根因分析

### 现象
用户登录页报 500 错误

### 直接原因
getUserSession() 返回 null，后续代码未做空值处理导致 NullPointerError

### 根本原因
Redis 实例在 14:23 出现网络抖动（可能是运维变更），
导致连接超时 → 连接池耗尽 → session 查询失败 → 空值未处理 → 500

### 因果链
Redis 网络抖动 → 连接超时 → 连接池耗尽 → session 查询失败
→ 返回 null → 未做空值检查 → NullPointerError → 500 响应
```

---

## 第五步：结论和建议

```markdown
## 结论

1. **根因**：Redis 网络抖动导致连接超时，session 查询失败
2. **影响面**：14:23-14:28 期间约 200 个请求受影响
3. **恢复方式**：Redis 连接自动恢复后问题消失

## 建议

### 短期（立即修复）
- getUserSession() 增加空值检查，返回 null 时走降级逻辑而非抛异常

### 中期（防止复发）
- Redis 连接池增加健康检查和自动重连机制
- 添加 Redis 连接状态监控告警

### 长期（提升韧性）
- session 查询增加本地缓存兜底
- 考虑 Redis Sentinel 或 Cluster 提高可用性
```

---

## 分析准则

- **先全局后细节**：先扫一遍日志全貌（错误分布、时间范围），再深入具体错误
- **关注时间相关性**：问题前后有什么变化？部署？配置？流量？
- **区分因果和巧合**：两个事件时间接近不代表有因果关系
- **不猜测**：日志里没有的信息就说"需要进一步确认"，不编原因
- **给可执行建议**：不只是"加个日志"，而是"在 `src/services/auth.ts:45` 的 getUserSession() 返回值后加空值检查"

