# Athena Query SOP (athena_query_sop)

## 用途
通过浏览器访问 AWS Athena 控制台，查询 CloudFront 日志（Parquet 格式），排查 403/404 原因、WAF Block、流量异常等问题。

## 前置条件
- 浏览器已登录 AWS 控制台（有 Athena 权限）
- 使用 Kiro IDE 编辑器（基于 Ace Editor）
- 目标数据库（Catalog: `AwsDataCatalog`, Database: `default`）

## 表结构

### 1. cloudfront_logs_parquet_pp_prod
CloudFront 标准日志表，Parquet 格式，按 `year/month/day/hour` 分区。

**核心列**：

| 列名 | 类型 | 说明 |
|------|------|------|
| date | string | 日志日期（如 `2026-04-30`） |
| time | string | 日志时间（如 `00:28:52`） |
| c_ip | string | 客户端 IP |
| cs_method | string | HTTP 方法（GET/POST 等） |
| cs_host | string | 请求的 Host 头 |
| cs_uri_stem | string | 请求路径（URL 路径部分） |
| cs_uri_query | string | 请求查询参数 |
| sc_status | string | HTTP 状态码（200/403/404 等） |
| sc_bytes | string | 响应字节数 |
| cs_user_agent | string | 客户端 User-Agent |
| cs_referer | string | 来源页面 URL |
| x_edge_location | string | CloudFront Edge 节点 |
| x_edge_result_type | string | 结果类型（Hit/Miss/Error 等） |
| x_edge_detailed_result_type | string | 详细结果类型 |
| x_edge_response_result_type | string | 响应结果类型 |
| x_edge_request_id | string | 请求 ID（可关联 WAF 日志） |
| time_taken | string | 请求耗时（秒） |
| time_to_first_byte | string | TTFB（秒） |
| cs_protocol | string | 协议（https/http） |
| cs_protocol_version | string | HTTP 协议版本 |
| ssl_protocol | string | SSL/TLS 协议版本 |
| ssl_cipher | string | SSL 加密套件 |
| c_port | string | 客户端端口 |
| distributionid | string | CloudFront Distribution ID |
| sc_content_type | string | 响应 Content-Type |
| sc_content_len | string | 响应内容长度 |
| fle_status | string | 字段级加密状态 |
| fle_encrypted_fields | string | 字段级加密字段 |
| x_forwarded_for | string | X-Forwarded-For 头 |
| x_host_header | string | 实际 Host 头 |
| cs_cookie | string | Cookie |
| sc_range_start | string | Range 请求起始 |
| sc_range_end | string | Range 请求结束 |

**分区列**（独立列，不在数据行中）：

| 列名 | 说明 |
|------|------|
| year | 如 `2026` |
| month | 如 `5` |
| day | 如 `6` |
| hour | 如 `0`~`23` |

### 2. 视图（17 个视图）
> 视图名较长，通过 `SHOW VIEWS` 获取完整列表。常见用途：

- **流量概览**：按日期/状态码聚合的视图
- **慢查询分析**：time_taken 较高的请求
- **4xx/5xx 统计**：按路径/状态码聚合错误
- **WAF 关联**：可关联 WAF 日志的请求

## 关键经验

### ⚠️ 分区裁剪（最重要）
`cloudfront_logs_parquet_pp_prod` 的分区列是 `year/month/day`（三层独立列），**不是** `date` 列。

**正确写法（必须用分区列过滤，否则全表扫描超时）**：
```sql
WHERE year = '2026' AND month = '5' AND day = '6'
```

**错误写法（会触发全表扫描，大概率超时）**：
```sql
WHERE date = '2026-05-06'
```

### ⚠️ Athena 不支持批量提交
每次只能执行一条 SQL。Ace Editor 需先清空再写入新 SQL。

### ⚠️ Ace Editor API
在 Kiro IDE 中，使用以下 JS 操作编辑器：
```js
editor.setValue(yourSqlString);
```
然后点击 "Run" 按钮执行。

## 操作步骤

### 步骤 1：打开 Athena 控制台
1. 浏览器访问 AWS 控制台 → 搜索 "Athena"
2. 进入查询编辑器（Query Editor）
3. 确认 Database 选择 `default`

### 步骤 2：检查表是否存在
```sql
SHOW TABLES IN default;
```
确认 `cloudfront_logs_parquet_pp_prod` 存在。

### 步骤 3：检查分区
```sql
SHOW PARTITIONS cloudfront_logs_parquet_pp_prod;
```
确认目标日期有数据分区。

### 步骤 4：编写查询（必遵守分区裁剪规则）

**示例 1：查特定文件的 403/404 原因**
```sql
SELECT 
  date,
  time,
  c_ip,
  cs_method,
  cs_uri_stem,
  cs_uri_query,
  sc_status,
  sc_bytes,
  cs_user_agent,
  x_edge_result_type,
  x_edge_detailed_result_type,
  x_edge_response_result_type,
  cs_referer
FROM cloudfront_logs_parquet_pp_prod
WHERE cs_uri_stem LIKE '%目标文件名.mp4%'
  AND year = '2026' AND month = '5' AND day = '6'
ORDER BY time DESC
LIMIT 50;
```

**示例 2：查某 IP 的所有请求**
```sql
SELECT date, time, cs_method, cs_uri_stem, sc_status, x_edge_result_type
FROM cloudfront_logs_parquet_pp_prod
WHERE c_ip = 'x.x.x.x'
  AND year = '2026' AND month = '5' AND day = '6'
ORDER BY time;
```

**示例 3：统计某天各状态码数量**
```sql
SELECT sc_status, COUNT(*) AS cnt
FROM cloudfront_logs_parquet_pp_prod
WHERE year = '2026' AND month = '5' AND day = '6'
GROUP BY sc_status
ORDER BY cnt DESC;
```

**示例 4：查 WAF Block 的请求（x_edge_result_type = 'Error'）**
```sql
SELECT date, time, c_ip, cs_uri_stem, sc_status, x_edge_detailed_result_type, x_edge_request_id
FROM cloudfront_logs_parquet_pp_prod
WHERE x_edge_detailed_result_type LIKE '%Block%'
  AND year = '2026' AND month = '5' AND day = '6'
ORDER BY time DESC;
```

**示例 5：查慢请求（耗时 > 5 秒）**
```sql
SELECT date, time, c_ip, cs_uri_stem, sc_status, time_taken, x_edge_location
FROM cloudfront_logs_parquet_pp_prod
WHERE CAST(time_taken AS DOUBLE) > 5.0
  AND year = '2026' AND month = '5' AND day = '6'
ORDER BY CAST(time_taken AS DOUBLE) DESC;
```

### 步骤 5：执行查询
1. 将 SQL 写入 Ace Editor（如用自动化，通过 `editor.setValue(sql)` 设置）
2. 点击 "Run" 按钮（或 Ctrl+Enter）
3. 等待结果（通常 2-10 秒，分区裁剪好则快）

### 步骤 6：结果分析
- **403**：多为 WAF Block 或签名验证失败。检查 `x_edge_detailed_result_type`，若含 `Block` 则关联 WAF 日志
- **404**：文件不存在或路径错误。检查 `cs_uri_stem` 和 Distribution 配置
- **Error**：CloudFront 内部错误，检查 `x_edge_result_type`
- **大量 499**：客户端提前断开连接

## 视图查询

### 查所有视图
```sql
SHOW VIEWS IN default;
```

### 查视图结构
```sql
DESCRIBE <view_name>;
```

### 查视图定义
```sql
SHOW CREATE VIEW <view_name>;
```

## 高级技巧

### 1. 时间范围查询（跨天）
```sql
SELECT date, COUNT(*) AS req_count
FROM cloudfront_logs_parquet_pp_prod
WHERE year = '2026' AND month = '5'
  AND day BETWEEN '1' AND '7'
GROUP BY date
ORDER BY date;
```

### 2. 按小时聚合
```sql
SELECT hour, sc_status, COUNT(*) AS cnt
FROM cloudfront_logs_parquet_pp_prod
WHERE year = '2026' AND month = '5' AND day = '6'
GROUP BY hour, sc_status
ORDER BY hour, sc_status;
```

### 3. 查 Top N 热门路径
```sql
SELECT cs_uri_stem, COUNT(*) AS hits
FROM cloudfront_logs_parquet_pp_prod
WHERE year = '2026' AND month = '5' AND day = '6'
GROUP BY cs_uri_stem
ORDER BY hits DESC
LIMIT 20;
```

### 4. 用 x_edge_request_id 关联 WAF 日志
```sql
-- 先查出一条请求的 request_id
SELECT x_edge_request_id, date, time, c_ip, cs_uri_stem, sc_status
FROM cloudfront_logs_parquet_pp_prod
WHERE year = '2026' AND month = '5' AND day = '6'
  AND sc_status = '403'
  AND x_edge_detailed_result_type LIKE '%Block%'
LIMIT 5;

-- 然后用 x_edge_request_id 去 WAF 日志表关联查询
```

## 常见问题

### Q: 查询超时怎么办？
A: 检查是否忘了分区裁剪！必须用 `year/month/day` 过滤。视图本身可能已有分区过滤，但自定义 SQL 必须加。

### Q: 查不出来数据？
A: 三步排查：① `SHOW PARTITIONS` 确认分区存在 ② `SELECT * FROM table WHERE year='...' AND month='...' AND day='...' LIMIT 5` 确认能查到数据 ③ 检查条件拼写

### Q: 怎么查最新数据？
A: 先查分区找到最新日期：`SHOW PARTITIONS cloudfront_logs_parquet_pp_prod`，看到最新分区后再查。

### Q: 怎么获取列名？
A: `DESCRIBE cloudfront_logs_parquet_pp_prod;`

## 自动化集成
- 通过 `tmwebdriver_sop`（TMWebDriver）在浏览器中操作 Athena 控制台
- Ace Editor 注入 SQL：`editor.setValue("SELECT ...")`
- 点击 "Run" 按钮执行
- 读取结果区域获取返回数据

## 参考
- 表列结构：详见 `athena_columns.txt`
- 示例 SQL：详见 `athena_query.sql`
- Athena 分区最佳实践：始终用分区列（year/month/day）过滤
