# 系统

> 分类代号：C.11  本章共 **4 个接口**

这几个接口是运维和监控最常看的：

- **heart**：心跳
- **version**：版本与构建信息
- **runstatus**：当前进程 / 连接 / 切片状态
- **viewlogs**：读最近 N 条日志

生产环境完全可以周期性采集 `runstatus` 做监控告警，**不需要登进后端机器**。

---

## 快速索引

| 序号 | SDK 方法 | URL |
|----:|---------|-----|
| 64 | `heart` / `heart` | `GET /heart` |
| 65 | `version` / `version` | `GET /version` |
| 66 | `run_status` / `runStatus` | `GET /api/v1/map/cmd/runstatus/_/v1?detail=true` |
| 67 | `view_logs` / `viewLogs` | `GET /api/v1/map/cmd/viewlogs/_/v1?record=N` |

---

## 64 · 心跳 `/heart`

直接挂 Gateway 上（**不走 `/api/v1/...` 前缀**），用来判断进程是否活着。

### 响应（实采）

```json
{
  "status": "ok",
  "timestamp": "2026-04-22T12:37:54.501381+08:00"
}
```

### Python / Node.js

```python
svc.heart()
```

```javascript
await svc.heart();
```

### 用作健康检查

```yaml
# docker-compose healthcheck 片段
healthcheck:
  test: ["CMD", "curl", "-f", "http://127.0.0.1:27660/heart"]
  interval: 30s
  timeout: 3s
  retries: 3
```

---

## 65 · 版本 `/version`

### 响应（实采）

```json
{
  "arch":    "amd64",
  "os":      "windows",
  "status":  "ok",
  "time":    "2026-04-22 12:37:54",
  "version": "2026041001"
}
```

- `version` 是 service 的 build id（yyyyMMDD + 计数）
- `time`  是服务器当前时间，可用来校时
- 图形服务的版本在 `runstatus → application.version` 里（本例是 `"20260305"`）

---

## 66 · 运行状态 `runstatus`

### 查询参数

| 字段 | 默认 | 说明 |
|------|-----:|------|
| `detail` | `false` | `true` 时额外返回 `activeRequests` 列表 |

### 响应（实采 `detail=true`）

```json
{
  "application": {
    "pid":                   "11996",
    "runtime":               24063,
    "taskActiveThreadCount": 0,
    "threadId":              "12000",
    "version":               "20260305"
  },
  "process": {
    "activeProcesss":            {},
    "activeRequestCount":        0,
    "activeRequests":            [],
    "curParallelProcessGeomNum": 0,
    "maxParallelProcessGeomNum": 2,
    "recycleProcesss":           [],
    "reqTimeout":                600000,
    "waitWorkMapIds":            []
  },
  "slice": {},
  "store": {
    "connectionNames":        "_cache_map",
    "storeLastAccessTime":    [],
    "storeNoActiveCloseTime": 60,
    "storeStatus":            []
  }
}
```

### 字段速查

| 字段 | 含义 |
|------|------|
| `application.runtime` | 进程启动毫秒数 |
| `process.activeRequestCount` | 当前在处理的请求数 |
| `process.activeRequests` | `detail=true` 时的 URL 列表，排查"卡在什么请求上" |
| `process.curParallelProcessGeomNum` | 当前并行几何任务 |
| `process.maxParallelProcessGeomNum` | 并发上限 |
| `process.recycleProcesss` | 被回收的子进程 |
| `slice` | 切片缓存状态（按 layer） |
| `store` | KV 存储连接 |

### Python

```python
status = svc.run_status(detail=True)
assert status["application"]["pid"]
print(status["process"]["activeRequestCount"], "个并发请求")
```

### Node.js

```javascript
const st = await svc.runStatus(true);
```

---

## 67 · 查看日志 `viewlogs`

### 查询参数

| 字段 | 默认 | 说明 |
|------|-----:|------|
| `record` | 100 | 读取最近多少条记录 |
| `time` | 60 | 只看最近 N 分钟内的日志 |

### 响应（实采，部分片段）

```json
{
  "logs": [
    "       *** log260422_0x115f4_2026-04-22.log ***  ",
    "[2026-04-22 11:58:01.625] [daily_logger] [info] File:() Line:(0) Msg: (\"process app started..._null_@>v1_1571__||__11996__||__28011__||__D:/Program Files/vjmapserver/data\")\n",
    "[2026-04-22 11:58:01.697] [daily_logger] [info] File:() Line:(0) Msg: (openMap begin... \"_null_@>v1\")\n",
    ...
  ]
}
```

每一条都是一行日志（带行尾 `\n`）；多子进程时会用 `*** log....log ***` 分隔不同文件。

> ⚠️ **`record` 是"每个日志文件最近 N 条"而非全局 N 条**（record=1/5/100 分别回 32/63/162 行——每个子进程日志文件各贡献 ≤N 条 + `***` 文件头行）。本地有十几个 worker 日志文件时返回值远大于 N，按 `***` 头切段分组解析。

### Python

```python
lines = svc.view_logs(record=200)["logs"]
for line in lines[-20:]:
    print(line.rstrip())
```

### Node.js

```javascript
const { logs } = await svc.viewLogs(200);
```

> ⚠️ 这是**最近 N 条**，不是整个日志文件；想做审计请定时拉并本地存档。

---

## 监控样例：Python 拉取 → Prometheus

```python
from time import sleep
def poll():
    while True:
        try:
            s = svc.run_status(detail=False)
            metrics = {
                "vjmap_up":             1,
                "vjmap_active_reqs":    s["process"]["activeRequestCount"],
                "vjmap_runtime_ms":     s["application"]["runtime"],
                "vjmap_store_count":    len(s["store"].get("storeStatus") or []),
            }
        except Exception:
            metrics = {"vjmap_up": 0}
        push_to_prometheus(metrics)
        sleep(15)
```

---
