# 指标简单搜索（simple_metric_search）使用说明

本文档介绍 `simple_metric_search` 的参数化指标查询能力。该功能会根据传入参数自动组装符合规范的 `mstats` SPL 并执行查询，避免手写指标查询语句。

## 功能概述

- 目标：通过参数（指标名称、聚合方式、时间参数、分组、过滤、排序、限制）生成规范 `mstats` 查询并执行。
- 引擎：指标查询统一使用 `mstats`。
- 语法约束：严格遵循 `metric_search_syntax.md` 的规则（时间参数紧跟 `mstats`，字段名单引号、值双引号，`sort by`，`where` 中 `in` 用多个条件 `OR` 连接等）。

## 参数说明

- `metrics`（必填，列表）：聚合表达式集合
  - 单项结构：
    - `name`：指标名称，如 `cpu_usage_idle`
    - `func`：聚合函数，如 `avg | sum | min | max | distinct | percentile | hperc | sumRate`
    - `alias`：结果别名，生成 `as '别名'`
    - `args`：函数额外参数（如 `percentile` 的百分位）
- `start`/`end`（可选）：时间参数，必须紧跟在 `mstats` 后，例如 `start="-1h"`、`end="@h"`。start以及end不支持now()函数。
- `span`（可选）：时间粒度，如 `1m`、`5m`。
- `timeshift`（可选）：时间偏移，如 `-1h`。
- `group_by`（可选）：分组标签列表，生成 `by 'tag1', 'tag2'`。
- `filters`（可选）：标签过滤，生成 `| where (...)`；支持 `=, !=, like, in, not in`（其中 `in/not in` 会展开为多个条件通过 `OR` 连接）。like 仅支持通配符 `%`，不支持`*`。
- `logic`（可选）：`AND | OR`，用于连接多个过滤条件，默认 `AND`。
- `sort_field`/`sort_order`（可选）：排序字段与顺序（`asc|desc`），生成 `| sort by '字段' 顺序`。
- `limit`（可选）：数量限制，生成 `| limit N`；同时限制返回行数。
- `format_type`（可选）：`text | csv | json`，默认 `csv`。
- `output_file`（可选）：写入文件路径；提供则把结果写入该文件。

## 组装规则要点

- 查询主段：`mstats start="..." end="..." span="..." timeshift="..." <聚合表达式> by '<tag>'`。
- 字段/值引号：标签名与别名用单引号（`'host'`、`'p95'`），值用双引号（`"keta-web"`）；数字值不加引号；含双引号的值使用三双引号。
- 过滤段：`| where (cond1 AND/OR cond2)`；
  - `in/not in` 展开为多个相等条件以 `OR` 连接：`('host'="h1" OR 'host'="h2")`。
  - `like` 写法：`like('field', "pattern")`。
- 排序与限制：`| sort by '<field>' asc|desc | limit N`。
- 校验：使用 `validate_mstats_syntax` 保证不与 `search2` 混用、时间参数位置正确、函数带括号。

## 示例

### 1) 平均值按主机分组并排序

```
metrics = [{"name":"cpu_usage_idle","func":"avg","alias":"_value"}]
start = "-2h"
span = "1m"
group_by = ["host"]
sort_field = "_value"
sort_order = "desc"
limit = 5
format_type = "text"
```

生成 SPL：

```
mstats start="-2h" span="1m" avg('cpu_usage_idle') as '_value' by 'host' | sort by '_value' desc | limit 5
```

### 2) 百分位 P95

```
metrics = [{"name":"avgHandlingTimeInMilli","func":"percentile","args":[95],"alias":"p95"}]
start = "-1h"
group_by = ["host"]
limit = 5
format_type = "csv"
```

生成 SPL：

```
mstats start="-1h" percentile('avgHandlingTimeInMilli', 95) as 'p95' by 'host' | limit 5
```

### 3) 标签过滤（OR 组合）

```
metrics = [{"name":"cpu_usage_idle","func":"avg","alias":"_value"}]
start = "-1h"
group_by = ["host"]
filters = [{"field":"host","op":"in","values":["keta-web-10-0-1-225","keta-web-10-0-1-154"]}]
logic = "OR"
sort_field = "_value"
limit = 5
format_type = "text"
```

生成 SPL：

```
mstats start="-1h" avg('cpu_usage_idle') as '_value' by 'host' | where ('host'="keta-web-10-0-1-225" OR 'host'="keta-web-10-0-1-154") | sort by '_value' desc | limit 5
```

## 返回与错误处理

- 返回格式：按 `format_type` 输出（`text|csv|json`）。
- 文件输出：提供 `output_file` 时写入文件并返回已写入提示。
- 空结果：返回友好建议（调整 `start/end/span`；检查分组字段是否为标签；放宽过滤条件）。
- 语法校验：当时间参数位置、函数括号、排序写法等不合规时返回明确的修复建议，规则见 `metric_search_syntax.md`。

## 使用建议

1. 先用较短时间窗口与较小 `span` 验证指标与分组，再扩展范围。
2. 为累计计数型指标使用 `sumRate` 或 `rollup("rate")` 进行变化率分析；直方图百分位 `hperc` 需满足桶数据与 `le=+Inf`。
3. 使用 `group_by` 时确保分组字段为标签（字符串类型），不要使用数值型指标字段。

## 其它说明
### 1) 时间参数（start/end）
- 相对时间示例：
  - `start="-1h"`（近 1 小时）
  - `start="-d@d" end="@d"`（昨天整天，不包含今天）
  - `start="-3d"`（近 3 天）
  - `start="-M@M" end="@M"`（上个月）
- 对齐符号：`@s @m @h @d @w @M @y`。
- 时间参数不支持now()函数。