事件
通过 device.events() 订阅运行态事件。
每个事件触发时都会再打 on_logged(等级跟随源事件),无论是否另订了对应事件。绑 on_logged 即可收到中文消息。
订阅后,调用 status_ex() 或 connected() 才会比对变化。第一次快照不触发(只记基线)。回调里 panic 不会把 SDK 弄停。每个事件只留一个回调:同名 on_* 再调一次是替换,不是追加。
网卡链路走事件:订阅 on_link_changed(服务端状态里没有 linkUp 字段时不触发)。IOPS 不走事件:on_io_status_changed 能订阅、能通过编译,但派发它的路径没有调用方,永远不会触发 —— 见 下节。要 IOPS 就轮询 io_status();链路快照另有 diag_snapshot().link_up。
功能概览
| 类别 | 事件 | 说明 | 自动日志 |
|---|---|---|---|
| 连接 | on_connected_changed | 与 IO 控制器的周期交换通断 | ✓ |
| 运行态 | on_state_changed | 运行态变化 | ✓ |
| 运行错误 | on_error_occurred | 运行错误 | ✓ |
| 链路 | on_link_changed | 网卡物理链路 Up / Down | ✓ |
| IOPS | on_io_status_changed | 收不到,别订 | — |
| 日志 | on_logged | 上面每条事件都会再打这条 | — |
on_io_status_changed 订了也不会响它能通过编译、能注册成功、不给任何报错,但回调一次都不会被调用。注册完一直没动静不等于 IOPS 一直是好的。拿不准就轮询 io_status()。详见 IOPS 订阅。
连接
on_connected_changed
pub fn on_connected_changed<F>(&self, cb: F)
where F: FnMut(&ConnectedChangedEvent) + 'static
周期数据交换通断时触发(connected == false 且 ever_connected == true = 掉线;ever_connected == false = 从未连上)。
回调参数:
pub struct ConnectedChangedEvent {
pub connected: bool, // 当前是否在换周期数据
pub ever_connected: bool, // 是否曾经连上过
pub level: EventLevel, // 连接 = Info;掉线 / 从未连上 = Warn
}
示例:
device.events().on_connected_changed(|e| {
if !e.connected && e.ever_connected {
println!("掉线");
}
});
运行态
on_state_changed
pub fn on_state_changed<F>(&self, cb: F)
where F: FnMut(&StateChangedEvent) + 'static
运行态变化时触发(SDK 只观测,不主动切状态)。old_state / new_state 类型是 ServiceState。
回调参数:
pub struct StateChangedEvent {
pub old_state: ServiceState, // 变化前,见 [ServiceState](./api#servicestate)
pub new_state: ServiceState, // 变化后
pub level: EventLevel, // Info
}
示例:
device.events().on_state_changed(|e| {
println!("{:?} → {:?}", e.old_state, e.new_state);
});
on_error_occurred
pub fn on_error_occurred<F>(&self, cb: F)
where F: FnMut(&ErrorOccurredEvent) + 'static
运行错误出现时触发;error_code 是 int 原值,枚举形态请用 device.error_code()。
回调参数:
pub struct ErrorOccurredEvent {
pub error_code: i32, // 运行错误原值(不是枚举)
pub message: String, // 中文消息;缺失为空串
pub level: EventLevel, // Warn
}
示例:
device.events().on_error_occurred(|e| {
println!("{}: {}", e.error_code, e.message);
});
链路
on_link_changed
pub fn on_link_changed<F>(&self, cb: F)
where F: FnMut(&LinkChangedEvent) + 'static
网卡物理链路 Up / Down 时触发。比对在 status_ex() / connected() 里做,第一次快照只记基线不触发。
服务端状态里没有 linkUp 字段时不触发 —— 不拿 connected 冒充物理链路,也不猜。
回调参数:
pub struct LinkChangedEvent {
pub link_up: bool, // 物理链路是否 Up
pub level: EventLevel, // Up = Info;Down = Warn
}
示例:
device.events().on_link_changed(|e| {
println!("链路 {}", if e.link_up { "Up" } else { "Down" });
});
过程数据质量
on_io_status_changed
pub fn on_io_status_changed<F>(&self, cb: F)
where F: FnMut(&IoStatusChangedEvent) + 'static
回调注册得进去,也通过编译,但一次都不会被调用:喂这条事件的解析路径(原先读 GET /api/io)现在没有调用方。
所以「订了 on_io_status_changed 之后一直没动静」不能当成「IOPS 一直是好的」。要看 IOPS 质量请轮询 io_status()。
回调参数:(当前不会被构造,列在这里只为对照类型)
pub struct IoStatusChangedEvent {
pub iops_bad: bool, // true = 当前 IOPS 不是全 GOOD
pub level: EventLevel, // BAD = Warn;否则 Info
}
只带一个布尔量:没有逐子模块的 IOPS 明细,也没有 BAD 字节计数。
日志
on_logged
pub fn on_logged<F>(&self, cb: F)
where F: FnMut(EventLevel, &str) + 'static
每个事件触发时都会再打这条,等级跟随源事件。
回调参数:
level(EventLevel) — 日志级别message(&str) — 日志正文
EventLevel
日志级别。取值见 枚举参考。没有稳定的整数判别值,按枚举名用。
示例:
device.events().on_logged(|level, message| {
println!("[{level:?}] {message}");
});
完整示例
device.events().on_connected_changed(|e| {
if !e.connected && e.ever_connected {
println!("掉线");
}
});
device.events().on_state_changed(|e| {
println!("{:?} → {:?}", e.old_state, e.new_state);
});
device.events().on_error_occurred(|e| {
println!("{}: {}", e.error_code, e.message);
});
device.events().on_link_changed(|e| {
println!("链路 {}", if e.link_up { "Up" } else { "Down" });
});
device.events().on_logged(|level, message| {
println!("[{level:?}] {message}");
});
IOPS 不进这份列表 —— on_io_status_changed 订了不会响,想要 IOPS 在循环里读 io_status()。