From 337e26858bce52b92b7f14c3bff43d6ea9b06a1a Mon Sep 17 00:00:00 2001 From: "yongjiang.lin" Date: Thu, 11 Jun 2026 14:46:29 +0800 Subject: [PATCH] init: 4 skills (bms-test-log-query, bms-prd-log-query, bms-mysql-test, bms-mysql-prd) --- .gitignore | 1 + README.txt | 40 +++++ bms-mysql-prd/SKILL.md | 62 ++++++++ bms-mysql-prd/scripts/bms-mysql-prd.py | 193 +++++++++++++++++++++++++ bms-mysql-test/SKILL.md | 74 ++++++++++ bms-mysql-test/scripts/bms-mysql.py | 171 ++++++++++++++++++++++ bms-prd-log-query/SKILL.md | 123 ++++++++++++++++ bms-test-log-query/SKILL.md | 111 ++++++++++++++ 8 files changed, 775 insertions(+) create mode 100644 .gitignore create mode 100644 README.txt create mode 100644 bms-mysql-prd/SKILL.md create mode 100644 bms-mysql-prd/scripts/bms-mysql-prd.py create mode 100644 bms-mysql-test/SKILL.md create mode 100644 bms-mysql-test/scripts/bms-mysql.py create mode 100644 bms-prd-log-query/SKILL.md create mode 100644 bms-test-log-query/SKILL.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..4859de3 --- /dev/null +++ b/README.txt @@ -0,0 +1,40 @@ +# Personal Agent Skills Incubator + +本项目是个人 AI Agent 技能的孵化器。 + +## 技能用途 + +编写的技能不绑定特定项目业务逻辑,而是通用能力,可移植到多种 AI Agent 平台: + +- **Claude Code** — 放在 `~/.claude/skills//SKILL.md` +- **Cursor** — 放在 `.cursor/skills//SKILL.md` +- **OpenClaw / Workbuddy / Codex** — 遵循各自技能目录规范 + +## 移植方式 + +将技能文件夹从本项目复制到目标 Agent 的技能目录下即可,**不需要删除本项目中的技能**。 +本项目是技能的"母版库",每次移植都是借鉴复制到目标环境,源文件保留不动。 + +## 技能列表 + +### 日志查询类 + +| 技能名 | 说明 | 环境变量 | +|--------|------|----------| +| `bms-test-log-query` | 查询 BMS 测试 (bms-sit) 应用日志,通过 Kibana (`http://172.17.12.18:8000`) 代理访问 ES,索引 `bms-test-*`,日均 200 万条 | `BMS_LOG_*` | +| `bms-prd-log-query` | 查询 BMS 生产 (bms-prod) 日志,通过 Kibana (`https://kiblog.qx.com`) 代理访问 ES,索引 `bmslog-bms-prod-*`,日均 1000 万条 | `BMS_PRD_LOG_*` | + +### 数据库查询类 + +| 技能名 | 说明 | +|--------|------| +| `bms-mysql-test` | 连接 BMS 测试 MySQL 数据库,支持 SELECT 直接执行,INSERT/UPDATE/DELETE/DDL 需 Windows 弹窗确认 | +| `bms-mysql-prd` | 连接 BMS 生产 MySQL 数据库,只读模式,禁止任何写操作/DDL | + +## 新增技能规范 + +1. **在当前项目根目录下创建**:`/SKILL.md`(直接在项目根目录建文件夹) +2. 编写 `SKILL.md`,包含连接信息、查询模板、使用规则 +3. 凭据统一存放在 `~/.env` 中,不在技能文件里写密码 +4. 环境变量加技能名前缀(如 `BMS_LOG_*`),避免冲突 +5. 完成后同步复制到 `~/.claude/skills/` 使全局生效 diff --git a/bms-mysql-prd/SKILL.md b/bms-mysql-prd/SKILL.md new file mode 100644 index 0000000..79df05c --- /dev/null +++ b/bms-mysql-prd/SKILL.md @@ -0,0 +1,62 @@ +--- +name: bms-mysql-prd +description: Connect to BMS production MySQL database. Use when the user asks to query BMS production database, check production data, or says "查询生产数据库", "查生产数据", "BMS生产库", "BMS正式库". Production database is read-only — any write/DDL will fail. +--- + +# BMS MySQL 生产数据库连接 Skill + +Connect to the BMS production MySQL database for read-only queries. + +## Available Databases + +| Database | Description | +| ----------------------- | -------------------- | +| `bms_base_center` | 基础数据中心 | +| `bms_buyinvoice_center` | 采购发票中心 | +| `bms_ext_center` | 外部扩展中心 | +| `bms_invoice_center` | 发票中心 | +| `bms_order_center` | 订单中心 | +| `bms_payable_center` | 应付中心 | +| `bms_task_center` | 任务中心 | +| `cache_db` | 缓存数据库 | +| `leshop_v3` | 乐商 V3 | +| `lts` | LTS | +| `manager_db` | 管理数据库 | +| `mq_db` | 消息队列数据库 | +| `sap_push_data` | SAP 推送数据 | +| `sf_db` | SF 数据库 | +| `mysql` | 系统数据库 | +| `information_schema` | 系统信息库 | + +## How to Use + +Run the helper script with a SQL query: + +```bash +python scripts/bms-mysql-prd.py --query "SELECT * FROM bms_base_center.enterprise_info LIMIT 10" +``` + +## Safety Rules + +- **Production is read-only** — the database account only has SELECT permission +- Any `INSERT`/`UPDATE`/`DELETE`/DDL will be rejected by the database +- Write/DDL operations still require a confirmation popup before attempting +- Results are printed in a formatted table + +## Script Location + +- `scripts/bms-mysql-prd.py` — the execution script (uses PyMySQL) + +## Examples + +```bash +# Query enterprise info +python scripts/bms-mysql-prd.py --query "SELECT * FROM bms_base_center.enterprise_info WHERE company_code = '7600'" + +# List tables in a database +python scripts/bms-mysql-prd.py --query "SHOW TABLES FROM bms_order_center" +``` + +## Output Format + +Results are printed as a formatted table with column headers and aligned values. Empty results show "0 rows returned." Write operations (if attempted) will fail with a permission error. diff --git a/bms-mysql-prd/scripts/bms-mysql-prd.py b/bms-mysql-prd/scripts/bms-mysql-prd.py new file mode 100644 index 0000000..3e2b953 --- /dev/null +++ b/bms-mysql-prd/scripts/bms-mysql-prd.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +BMS MySQL Production Database Query Tool + +Read-only access to the BMS production MySQL database. +- SELECT/SHOW/DESC/EXPLAIN: execute directly +- INSERT/UPDATE/DELETE/DDL: require confirmation popup (will fail with permission error) +""" + +import argparse +import re +import sys + +import pymysql + + +# ─── Connection Config ─────────────────────────────────────────────────────── + +DB_CONFIG = { + "host": "47.106.125.251", + "port": 9696, + "user": "i7bSEtwU", + "password": "", + "charset": "utf8mb4", + "cursorclass": pymysql.cursors.DictCursor, +} + +# ─── Query Classification ──────────────────────────────────────────────────── + +READ_ONLY_PATTERNS = re.compile( + r"^\s*(SELECT|SHOW|DESC|DESCRIBE|EXPLAIN|USE|SET)\b", re.IGNORECASE +) + +WRITE_DDL_PATTERNS = re.compile( + r"^\s*(INSERT|UPDATE|DELETE|REPLACE|CREATE|ALTER|DROP|TRUNCATE|RENAME|GRANT|REVOKE|LOAD\s+DATA)\b", + re.IGNORECASE, +) + + +def is_read_only(sql: str) -> bool: + """Return True if the SQL is a read-only query.""" + return bool(READ_ONLY_PATTERNS.match(sql)) + + +def is_write_or_ddl(sql: str) -> bool: + """Return True if the SQL modifies data or schema.""" + return bool(WRITE_DDL_PATTERNS.match(sql)) + + +# ─── Confirmation Dialog ───────────────────────────────────────────────────── + +def ask_confirmation(sql: str) -> bool: + """Show a Windows popup dialog asking the user to confirm the SQL execution. + + Returns True if the user clicks 'Yes', False otherwise. + """ + import tkinter as tk + from tkinter import messagebox + + root = tk.Tk() + root.withdraw() # Hide the main window + + title = "BMS MySQL 生产 - 写操作确认" + message = ( + "即将执行以下写操作 / DDL 语句(生产库只读,该操作将报错),是否继续?\n\n" + f"SQL:\n{sql}\n" + ) + + result = messagebox.askyesno(title, message, icon="warning") + root.destroy() + return result + + +def show_error_popup(sql: str, error: str) -> None: + """Show a Windows popup dialog when a write operation is rejected.""" + import tkinter as tk + from tkinter import messagebox + + root = tk.Tk() + root.withdraw() + + title = "BMS MySQL 生产 - 操作被拒绝" + message = ( + "生产库为只读权限,以下写操作已被数据库拒绝:\n\n" + f"SQL:\n{sql}\n\n" + f"错误信息:\n{error}" + ) + + messagebox.showwarning(title, message) + root.destroy() + + +# ─── Table Formatting ──────────────────────────────────────────────────────── + +def format_table(rows: list, columns: list) -> str: + """Format query results as an aligned text table.""" + if not rows: + return "0 rows returned." + + # Calculate column widths + widths = {col: len(str(col)) for col in columns} + for row in rows: + for col in columns: + val = str(row.get(col, "")) + widths[col] = max(widths[col], len(val)) + + # Build header + header = " | ".join(str(col).ljust(widths[col]) for col in columns) + separator = "-+-".join("-" * widths[col] for col in columns) + + # Build rows + lines = [header, separator] + for row in rows: + line = " | ".join( + str(row.get(col, "")).ljust(widths[col]) for col in columns + ) + lines.append(line) + + lines.append(f"\n{len(rows)} row(s) returned.") + return "\n".join(lines) + + +# ─── Main Execution ────────────────────────────────────────────────────────── + +def execute_query(sql: str) -> None: + """Connect to the database and execute the given SQL query.""" + + print(f"\n{'='*60}") + print(f"BMS MySQL Production (47.106.125.251:9696)") + print(f"{'='*60}") + print(f"SQL: {sql}\n") + + # Classify the query + if is_read_only(sql): + query_type = "READ-ONLY" + elif is_write_or_ddl(sql): + query_type = "WRITE / DDL (只读库,将报错)" + else: + query_type = "UNKNOWN" + + print(f"类型: {query_type}\n") + + # For write/DDL, require confirmation + if is_write_or_ddl(sql): + if not ask_confirmation(sql): + print("用户已取消操作。") + sys.exit(0) + + # Connect and execute + try: + conn = pymysql.connect(**DB_CONFIG) + cursor = conn.cursor() + cursor.execute(sql) + + if is_read_only(sql): + rows = cursor.fetchall() + columns = [desc[0] for desc in cursor.description] if cursor.description else [] + print(format_table(rows, columns)) + else: + conn.commit() + affected = cursor.rowcount + print(f"操作成功,影响 {affected} 行。") + + cursor.close() + conn.close() + + except pymysql.MySQLError as e: + error_msg = str(e) + print(f"数据库错误: {error_msg}", file=sys.stderr) + if is_write_or_ddl(sql): + show_error_popup(sql, error_msg) + sys.exit(1) + except Exception as e: + print(f"执行失败: {e}", file=sys.stderr) + sys.exit(1) + + +def main(): + parser = argparse.ArgumentParser( + description="BMS MySQL 生产数据库查询工具(只读)" + ) + parser.add_argument( + "--query", "-q", + required=True, + help="要执行的 SQL 语句", + ) + args = parser.parse_args() + execute_query(args.query) + + +if __name__ == "__main__": + main() diff --git a/bms-mysql-test/SKILL.md b/bms-mysql-test/SKILL.md new file mode 100644 index 0000000..aee11d1 --- /dev/null +++ b/bms-mysql-test/SKILL.md @@ -0,0 +1,74 @@ +--- +name: bms-mysql-test +description: Connect to BMS test MySQL database. Use when the user asks to query BMS database, execute SQL against BMS, check BMS data, or says "查询BMS数据库", "执行SQL", "连接BMS MySQL", "BMS数据库". This skill handles safe SQL execution — SELECT runs directly, but INSERT/UPDATE/DELETE/DDL require Windows popup confirmation before executing. +--- + +# BMS MySQL 数据库连接 Skill + +Connect to the BMS test environment MySQL database and execute SQL queries safely. + +## Available Databases + +| Database | Description | +| ----------------------- | -------------------- | +| `bms_base_center` | 基础数据中心 | +| `bms_buyinvoice_center` | 采购发票中心 | +| `bms_ext_center` | 外部扩展中心 | +| `bms_invoice_center` | 发票中心 | +| `bms_order_center` | 订单中心 | +| `bms_payable_center` | 应付中心 | +| `bms_task_center` | 任务中心 | +| `cache_db` | 缓存数据库 | +| `leshop_v3` | 乐商 V3 | +| `lts` | LTS | +| `manager_db` | 管理数据库 | +| `mq_db` | 消息队列数据库 | +| `sap_push_data` | SAP 推送数据 | +| `sf_db` | SF 数据库 | +| `mysql` | 系统数据库 | +| `information_schema` | 系统信息库 | + +## How to Use + +Run the helper script with a SQL query: + +```bash +python scripts/bms-mysql.py --query "SELECT * FROM your_table LIMIT 10" +``` + +## Safety Rules + +### Read-only queries — execute directly +- `SELECT`, `SHOW`, `DESC`, `DESCRIBE`, `EXPLAIN` — run without confirmation +- Results are printed in a formatted table + +### Write / DDL operations — require confirmation +- `INSERT`, `UPDATE`, `DELETE`, `REPLACE` +- `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `RENAME` +- `GRANT`, `REVOKE` +- A Windows popup dialog displays the full SQL and asks for Yes/No confirmation +- Only executes if user clicks **是 (Yes)** + +## Script Location + +- `scripts/bms-mysql.py` — the execution script (uses PyMySQL) + +## Examples + +```bash +# Query user table (no confirmation needed) +python scripts/bms-mysql.py --query "SELECT id, name FROM users WHERE status = 1 LIMIT 20" + +# Show tables (no confirmation needed) +python scripts/bms-mysql.py --query "SHOW TABLES" + +# Delete a record (requires confirmation popup) +python scripts/bms-mysql.py --query "DELETE FROM logs WHERE created_at < '2025-01-01'" + +# Alter table (requires confirmation popup) +python scripts/bms-mysql.py --query "ALTER TABLE users ADD COLUMN phone VARCHAR(20)" +``` + +## Output Format + +Results are printed as a formatted table with column headers and aligned values. Empty results show "0 rows returned." Write operations show the number of affected rows. diff --git a/bms-mysql-test/scripts/bms-mysql.py b/bms-mysql-test/scripts/bms-mysql.py new file mode 100644 index 0000000..cc692b0 --- /dev/null +++ b/bms-mysql-test/scripts/bms-mysql.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +BMS MySQL Database Query Tool + +Executes SQL queries against the BMS test environment MySQL database. +- SELECT/SHOW/DESC/EXPLAIN: execute directly +- INSERT/UPDATE/DELETE/DDL: require Windows popup confirmation before executing +""" + +import argparse +import re +import sys + +import pymysql + + +# ─── Connection Config ─────────────────────────────────────────────────────── + +DB_CONFIG = { + "host": "47.106.125.251", + "port": 9696, + "user": "X7OTnSMa", + "password": "", + "charset": "utf8mb4", + "cursorclass": pymysql.cursors.DictCursor, +} + +# ─── Query Classification ──────────────────────────────────────────────────── + +READ_ONLY_PATTERNS = re.compile( + r"^\s*(SELECT|SHOW|DESC|DESCRIBE|EXPLAIN|USE|SET)\b", re.IGNORECASE +) + +WRITE_DDL_PATTERNS = re.compile( + r"^\s*(INSERT|UPDATE|DELETE|REPLACE|CREATE|ALTER|DROP|TRUNCATE|RENAME|GRANT|REVOKE|LOAD\s+DATA)\b", + re.IGNORECASE, +) + + +def is_read_only(sql: str) -> bool: + """Return True if the SQL is a read-only query.""" + return bool(READ_ONLY_PATTERNS.match(sql)) + + +def is_write_or_ddl(sql: str) -> bool: + """Return True if the SQL modifies data or schema.""" + return bool(WRITE_DDL_PATTERNS.match(sql)) + + +# ─── Confirmation Dialog ───────────────────────────────────────────────────── + +def ask_confirmation(sql: str) -> bool: + """Show a Windows popup dialog asking the user to confirm the SQL execution. + + Returns True if the user clicks 'Yes', False otherwise. + """ + import tkinter as tk + from tkinter import messagebox + + root = tk.Tk() + root.withdraw() # Hide the main window + + title = "BMS MySQL - 写操作确认" + message = ( + "即将执行以下写操作 / DDL 语句,是否继续?\n\n" + f"SQL:\n{sql}\n" + ) + + result = messagebox.askyesno(title, message, icon="warning") + root.destroy() + return result + + +# ─── Table Formatting ──────────────────────────────────────────────────────── + +def format_table(rows: list, columns: list) -> str: + """Format query results as an aligned text table.""" + if not rows: + return "0 rows returned." + + # Calculate column widths + widths = {col: len(str(col)) for col in columns} + for row in rows: + for col in columns: + val = str(row.get(col, "")) + widths[col] = max(widths[col], len(val)) + + # Build header + header = " | ".join(str(col).ljust(widths[col]) for col in columns) + separator = "-+-".join("-" * widths[col] for col in columns) + + # Build rows + lines = [header, separator] + for row in rows: + line = " | ".join( + str(row.get(col, "")).ljust(widths[col]) for col in columns + ) + lines.append(line) + + lines.append(f"\n{len(rows)} row(s) returned.") + return "\n".join(lines) + + +# ─── Main Execution ────────────────────────────────────────────────────────── + +def execute_query(sql: str) -> None: + """Connect to the database and execute the given SQL query.""" + + print(f"\n{'='*60}") + print(f"BMS MySQL (47.106.125.251:9696)") + print(f"{'='*60}") + print(f"SQL: {sql}\n") + + # Classify the query + if is_read_only(sql): + query_type = "READ-ONLY" + elif is_write_or_ddl(sql): + query_type = "WRITE / DDL" + else: + query_type = "UNKNOWN" + + print(f"类型: {query_type}\n") + + # For write/DDL, require confirmation + if is_write_or_ddl(sql): + if not ask_confirmation(sql): + print("用户已取消操作。") + sys.exit(0) + + # Connect and execute + try: + conn = pymysql.connect(**DB_CONFIG) + cursor = conn.cursor() + cursor.execute(sql) + + if is_read_only(sql): + rows = cursor.fetchall() + columns = [desc[0] for desc in cursor.description] if cursor.description else [] + print(format_table(rows, columns)) + else: + conn.commit() + affected = cursor.rowcount + print(f"操作成功,影响 {affected} 行。") + + cursor.close() + conn.close() + + except pymysql.MySQLError as e: + print(f"数据库错误: {e}", file=sys.stderr) + sys.exit(1) + except Exception as e: + print(f"执行失败: {e}", file=sys.stderr) + sys.exit(1) + + +def main(): + parser = argparse.ArgumentParser( + description="BMS MySQL 数据库查询工具" + ) + parser.add_argument( + "--query", "-q", + required=True, + help="要执行的 SQL 语句", + ) + args = parser.parse_args() + execute_query(args.query) + + +if __name__ == "__main__": + main() diff --git a/bms-prd-log-query/SKILL.md b/bms-prd-log-query/SKILL.md new file mode 100644 index 0000000..23bca0b --- /dev/null +++ b/bms-prd-log-query/SKILL.md @@ -0,0 +1,123 @@ +--- +name: bms-prd-log-query +description: > + Query BMS production (bms-prod) logs from Elasticsearch via Kibana console proxy. + Use when the user asks to check BMS production logs, search prod errors, or look up bms-prod data. + All queries go through Kibana at https://kiblog.qx.com — ES direct port is NOT accessible. +metadata: + author: local + version: 1.0.0 +--- + +# BMS Production Log Query Skill + +> **Scope: ONLY `bms-prod` data view → `*bms*,*wos*` indices.** + +## Connection Details (DO NOT re-verify — confirmed working) + +- **Auth**: Read from `~/.env` (home directory): + - `BMS_PRD_LOG_URL` = Kibana proxy URL + - `BMS_PRD_LOG_USERNAME` = elastic + - `BMS_PRD_LOG_PASSWORD` = (stored in .env) +- **ES Version**: 8.6.1 +- **ES direct port**: NOT accessible. All queries go through Kibana console proxy. + +## Data View Mapping + +| Kibana Data View | ES Index Pattern | +|-----------------|------------------| +| `bms-prod` | `*bms*,*wos*` | + +## Kibana Console Proxy Format + +``` +POST https://kiblog.qx.com/api/console/proxy?path=&method=GET +``` + +Headers: `kbn-xsrf: true`, `Content-Type: application/json` + +## Index Pattern + +- `bmslog-bms-prod-YYYY-MM-DD` — daily rolling indices, ~10,000,000 docs/day (weekday), ~7,000,000 (weekend) + +## Log Fields + +| Field | Description | +|-------|-------------| +| `@timestamp` | ISO 8601 timestamp | +| `timestamp` | Original timestamp string | +| `message` | Log message (Chinese/English) | +| `level` | Log level: INFO, WARN, ERROR, etc. | +| `app_name` | Application name (e.g. `bms-web`) | +| `class` | Java class name | +| `thread` | Thread name | +| `traceId` | Distributed trace ID | +| `host_ip` | Host IP address | +| `log_origin` | Log origin identifier | +| `stack_trace` | Exception stack trace (empty if no error) | + +## Query Patterns + +### Latest N logs +```json +POST /api/console/proxy?path=/bmslog-bms-prod-/_search&method=GET +{ + "sort": [{"@timestamp": "desc"}], + "size": 10 +} +``` + +### Search by keyword +```json +POST /api/console/proxy?path=/bmslog-bms-prod-/_search&method=GET +{ + "query": { + "multi_match": { + "query": "", + "fields": ["message", "stack_trace"] + } + }, + "sort": [{"@timestamp": "desc"}], + "size": 20 +} +``` + +### Search errors +```json +POST /api/console/proxy?path=/bmslog-bms-prod-/_search&method=GET +{ + "query": { + "bool": { + "must": [ + { "match": { "level": "ERROR" } } + ] + } + }, + "size": 20, + "sort": [{"@timestamp": "desc"}] +} +``` + +### Search by traceId +```json +POST /api/console/proxy?path=/bmslog-bms-prod-/_search&method=GET +{ + "query": { + "term": { "traceId": "" } + }, + "sort": [{"@timestamp": "asc"}], + "size": 100 +} +``` + +### Count docs +``` +GET /api/console/proxy?path=/bmslog-bms-prod-/_count&method=GET +``` + +## Rules + +1. **Never re-probe ES connectivity** — Kibana proxy is the only working method +2. **Never try ES direct ports** — not accessible +3. **Never store credentials** in this file +4. **When user says "查 bms-prod" 或 "查生产日志" → query `bmslog-bms-prod-*` indices** diff --git a/bms-test-log-query/SKILL.md b/bms-test-log-query/SKILL.md new file mode 100644 index 0000000..3718cf8 --- /dev/null +++ b/bms-test-log-query/SKILL.md @@ -0,0 +1,111 @@ +--- +name: bms-test-log-query +description: > + Query BMS (bms-sit) application logs from Elasticsearch via Kibana console proxy. + Use when the user asks to check BMS logs, search BMS errors, or look up recent log entries. + All queries go through Kibana at http://172.17.12.18:8000 — ES direct port is NOT accessible. +metadata: + author: local + version: 3.0.0 +--- + +# BMS Log Query Skill + +> **Scope: ONLY `bms-sit` data view → `bms-test*` and `pms*` indices.** + +## Connection Details (DO NOT re-verify — confirmed working) + +- **Auth**: Read from `~/.env` (home directory): + - `BMS_LOG_URL` = Kibana proxy URL + - `BMS_LOG_USERNAME` = elastic + - `BMS_LOG_PASSWORD` = (stored in .env) +- **ES Version**: 8.6.1 +- **ES direct port**: NOT accessible. All queries go through Kibana console proxy. + +## Data View Mapping + +| Kibana Data View | ES Index Pattern | +|-----------------|------------------| +| `bms-sit` | `bms-test*, pms*` | + +## Kibana Console Proxy Format + +``` +POST http://172.17.12.18:8000/api/console/proxy?path=&method= +``` + +Headers: `kbn-xsrf: true`, `Content-Type: application/json` + +## Index Pattern + +- `bms-test-YYYY-MM-DD` — daily rolling indices, ~2,000,000 docs/day +- `pms-test-YYYY-MM-DD` — PMS test logs, ~59,000 docs/day + +## Query Patterns + +### Latest N logs +```json +POST /api/console/proxy?path=/bms-test-/_search&method=GET +{ + "sort": [{"@timestamp": "desc"}], + "size": 10 +} +``` + +### Search by keyword +```json +POST /api/console/proxy?path=/bms-test-/_search&method=GET +{ + "query": { + "multi_match": { + "query": "", + "fields": ["message", "error.message", "original_message"] + } + }, + "sort": [{"@timestamp": "desc"}], + "size": 20 +} +``` + +### Search errors in time range +```json +POST /api/console/proxy?path=/bms-test-/_search&method=GET +{ + "query": { + "bool": { + "must": [ + { "range": { "@timestamp": { "gte": "now-1h", "lte": "now" } } }, + { "match_phrase": { "message": "ERROR" } } + ] + } + }, + "size": 20, + "sort": [{"@timestamp": "desc"}] +} +``` + +### Count docs +``` +GET /api/console/proxy?path=/bms-test-/_count&method=GET +``` + +### Get mapping (available fields) +``` +GET /api/console/proxy?path=/bms-test-/_mapping&method=GET +``` + +## Common Fields + +- `@timestamp` — log timestamp +- `message` — main log message (Chinese/English) +- `original_message` — original unformatted message +- `log.level` — INFO, WARN, ERROR, etc. +- `error.message` — error details +- `host.name` — host/container name + +## Rules + +1. **Never re-probe ES connectivity** — Kibana proxy is the only working method +2. **Never try ports 9200/9201/5601** — not accessible +3. **Never store credentials** in this file +4. **When user says "查 bms-sit" → query `bms-test-*` indices**