10. 事件流监听器
连接到事件通道(端口 10020),打印系统事件,并可按级别、名称模式和排除规则进行可选过滤。只读——不使用会话配置文件,也不发送任何命令。
学习内容:
- 以被动观察者的身份订阅WebSocket 事件(端口
10020) - 解析事件 JSON —
level、name、category、data、message - 按最低严重程度筛选
- 通配符名称的匹配与排除
- 结合本教程与其他任意教程,用于对控制环进行基准测试
工作流程
- 解析命令行选项(
--level、--name、--exclude、--no-hide-rate、--port)。 - 连接到
ws://localhost:10020(即事件通道)——由于这是只读观察者,因此不会发送会话配置文件。 - 对于收到的每条消息,解析事件 JSON 并应用过滤规则:
- 如果
level如果低于最低严重级别,则予以丢弃。 - 如果指定了
--name模式,则仅当其中某个模式匹配(匹配name本身或category/name)时保留,否则丢弃。 - 如果任一
--exclude若模式匹配,则丢弃。
- 如果
- 打印已保留的事件,包括其级别、完整名称、可选的消息以及可选的
data负载。
参数
| 参数 | 默认值 | 用途 |
|---|---|---|
--port | 10020 | 事件通道端口 |
-l, --level | info | 最低严重级别,可选值为 info、notice、warning、error、critical、panic 之一 |
-n, --name | (无) | 仅显示符合该模式的事件(glob 通配符,可重复指定) |
-x, --exclude | (无) | 隐藏符合该模式的事件(glob 通配符,可重复指定) |
--no-hide-rate | false | 包含 system-rate-report 事件(默认隐藏,因其输出量很大) |
对控制环进行基准测试
在一个终端中运行任意教程(04-hello-floor、05-position-control、06-combined……),并在另一个终端中以 --no-hide-rate 运行事件监听器。system-rate-report 该事件包含设备的有效 tick 速率——通过比较同一教程中的 Python / C++ nlohmann 版本与 C++ Glaze 版本,可以观察到在约 4 kHz 控制环路上的序列化开销。
# Terminal 1 — pick a variant
./04-haply-inverse-hello-floor # C++ nlohmann
./04-haply-inverse-hello-floor-glz # C++ Glaze
python 04-haply-inverse-hello-floor.py # Python
# Terminal 2 — watch the rate
./10-haply-inverse-events --no-hide-rate
读取的状态字段
收到的每条消息都算作一个事件:
level— 字符串形式的严重级别(info……panic)name— 事件名称(例如device-connected、system-rate-report)category— 类别(例如device、session、system)message— 可选的可读字符串data— 可选的嵌套 JSON 负载(结构取决于具体事件)
完整的事件目录请参见:事件与监控。
发送 / 接收
被动订阅——仅使用 recv(),不会返回任何内容。三个版本的过滤流程相同;值得关注的 Inverse API 专属部分是事件结构体的形式。
- Python
- C++ (nlohmann)
- C++ (Glaze)
async for msg in websocket 这是接收循环的最简洁写法。
async with websockets.connect(uri) as websocket:
async for msg in websocket:
try:
event = json.loads(msg)
except json.JSONDecodeError:
continue
if accept_event(event, min_level_index, name_patterns, exclude_patterns):
print(format_event(event))
libhv 回调模型——onmessage 在 I/O 线程上运行,主线程阻塞等待按下 ENTER 键。事件被视为无类型的 JSON——每个字段都通过带有默认值的 .value(...) 读取。
ws.onmessage = [&](const std::string &msg) {
json event;
try { event = json::parse(msg); } catch (...) { return; }
if (accept_event(event, opts.min_level, opts.name_patterns, opts.exclude_patterns))
print_event(event);
};
ws.open("ws://localhost:10020");
while (std::cin.get() != '\n') {} // block main thread
已知的事件字段映射到一个有类型的 event_data 结构体。data 字段保留为 glz::raw_json_view,因此可以直接转发任何嵌套负载(其结构取决于具体事件),而无需定义完整的模式。
// Struct model — known fields typed, nested `data` kept as raw JSON
struct event_data {
std::string level;
std::string name;
std::string category;
std::string message;
glz::raw_json_view data{};
};
// Send / receive
ws.onmessage = [&](const std::string &msg) {
event_data event{};
if (glz::read<glz_settings>(event, msg)) return; // drop malformed
if (accept_event(event, opts.min_level, opts.name_patterns, opts.exclude_patterns))
print_event(event);
};
ws.open("ws://localhost:10020");
while (std::cin.get() != '\n') {} // block main thread
随 SDK 安装程序一同提供
教程 10 同样随 SDK 一起安装在本地,请在服务安装目录下的 tutorials/10-haply-inverse-events/ 中查找。
相关内容: 事件与监控·WebSocket 协议