# ELK 索引目录（schema reference）

> 每张索引一节：**集群 / 账号 / 关键字段 / JSON 字符串字段的内部结构**。纯 schema 参考。
>
> 业务侧"为什么这么查 / 怎么排查问题"在 [`business/`](business/) 目录：
>
> - [`business/keyword-free.md`](business/keyword-free.md) — 免唤醒判决（拒识 / kwfree 两张表的视角差异）
> - [`business/intent-arbitrator.md`](business/intent-arbitrator.md) — 中控仲裁
> - [`business/micar-onetrack.md`](business/micar-onetrack.md) — 小米汽车 OneTrack 端侧埋点（端到端可用性 / 全离线日志 / 离线NLP结果）

## 集群 & 账号

⚠️ **不止一个 ES 集群**。每个 profile 自带 `host` 字段指向所在集群。账号密码（团队共用）已 commit 在仓库的 `profiles.json` 里，clone 即可用。

| Profile Key | ES 集群 | 账号 | 对应 Kibana 前端 |
| ----------- | ------ | --- | ---------------- |
| `default` | `akaiservice.api.es.srv:80` | `ai_service_kibana` | `aiservice.ak.kibana.cloud.mioffice.cn` / `akelk.pt.ai.srv` |
| `reject` | `akaiservice.api.es.srv:80` | `ai_service_kibana` | `akaiservice.kibana.pt.xiaomi.com` |
| `micar` | `c3log.api.es.srv:80` | `xiaoai_micar_kibana` | `c3log.kibana.pt.xiaomi.com` |

`default` / `reject` 共用一个集群和账号；`micar` 是**完全独立的 c3log 集群**，跨集群账号互相不通（403）。

## 索引清单

| preset | 索引 pattern | profile | request id 字段 | 时间字段 | 内置过滤 | 主要业务 |
| ------ | ----------- | ------- | -------------- | ------- | ------- | -------- |
| `main` | `arch-flat-nlp-log-f-*` | default | `request_id` | `timestamp` | — | 主 NLP 日志 / 中控仲裁 |
| `reject` | `aiservice_duplex_rejection_lcs_log*` | reject | `requestId` | `time` | — | 后置拒识 |
| `kwfree` | `nlp_post_processing_lcs-*` | default | `requestId` | `timestamp` | `moduleName=keyword-free-log` | 后处理免唤醒 |
| `micar` | `onetrack_xiaoai_micar*` | micar | `request_id` | `timestamp` | — | 小米汽车 OneTrack 端侧埋点 |

⚠️ **字段命名各表不统一**：snake (`request_id`) vs camel (`requestId`)；时间字段 `timestamp` vs `time`。Kibana 显示的字段名不一定等于 ES 字段名。

---

## `arch-flat-nlp-log-f-*`（preset=`main`）

主 NLP 服务端日志，每次请求一条。

**顶层字段**（节选）：
`request_id`, `query`, `query_origin`, `domain`, `func`, `intention`, `code`, `latency`,
`user_agent`, `session_id`, `app_id`, `app_name`, `device_id`, `mask_did`,
`arbitrator_dialog_status`, `offline_arbitrate_domains`,
`is_llm`, `is_llm_classify_enable`, `is_llm_classify_success`,
`large_model_info`, `large_model_traceid`,
`llm_intent`, `llm_intent_model_name`, `llm_intent_model_version`, `llm_content`, `llm_knowledge`, `llm_system_prompt`, `llm_history_size`, `llm_reject_intent`, `llm_access_control`, `llm_description`,
`is_continuous_dialog`, `exit_continuous_dialog`, `is_multi_turn`, `is_multi_rewrite`, `multi_rewrite_method`,
`reject_type`, `rejection_hint`, `rejection_info`, `is_shumei_reject`, `is_filtered`, `is_user_cancelled`,
`requestInfo`, `responseInfo`, `text`, `display_text`, `to_read`, `to_speak`, `tts_speaker`, `tts_vendor`,
`car_type`, `car_config`, `car_category`, `vehicle_driving_status`, `vehicle_wakeup_zone`, `is_real_vehicle`, `is_bench_vehicle`, `is_internal`

**关键嵌套对象**：

- `intention` (dict) — 意图判决总集，含：
  - `intention.intent_arbitrator_info` ⭐ — **中控仲裁对象**（顶层同名字段通常 null，**真东西在这里**），子结构详见 [`business/intent-arbitrator.md`](business/intent-arbitrator.md)
  - `intention.score` / `intention.func` / `intention.domain` / `intention.query`
  - `intention.dialog_status`, `intention.rewrite_infos`, `intention.domain_judge`, `intention.provider_domains`

---

## `aiservice_duplex_rejection_lcs_log*`（preset=`reject`）

后置拒识模块日志。**同一 requestId 通常多条（多轮）**，按 `time` 倒序取最新。

**顶层字段**：
`requestId`, `time`, `query`, `appId`, `deviceId`, `sessionId`, `env`,
`isDuplex`, `isExit`, `isWakeup`, `costInfo`, `exitInfo`, `instructionPriority`,
`rejectHint`, `rejectInfo`, `rejectType`, `requestInfo`, `strategy_info`

**JSON 字符串字段**（脚本自动深度解析）：
- `rejectInfo` — 完整拒识判决，关键路径：
  - `rejectInfo.reject_reason` / `rejectInfo.rejection_info` / `rejectInfo.debug_info`
  - `rejectInfo.strategy_info.reject.<策略名>` — 各子策略
  - 常用子策略 `KEY_WORD_FREE_RESTRIC`（免唤醒）：`process` / `skipped_reason` / `keywordFreeType` / `isCodeMatch` / `getProcessedQuery` / `Function List` —— 业务深入见 [`business/keyword-free.md`](business/keyword-free.md)

---

## `nlp_post_processing_lcs-*`（preset=`kwfree`）

后处理通用日志表。`kwfree` preset 内置 `moduleName=keyword-free-log` 过滤，锁定到免唤醒模块那条。

**顶层字段**：
`requestId`, `timestamp`, `moduleName`, `appId`, `env`, `machine`, `maskUid`, `message`

**JSON 字符串字段**（脚本自动深度解析）：

- `message` — 免唤醒模块本次处理的入参出参，关键路径：
  - `message.process` / `message.skipReason`
  - `message.route.flow` / `route.enableFullMigration` / `route.clawEnabled`
  - `message.request.query` / `keywordFreeType` / `zone` / `appId` / `maskUid` / `maskDeviceId`
  - `message.fallback.oldRejectType` / `fallback.oldDomain`
  - 业务深入见 [`business/keyword-free.md`](business/keyword-free.md)

---

## `onetrack_xiaoai_micar*`（preset=`micar`）

小米汽车小爱端侧 OneTrack 埋点。**c3log 独立集群**。按日 rolling，单日 ~300GB——**强烈建议 `--date YYYYMMDD`**。

⚠️ **同一 request_id 多条记录**，按 `tip` 区分业务点位。**不同 tip 的负载 schema 不统一**。

**顶层公共字段**：
`request_id`, `tip`, `tip_id`, `tip_name`, `tip_module_name`, `tip_page_id`, `tip_pos`,
`event_name` (`execute` / `state` / `start`),
`device_id`, `vid`, `instance_id`, `app_id`, `app_package_name`, `pkg`,
`path_id`, `clientTime`, `serverTime`, `timestamp`,
`network`, `region`, `mfrs`, `model`, `car_type`, `car_config`,
`voice_position` (`driver` / `passenger`), `wakeup_origin`,
`srv_env`, `app_ver`, `micar_ver`, `os_ver`,
`is_internal`, `is_bench_vehicle`, `sender`, `distinct_id`, `plugin_id`

**主要 tip 与负载位置**：

| tip | tip_name | 负载在 |
| --- | -------- | ------ |
| `1024.1.1.1.23177` | 小爱端到端可用性 | 顶层 `key_value`（性能时序） |
| `1024.1.2.1.23176` | 小爱全离线日志 | 顶层 `request_infos[]` / `response_infos[]` / `other_infos`（**不在 `key_value`**） |
| `1024.1.2.1.34496` | 离线NLP结果 | `key_value.instructions` |
| `1024.4.1.1.25631` | ASR识别状态 | `key_value` 为 null，看 `event_name` / `other_infos` |
| `1024.1.1.1.33610` | 第三方接口调用 | — |
| `1024.1.3.1.23520` / `23521` | 小爱指令开始 / 结束 | — |

**JSON 字符串字段**（脚本自动深度解析）：

- `key_value`（大多数 tip）
- `request_infos[]` / `response_infos[]` / `other_infos[]`（23176）

各 tip 字段语义、模型相关字段（`nlp_debug_info` / `Arbitrate` / `nlp_model_version` 等）业务深入见 [`business/micar-onetrack.md`](business/micar-onetrack.md)。

---

## 新增索引流程

1. 从 Kibana URL 拿：Kibana index UUID、KQL 字段、filter 里的 `match_phrase` 条件
2. 必要时跑临时 `_probe_*.py`（命名已 gitignore）：用 `match_phrase` 条件 + `*` 索引跨库搜，从命中文档的 `_index` 反推真实索引名
3. 确认 **request id 字段名**（`request_id` / `requestId`）和**时间字段**（`timestamp` / `time`）
4. 如 `AuthorizationException(403)`，换 profile
5. 字段为 JSON 字符串时（如 `rejectInfo` / `message` / `key_value`）脚本已自动深度解析，把业务路径记到本文档对应索引一节
6. 在 `elk_query.py` 的 `PRESETS` 加一条，`extra_filters` 写清楚（如 `moduleName=...`）
7. 如果是新业务主题，在 `business/` 下加一份业务深入文档
