# 对象与心跳

Categraf 每 10 秒向夜莺发一次心跳，带上主机元信息完成注册；设备列表据此显示状态和标签，主机要手动归入业务组。

最后校对于 2026-10-10

**基础设施 → 设备列表** 是夜莺里的机器清单。这页讲一台机器怎么进到这个列表里、 列表里每一列是从哪来的、以及怎么给机器打标签、挂到业务组上。

## 心跳做了什么[​](#心跳做了什么 "心跳做了什么的直接链接")

Categraf 每隔 `[heartbeat] interval` 秒（默认 10）往夜莺的 `POST /v1/n9e/heartbeat` 发一个包，内容是这台机器的元信息：

| 字段                                | 来源                                                     |
| ----------------------------------- | -------------------------------------------------------- |
| `hostname`                          | `[global] hostname`，留空取 `os.Hostname()`              |
| `agent_version`                     | categraf 版本                                            |
| `os` / `arch`                       | 操作系统和 CPU 架构                                      |
| `cpu_num` / `cpu_util` / `mem_util` | 核数、CPU 和内存使用率                                   |
| `host_ip`                           | 探测到的本机 IP                                          |
| `global_labels`                     | `[global.labels]` 里配的标签                             |
| `extend_info`                       | CPU 型号、内存总量、网卡、内核版本、文件系统等一大堆明细 |
| `unixtime`                          | 发送时刻，夜莺用它算时间偏移                             |

**`hostname` 就是这台机器的唯一标识**（列表里的「标识」列）。夜莺按它建表， 所以它必须全局唯一——两台机器用同一个 hostname，夜莺只会有一条记录， 两边的元信息会在每次心跳时互相覆盖，**而且不会有任何告警**。

`interval` 小于 4 会被抬到 4；实际节奏比配置值略长，因为算 CPU 使用率本身要采样几秒。

`hostname` 支持占位符：`$hostname`、`$ip`、`$sn`（BIOS 序列号），以及环境变量。 比如 `hostname = "prod-$ip"`。

**第一次心跳只会写下最基本的东西**——夜莺是先查缓存再决定更新哪些字段的， 新机器还不在缓存里，所以 `AGENT版本`、`操作系统`、`来源 IP`、`上报的标签` 这几列要等 下一次缓存刷新之后的心跳才会填上。刚装完看到这几列是空的，等一会儿再看。

## 设备列表里能看到什么[​](#设备列表里能看到什么 "设备列表里能看到什么的直接链接")

表格 12 列，除了「自定义标签」「业务组」「备注」是你在夜莺里设的，其余都来自心跳：

| 列         | 说明                                                       |
| ---------- | ---------------------------------------------------------- |
| 标识       | 就是 hostname，唯一                                        |
| 状态       | 心跳新鲜度，见下一节                                       |
| AGENT版本  | categraf 版本                                              |
| 上报的标签 | agent 上报的 `[global.labels]`。需要 categraf v0.3.80 以上 |
| 自定义标签 | 你在夜莺里给这台机器打的标签                               |
| 业务组     | 这台机器属于哪些业务组                                     |
| 更新时间   | 最近一次心跳                                               |
| 内存 / CPU | 使用率。显示 unknown 表示这台机器从没上报过元信息          |
| 时间偏移   | 夜莺所在机器的时间**减去** categraf 所在机器的时间         |
| 来源 IP    | 心跳请求的来源地址                                         |
| 备注       | 你写的说明，会附到告警事件上                               |

左边的概览面板给的是聚合视角：机器总数、有心跳 / 无心跳、版本号分布、 以及「预置筛选」（全部机器 / 未归组机器）和业务组树。**未归组机器**特别值得看一眼—— 装完没挂业务组的机器都在那儿，很容易被漏掉。

「标识」这一列的表头里有个下拉，可以复制当前页 / 全部 / 所选的机器标识， 批量操作时很省事。

## 状态怎么判定[​](#状态怎么判定 "状态怎么判定的直接链接")

按最近一次心跳到现在的时间：

| 距上次心跳                      | 状态   |
| ------------------------------- | ------ |
| 60 秒内                         | 正常   |
| 60\~180 秒                      | 中间态 |
| 超过 180 秒，或者从来没有过心跳 | 无心跳 |

有一件事容易看错：**「更新时间」这一列不是心跳时间。** v9 里心跳时间只写 Redis （24 小时过期），数据库里的 `update_at` 只在元信息真的变了的时候才更新。 所以你可能看到「更新时间」是 40 分钟前，但状态显示正常——这不是 bug。 判断机器活没活着，看**状态**列。

顺带一个推论：**Redis 数据丢了，所有机器都会显示成无心跳**，直到下一轮心跳补回来。

CPU / 内存显示 `unknown` 是另一回事，它表示这台机器**从来没上报过元信息**—— 通常是只配了 writers、没开 heartbeat。

## 两种标签：上报的和自定义的[​](#两种标签上报的和自定义的 "两种标签：上报的和自定义的的直接链接")

夜莺把机器标签分成两类，来源不同，行为也不同：

* **上报的标签**：agent 在 `[global.labels]` 里配的，每次心跳全量覆盖。 改它要去机器上改配置；
* **自定义标签**：在夜莺界面上打的，形如 `k=v`，多个用空格分隔。 勾选机器后 **批量操作 → 绑定标签** / **解绑标签**。

**两边键名撞车时，上报的标签赢**，同名的自定义标签会被丢掉。 所以别用自定义标签去覆盖 agent 上报的值，那条路走不通。

这两类标签最终都会被附加到这台机器的指标上（由夜莺在转发时完成）， 所以打完标签就能在 PromQL 里按它筛选、聚合。

## 把机器归入业务组[​](#把机器归入业务组 "把机器归入业务组的直接链接")

业务组是夜莺的权限和归属单位：告警规则、仪表盘都挂在业务组下面。 机器不挂业务组，就没法被业务组内的规则覆盖。

勾选机器 → **批量操作 → 修改业务组**。一台机器可以属于多个业务组。

同一个菜单里还有 **修改备注**（备注会附到这台机器产生的告警事件上）和 **批量删除**。 删掉的机器如果 agent 还在跑，下一次心跳会把它重新建出来——**要真正下线一台机器， 先停 categraf，再删记录**。

## 对机器本身告警[​](#对机器本身告警 "对机器本身告警的直接链接")

机器失联这类告警不走时序库，用的是专门的 Host 规则类型： **告警通知 → 规则管理 → 新增**，数据源类型选 **Host**，告警条件有三种：

| 条件         | 含义                                                      |
| ------------ | --------------------------------------------------------- |
| 机器失联     | 超过 N 秒没有心跳                                         |
| 机器集群失联 | N 秒内失联比例超过 X%，用来区分「单机挂了」和「机房挂了」 |
| 机器时间偏移 | 时间偏移超过 N 毫秒                                       |

「机器集群失联」值得配一条：单机失联和整机房失联的处理方式完全不同， 分开告警能省掉一次误判。

## 下一步[​](#下一步 "下一步的直接链接")

* 机器没出现、状态不对：[排障](https://n9e.github.io/zh/docs/data/categraf/troubleshooting.md)
* 业务组是怎么回事：[业务组](https://n9e.github.io/zh/docs/concepts/business-groups.md)
* 给这些机器配规则：[第一条告警规则](https://n9e.github.io/zh/docs/alerting/first-rule.md)
* 从一台机器跳到它的核心指标：[对象快捷视图](https://n9e.github.io/zh/docs/query/object-view.md)
