阿里云 SLS 查询与分析

场景说明

当用户想要:

  • 解释、重写、优化或执行已有查询
  • 将自然语言需求转换为 SLS 索引查询SQLSPL 语句

时使用本 Skill。

前置条件

安装 Aliyun CLI

运行 aliyun version 确认版本 >= 3.3.8。若未安装或版本过低,请按文档 references/cli-installation-guide.md 安装或更新。

更新插件

aliyun plugin update

检查阿里云凭证已配置

运行 aliyun configure list 检查凭证是否已配置。

若未显示有效 profile,停止并请用户在本会话之外运行 aliyun configure

安全规则:

  • 绝不读取、回显或打印 AK/SK 值
  • 绝不要求用户将 AK/SK 粘贴到对话中
  • 使用 aliyun configure list 检查凭证状态

RAM 权限要求

APICLIAction用途
GetLogsV2get-logs-v2log:GetLogStoreLogs运行查询 / SQL / SPL 并读取结果
GetIndexget-indexlog:GetIndex读取索引配置以验证前置条件

最小及完整 RAM 策略 JSON 见 references/ram-policies.md

权限失败处理: 如果调用返回 Unauthorized 权限错误,停止并向用户展示 references/ram-policies.md。未经用户明确确认,不要换另一个账号重试。

可观测性(每条 aliyun api 命令都必须遵守)

加载本 Skill 时,为整个会话生成一次随机 session ID(32 字符小写十六进制字符串)。在下方用作 {session-id}

规则: 每条调用云 API 的 aliyun CLI 命令必须包含 --user-agent 标志。本地工具命令(如 configurepluginversion)不支持该标志,应排除。

--user-agent "AlibabaCloud-Agent-Skills/alibabacloud-sls-query/{session-id}"

示例(假设 session-id 为 a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6):

aliyun sls get-logs-v2 --project my-project --logstore my-logstore \
  --from 1740000000 --to 1740003600 --query '*' \
  --user-agent "AlibabaCloud-Agent-Skills/alibabacloud-sls-query/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"

在任何 aliyun API 命令调用上,都不要跳过、改变格式或省略 --user-agent

核心工作流

  1. 读取索引配置(GetIndex)
  2. 选择查询模式
  3. 构建语句
  4. 解析时间范围
  5. 执行查询
  6. 从响应中提取数据
  7. 呈现 CLI 命令和结果

步骤 1:读取索引配置(强制)

始终先调用 get-index —— 索引配置决定步骤 2 中哪些查询模式可用。

aliyun sls get-index \
  --project <project> --logstore <logstore>

响应中有两个部分驱动后续所有决策:

部分含义
line全文索引 —— 缺失表示全文搜索已禁用
keys字段索引 —— 字段 → { type, doc_value, token, caseSensitive, chn, ... } 的映射。doc_value: true 表示该字段已启用统计

如果调用返回 IndexConfigNotExist(HTTP 404),或响应中 linekeys 均未填充,则该 Logstore 完全没有索引 —— 立即停止并告知用户必须先创建索引,才能运行任何查询 / SQL / SPL。

  • 响应可能很大 —— 只提取与当前查询相关的字段。按 logstore 缓存并在会话内复用。

字段类型、分词,以及 get-index 如何映射到能力,见 references/related-apis.mdreferences/query-analysis.md

步骤 2:选择查询模式(关键)

查询语句采用以下形式之一:

优先级模式语句形式使用时机要求
1索引搜索&lt;index-search&gt;过滤原始日志;按时间顺序和分页返回日志全文(line)或任一字段索引(keys.&lt;field&gt;
2SQL`<index-search> \<SQL>`聚合、GROUP BY、排序、窗口、top-N、投影等分析操作目标字段有 keys.&lt;field&gt;doc_value: true
3SQL 扫描`<index-search> \<SQL scan>`用户要求
4SPL`<index-search> \<SPL>`用户要求

选择规则:

  • 为最快速度,始终优先索引搜索
  • 当用户需要分析操作或字段投影而非获取全部原始日志时(如聚合、GROUP BY、排序、窗口分析、top-N,或只返回所需字段 / 列),使用索引搜索 + SQL
  • 不要主动选择 SQL 扫描SPL;仅在用户明确要求时使用。

完整决策指南见 references/query-analysis.md

步骤 3:编写语句

#### 3.1 先构建索引搜索段(| 左侧)

收集所有可用索引搜索语法表达的过滤条件,放在第一个 | 之前。若无过滤条件则用 *

* and "payment failed" and status: "500" and not path: "/healthz"
  • * 匹配全部;"..." 是全文(需要全文索引)。
  • key: "value" 是字段过滤(需要字段索引)。
  • and / or / not 组合;用括号分组。
  • key: * 表示字段存在。范围(&gt;&gt;=[a, b])仅对 long / double 有效。

如果无需聚合或行级处理即可完整回答需求,到此为止 —— 这已是一个完整的索引搜索。完整索引搜索语法见 references/query-analysis.md

#### 3.2 追加 SQL —— 用于聚合 / 分析

status: 500 | SELECT date_trunc('minute', __time__) AS minute,
                    count(*) AS errors
              FROM log
              GROUP BY minute
              ORDER BY minute
  • 阅读 references/query-analysis.md 了解查询与 SQL 规则
  • 表名为 log(建议省略)。
  • SQL 遵循 get-index 中的索引字段类型 —— long / double 字段可直接比较(status &gt;= 500)。仅当字段索引为 text 但需要数值语义时才转换(用 try_cast 抑制错误)。
  • 特殊函数选择(聚合、JSON、正则、日期时间、IP 地理位置…)见 references/functions-guide.md

#### 3.3 追加 SPL —— 用于行级处理 / 灵活过滤

status: 500 and service: payment
| where try_cast(latency as BIGINT) > 1000
| extend latency_ms = try_cast(latency as BIGINT)
| project service, latency_ms, message

SPL 语法、管道命令和字段处理规则,请阅读 references/spl-guide.md

#### 3.4 追加 SQL 扫描 —— 目标字段无索引 / 统计时的兜底

语法遵循常规 SQL(见 3.2),有一点不同:每个字段都是 varchar,因此数值比较或运算前始终先 cast() / try_cast()。扫描语义见 references/query-analysis.md

* | set session mode=scan; SELECT api, count(1) AS pv FROM log GROUP BY api

步骤 4:解析时间范围

在构建 CLI 命令之前,将 --from / --to 生成为 Unix 秒级时间戳--from 为闭区间,--to 为开区间。

从三种输入模式中选择一种:

  1. 相对时间 —— 用户说"最近 / 过去 N 分钟 | 小时 | 天"。
  2. 无时区的自然语言绝对时间 —— 归一化为 YYYY-MM-DD HH:MM:SS,然后按机器本地时区解析。
  3. 带明确时区的绝对时间 —— 按客户提供的时区或 UTC 偏移解析。

1. 相对时间

最近 15 分钟

FROM=$(($(date +%s) - 900))

TO=$(date +%s)


**2. 无时区的自然语言绝对时间**

如果用户给出日期 / 时间但无时区,使用机器本地时区。先将 `2026年3月13日12点` 这类自然语言归一化为 `2026-03-13 12:00:00`,再按本地时间解析。

示例:2026年3月13日12点 -> 2026-03-13 12:00:00

Linux(GNU date):本地时区

FROM=$(date -d "2026-03-13 12:00:00" +%s)

macOS(BSD date):本地时区

FROM=$(date -j -f "%Y-%m-%d %H:%M:%S" "2026-03-13 12:00:00" +%s)


对于"2026年3月13日12点到13点"这类时间范围,用同样方式计算两个端点。对于单个时间点请求,从用户意图推断一个实用窗口;若不清楚,执行前先询问范围。

**3. 带明确时区的绝对时间**

将本地日期 / 时间转换为 Unix 时间戳:用 `date -u` 将输入解析为 UTC,然后**减去**该时区的 UTC 偏移秒数。

公式:`unix_ts = date_utc_parse(input) − (UTC_offset_hours × 3600)`

示例:2025-01-15 10:30:00 北京时间(UTC+8)

北京为 UTC+8,因此减去 8 × 3600 = 28800

Linux(GNU date)

FROM=$(( $(date -u -d "2025-01-15 10:30:00" +%s) - 28800 ))

macOS(BSD date)

FROM=$(( $(date -u -j -f "%Y-%m-%d %H:%M:%S" "2025-01-15 10:30:00" +%s) - 28800 ))

示例:2025-01-15 10:30:00 纽约时间(UTC-5)

纽约为 UTC-5,因此减去 -5 × 3600 = 减去 -18000 = 加 18000

Linux(GNU date)

FROM=$(( $(date -u -d "2025-01-15 10:30:00" +%s) + 18000 ))

macOS(BSD date)

FROM=$(( $(date -u -j -f "%Y-%m-%d %H:%M:%S" "2025-01-15 10:30:00" +%s) + 18000 ))


常见 UTC 偏移(要减去的值):

| 时区         | UTC 偏移小时 | 要减去的秒数 |
|------------------|------------------|---------------------|
| 北京(UTC+8)  | +8               | `28800`             |
| 东京(UTC+9)    | +9               | `32400`             |
| 伦敦(UTC)     | 0                | `0`                 |
| 纽约(UTC-5) | -5               | `-18000`            |

---

### 步骤 5:通过 `get-logs-v2` 执行

使用 `aliyun sls get-logs-v2` 执行查询。运行 `aliyun help sls get-logs-v2` 查看 CLI 参数用法;详细 API 参数说明请阅读 [references/related-apis.md](references/related-apis.md)。

**必需 CLI 标志:**

- `--project`:SLS 项目名
- `--logstore`:项目内的 Logstore 名
- `--from`:时间范围起点,**Unix 秒级时间戳**(含)
- `--to`:时间范围终点,**Unix 秒级时间戳**(不含)
- `--query`:步骤 3 构建的语句

分页方式取决于语句是否含 `|`:

#### 5.1 仅索引搜索 —— 用 `--offset` / `--line` 分页

aliyun sls get-logs-v2 \

--project my-project --logstore my-logstore \

--from 1740000000 --to 1740003600 \

--query '* and "payment failed" and status: "500"' \

--line 100 --offset 0 --reverse true


- 分页:`--line` 是页大小(`1–100`,必填);`--offset` 是起始行(可选,默认 `0`)。
- 排序:`--reverse true` 返回最新在前;默认 `false` 为最旧在前。

#### 5.2 含 SQL —— 用语句内 `LIMIT` 分页

aliyun sls get-logs-v2 \

--project my-project --logstore my-logstore \

--from 1740000000 --to 1740003600 \

--query 'status: "500" | SELECT request_uri, count(*) AS cnt FROM log GROUP BY request_uri ORDER BY cnt DESC LIMIT 20'


- SQL 默认结果上限为 **100 行**。要获取更多结果或分页:
  - `LIMIT count` —— 提高上限(例如 `LIMIT 500` 最多返回 500 行)
  - `LIMIT offset, count` —— 分页(例如 `LIMIT 20, 20` 为第 21–40 行;`LIMIT 40, 20` 为第 41–60 行)。offset+count 最大为 1000000。
  - **不要**使用 `LIMIT count OFFSET offset` 语法 —— **不支持**。始终使用 `LIMIT offset, count`。
- 排序:用 `ORDER BY <field> DESC/ASC` 排序。

**结果完整性检查:** 每个响应都包含 `meta.progress`。若为 `Incomplete`,**重新发起同一请求**直到返回 `Complete`。

---

### 步骤 6:从响应中提取数据

`get-logs-v2` 返回:

{

"meta": { "progress": "Complete", "count": 10, ... },

"data": [ { "field1": "value1", ... }, ... ]

}


| 字段 | 含义 |
|-------|---------|
| `meta.progress` | `Complete` 或 `Incomplete`(见步骤 5) |
| `meta.count` | 返回的行数 |
| `data` | 日志条目或聚合行数组;可能包含 `__time__`(Unix 秒,字符串) |

用 `jq`(首选)或 `--cli-query`(JMESPath)提取用户需要的字段:

| 提取 | `jq` | `--cli-query`(JMESPath) |
|---------|------|--------------------------|
| 数据行 | `\| jq '.data'` | `--cli-query 'data'` |
| 进度 | `\| jq '.meta.progress'` | `--cli-query 'meta.progress'` |
| 行数 | `\| jq '.meta.count'` | `--cli-query 'meta.count'` |
| 特定字段 | `\| jq '.data[] \| {LogStore, read_mb}'` | `--cli-query 'data[].{LogStore: LogStore, read_mb: read_mb}'` |

---

### 步骤 7:呈现 CLI 命令和结果

**CLI 命令** —— 始终展示完整、可直接复制粘贴的 `aliyun sls get-logs-v2 ...` 命令。脱敏任何 AK/SK。如果查询未执行(写入 / 解释场景),呈现用户应运行的命令。

**结果** —— 查询已执行时,用步骤 6 提取 `data` 并按用户要求格式化(表格、列表、摘要等)。附加一句说明查询模式选择理由。

---

全局规则

  • 原始日志检索始终优先索引搜索以获最快速度;分析或字段投影使用索引搜索 + SQL。
  • 当用户只需要特定字段时,用 SELECT 投影它们,而非获取全部原始日志 —— 这减少网络开销。需要目标字段 doc_value: true(在步骤 1 确认)。
  • 不要硬编码 __time__ 过滤 —— 通过 --from / --to 传时间范围。
  • 已废弃 API:绝不调用 get-logs;始终使用 get-logs-v2

故障排查

当用户报告"无数据"、"结果错误"或 CLI 错误时,严格按此顺序走查清单:

  1. 时间范围 —— --from/--to 错误?用了毫秒而非秒?最近的写入仍在索引中?
  2. 索引配置 —— 字段索引缺失?全文索引关闭?目标字段不在 keys 中?
  3. 字段类型 / 统计 —— 对 text 字段做范围查询?对无 doc_value 的字段做 SQL?
  4. 语法 —— SQL 与 SPL 混用?模糊匹配中的前导 *?SPL 字符串转义?
  5. 模式选择 —— 索引查询即可时却用扫描?在 SPL 中聚合而非 SQL?
  6. 完整性 —— meta.progress = Incomplete,调用方未重试(见步骤 5)。
  7. ProjectNotExist —— 地域或端点错误。用跨地域发现自动定位项目,或请用户确认地域。调用 get-project --cross-region true 前,必须先阅读 references/regions.md 中的跨地域发现章节 —— 该 API 仅通过 cn-zhangjiakou.log.aliyuncs.com 端点可用。
  8. 网络故障(超时、连接被拒绝)—— 尝试切换到内网端点。见 references/regions.md

完整故障模式和错误码目录,见 references/troubleshooting.mdreferences/related-apis.md 中的 Common Errors 表。

参考文档

文档说明
references/query-analysis.md模式决策、索引搜索 / SQL 规则、扫描语义
references/spl-guide.mdSPL 管道语法、常用命令、字段处理
references/functions-guide.md函数分类、SQL/SPL 差异、模板
references/troubleshooting.md"无数据 / 结果错误 / 报错"手册
references/related-apis.mdGetLogsV2GetIndex API 与 CLI 参考
references/ram-policies.md最小及完整 RAM 策略
references/cli-installation-guide.mdAliyun CLI 安装、鉴权模式、profile
references/regions.md地域 / 端点配置、内网端点、跨地域发现(get-project --cross-region true仅 cn-zhangjiakou
references/acceptance-criteria.mdCLI 调用验收测试
references/query_analysis/*.yaml · references/spl/*.yaml · references/functions/*.yaml本 Skill 捆绑的权威 YAML