目录
代码
分析
主要结构
判断逻辑
备注
代码
class ChannelMonitor : public RecurrentRunner {
public:
explicit ChannelMonitor(
const std::shared_ptr<LatencyMonitor>& latency_monitor);
void RunOnce(const double current_time) override;
private:
static void UpdateStatus(
const apollo::dreamview::ChannelMonitorConfig& config,
ComponentStatus* status, const bool update_freq, const double freq);
std::shared_ptr<LatencyMonitor> latency_monitor_;
};
void ChannelMonitor::RunOnce(const double current_time) {
auto manager = MonitorManager::Instance();
const auto& mode = manager->GetHMIMode();
auto* components = manager->GetStatus()->mutable_components();
for (const auto& iter : mode.monitored_components()) {
const std::string& name = iter.first;
const auto& config = iter.second;
if (config.has_channel()) {
double freq;
const auto update_freq =
latency_monitor_->GetFrequency(config.channel().name(), &freq);
UpdateStatus(config.channel(),
components->at(name).mutable_channel_status(), update_freq,
freq);
}
}
}
分析
主要结构
runOnce 中不变的套路:
- 先从HMI mode 中获取所有配置的监控项目;
- 遍历监控项目,使用latency_monitor_->GetFrequency 获取channel的频率;
- 使用UpdateStatus 更新状态,生成报警
判断逻辑
void ChannelMonitor::UpdateStatus(
const apollo::dreamview::ChannelMonitorConfig& config,
ComponentStatus* status, const bool update_freq, const double freq) {
status->clear_status();
const auto reader_message_pair = GetReaderAndLatestMessage(config.name());
const auto reader = reader_message_pair.first;
const auto message = reader_message_pair.second;
if (reader == nullptr) {
SummaryMonitor::EscalateStatus(
ComponentStatus::UNKNOWN,
absl::StrCat(config.name(), " is not registered in ChannelMonitor."),
status);
return;
}
if (message == nullptr || message->ByteSize() == 0) {
SummaryMonitor::EscalateStatus(
ComponentStatus::FATAL,
absl::StrCat("the message ", config.name(), " reseived is empty."),
status);
return;
}
// Check channel delay
const double delay = reader->GetDelaySec();
if (delay < 0 || delay > config.delay_fatal()) {
SummaryMonitor::EscalateStatus(
ComponentStatus::FATAL,
absl::StrCat(config.name(), " delayed for ", delay, " seconds."),
status);
}
// Check channel fields
const std::string field_sepr = ".";
if (message != nullptr) {
for (const auto& field : config.mandatory_fields()) {
if (!ValidateFields(*message, absl::StrSplit(field, field_sepr), 0)) {
SummaryMonitor::EscalateStatus(
ComponentStatus::ERROR,
absl::StrCat(config.name(), " missing field ", field), status);
}
}
}
// Check channel frequency
if (update_freq) {
if (freq > config.max_frequency_allowed()) {
SummaryMonitor::EscalateStatus(
ComponentStatus::WARN,
absl::StrCat(config.name(), " has frequency ", freq,
" > max allowed ", config.max_frequency_allowed()),
status);
}
if (freq < config.min_frequency_allowed()) {
SummaryMonitor::EscalateStatus(
ComponentStatus::WARN,
absl::StrCat(config.name(), " has frequency ", freq,
" < min allowed ", config.max_frequency_allowed()),
status);
}
}
SummaryMonitor::EscalateStatus(ComponentStatus::OK, "", status);
}
- 通过channel 创建reader,获取最后一条msg;
- 如果reader 创建失败就把状态设置为unknow;
- 如果最后一帧消息是空,就把状态设置为FATAL;
- double delay = reader->GetDelaySec(); 获取延迟;如果延迟<0或者大于阈值就FATAL报警;
- 检查必要字段是否缺失,如果缺失就ERROR;
- 检查发送频率是否正常,如果不在阈值区间就报WARN;
备注
template <typename MessageT>
double Reader<MessageT>::GetDelaySec() const {
if (latest_recv_time_sec_ < 0) {
return -1.0;
}
if (second_to_lastest_recv_time_sec_ < 0) {
return Time::Now().ToSecond() - latest_recv_time_sec_;
}
return std::max((Time::Now().ToSecond() - latest_recv_time_sec_),
(latest_recv_time_sec_ - second_to_lastest_recv_time_sec_));
}
Reader 获取时间延迟的方法就是通过订阅接收到数据的然后做上一帧时间的差值