OrangePi3588Media/plugins/alarm/actions/log_action.cpp
2026-04-18 20:58:31 +08:00

103 lines
3.3 KiB
C++

#include "log_action.h"
#include <chrono>
#include <ctime>
#include <iomanip>
#include <mutex>
#include <sstream>
#include "utils/logger.h"
namespace rk3588 {
namespace {
bool SafeLocalTime(std::time_t t, std::tm& out) {
#if defined(_WIN32)
return localtime_s(&out, &t) == 0;
#elif defined(__unix__) || defined(__APPLE__)
return localtime_r(&t, &out) != nullptr;
#else
static std::mutex mu;
std::lock_guard<std::mutex> lock(mu);
std::tm* p = std::localtime(&t);
if (!p) return false;
out = *p;
return true;
#endif
}
LogLevel LogLevelFromStringOrInfo(const std::string& s) {
LogLevel lvl = LogLevel::Info;
(void)ParseLogLevel(s, lvl);
return lvl;
}
} // namespace
bool LogAction::Init(const SimpleJson& config) {
level_ = config.ValueOr<std::string>("level", "info");
include_detections_ = config.ValueOr<bool>("include_detections", true);
LogInfo("[LogAction] initialized, level=" + level_);
return true;
}
void LogAction::Execute(AlarmEvent& event, std::shared_ptr<Frame> /*frame*/) {
auto now = std::chrono::system_clock::now();
auto time_t_now = std::chrono::system_clock::to_time_t(now);
std::tm tm_now{};
(void)SafeLocalTime(time_t_now, tm_now);
std::ostringstream oss;
oss << "[ALARM][" << level_ << "] "
<< std::put_time(&tm_now, "%Y-%m-%d %H:%M:%S")
<< " event_id=" << (event.event_id.empty() ? "-" : event.event_id)
<< " node=" << event.node_id
<< " rule=" << event.rule_name
<< " frame=" << event.frame_id;
if (include_detections_ && !event.detections.empty()) {
oss << " detections=[";
for (size_t i = 0; i < event.detections.size(); ++i) {
const auto& det = event.detections[i];
if (i > 0) oss << ", ";
oss << "{cls=" << det.cls_id
<< " score=" << std::fixed << std::setprecision(2) << det.score
<< " bbox=(" << static_cast<int>(det.bbox.x) << ","
<< static_cast<int>(det.bbox.y) << ","
<< static_cast<int>(det.bbox.w) << ","
<< static_cast<int>(det.bbox.h) << ")}";
}
oss << "]";
}
if (!event.face_matches.empty()) {
oss << " face_matches=[";
for (size_t i = 0; i < event.face_matches.size(); ++i) {
const auto& match = event.face_matches[i];
if (i > 0) oss << ", ";
const float sim_margin = match.best_sim - match.second_sim;
const std::string candidate = match.candidate_name.empty() ? "n/a" : match.candidate_name;
oss << "{status=" << FaceAlarmStatusName(match.status)
<< " candidate=" << candidate
<< " candidate_id=" << match.candidate_person_id
<< " best_sim=" << std::fixed << std::setprecision(2) << match.best_sim
<< " second_sim=" << std::fixed << std::setprecision(2) << match.second_sim
<< " sim_margin=" << std::fixed << std::setprecision(2) << sim_margin
<< "}";
}
oss << "]";
}
if (!event.snapshot_url.empty()) {
oss << " snapshot=" << event.snapshot_url;
}
if (!event.clip_url.empty()) {
oss << " clip=" << event.clip_url;
}
Logger::Instance().Log(LogLevelFromStringOrInfo(level_), oss.str());
}
} // namespace rk3588