add fun in log4

This commit is contained in:
lnk
2026-01-07 11:02:03 +08:00
parent be068fab40
commit 02127869c0
4 changed files with 139 additions and 16 deletions

View File

@@ -125,14 +125,13 @@ bool DebugSwitch::match(const std::string& logger_name, int level, int logtype)
std::map<std::string, TypedLogger> logger_map;
DebugSwitch g_debug_switch;
class SendAppender : public Appender {
/*class SendAppender : public Appender {
protected:
void append(const spi::InternalLoggingEvent& event) {
std::string logger_name = event.getLoggerName();
int level = event.getLogLevel();
std::string msg = event.getMessage();
int logtype = (logger_name.find(".COM") != std::string::npos) ? LOGTYPE_COM : LOGTYPE_DATA;
std::string level_str;
if (logger_name.find("process") == 0)
level_str = "process";
@@ -193,15 +192,139 @@ public:
virtual ~SendAppender() {
destructorImpl(); // 重要!释放 log4cplus 基类资源
}
};*/
class SendAppender : public Appender {
private:
struct RateState {
uint64_t hit_count = 0; // 同一条日志累计命中次数
std::chrono::steady_clock::time_point last_emit =
std::chrono::steady_clock::time_point::min();
};
static std::unordered_map<std::string, RateState> s_rate_map;
static std::mutex s_rate_mutex;
// 定义“同一条日志”的规则logger + level + code + msg //原来只区分了日志登记名和等级,现在具体到每一条日志
static std::string make_key(const std::string& logger_name, int level, int code, const std::string& msg) {
std::ostringstream oss;
oss << logger_name << "|" << level << "|" << code << "|" << msg;
return oss.str();
}
// 前 5 次1 秒一次;第 6 次起300 秒一次
static bool should_emit(const std::string& key) {
using namespace std::chrono;
const auto now = steady_clock::now();
std::lock_guard<std::mutex> lk(s_rate_mutex);
RateState& st = s_rate_map[key];
st.hit_count++;
const int period_sec = (st.hit_count > 5) ? 300 : 1;
if (st.last_emit == steady_clock::time_point::min()) {
st.last_emit = now;
return true;
}
const auto elapsed = duration_cast<seconds>(now - st.last_emit).count();
if (elapsed >= period_sec) {
st.last_emit = now;
return true;
}
return false;
}
protected:
void append(const spi::InternalLoggingEvent& event) override {
std::string logger_name = event.getLoggerName();
int level = event.getLogLevel();
std::string msg = event.getMessage();
std::string level_str;
if (logger_name.find("process") == 0)
level_str = "process";
else if (logger_name.find("monitor") != std::string::npos)
level_str = "measurepoint";
else
level_str = "terminal";
// TLS code
int code = g_log_code_tls;
const int safe_logtype = 0;
if (!(level == ERROR_LOG_LEVEL ||
level == WARN_LOG_LEVEL ||
g_debug_switch.match(logger_name, level, safe_logtype))) {
return;
}
// ★新增:限频判断(同一条日志前 5 次 1 秒一次;之后 300 秒一次)
const std::string key = make_key(logger_name, level, code, msg);
if (!should_emit(key)) {
return;
}
std::ostringstream oss;
oss << "{\"processNo\":\"" << std::to_string(g_front_seg_index)
<< "\",\"nodeId\":\"" << FRONT_INST
<< "\",\"businessId\":\"" << extract_logger_id(logger_name)
<< "\",\"level\":\"" << level_str
<< "\",\"time\":\"" << now_yyyy_mm_dd_hh_mm_ss()
<< "\",\"grade\":\"" << get_level_str(level)
// ★建议code 用数字(不是字符串)
<< "\",\"code\":" << code
<< ",\"log\":\"" << escape_json(msg) << "\"}";
queue_data_t connect_info;
connect_info.strTopic = G_LOG_TOPIC;
connect_info.strText = oss.str();
connect_info.tag = G_LOG_TAG;
connect_info.key = G_LOG_KEY;
std::lock_guard<std::mutex> lock(queue_data_list_mutex);
queue_data_list.push_back(connect_info);
}
std::string escape_json(const std::string& input) {
std::ostringstream ss;
for (size_t i = 0; i < input.size(); ++i) {
switch (input[i]) {
case '\\': ss << "\\\\"; break;
case '"': ss << "\\\""; break;
case '\n': ss << "\\n"; break;
case '\r': ss << "\\r"; break;
case '\t': ss << "\\t"; break;
default: ss << input[i]; break;
}
}
return ss.str();
}
void close() override {
// 可空实现
}
public:
SendAppender() {}
virtual ~SendAppender() {
destructorImpl();
}
};
//用来控制日志上送的静态变量定义
std::unordered_map<std::string, SendAppender::RateState> SendAppender::s_rate_map;
std::mutex SendAppender::s_rate_mutex;
//用来控制日志上送的结构
struct LOGEntry {
std::string id;
std::string level; // terminal / measurepoint
int logtype; // com / data
int min_grade;
int countdown;
std::string id; //测点和装置需要的id
std::string level; // terminal / measurepoint /process
int min_grade; // DEBUG / INFO / WARN / ERROR
int countdown; // 倒计时,单位秒
};
//日志上送map管理
@@ -209,8 +332,8 @@ std::map<std::string, LOGEntry> g_log_entries;
pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;
// 生成唯一 key
std::string build_debug_key(const std::string& id, const std::string& level, int logtype) {
return id + "|" + level + "|" + (logtype == 1 ? "COM" : "DATA");
std::string build_debug_key(const std::string& id, const std::string& level) {
return id + "|" + level + "|";
}
// 外部线程中调用每秒更新所有倒计时0 则删除
@@ -234,17 +357,16 @@ void update_log_entries_countdown() {
void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str) {
if (level != "terminal" && level != "measurepoint") return;
int type = (logtype_str == "com") ? LOGTYPE_COM : LOGTYPE_DATA;
int grade_level = (grade == "DEBUG") ? DEBUG_LOG_LEVEL : INFO_LOG_LEVEL;
std::string key = build_debug_key(id, level, type);
std::string key = build_debug_key(id, level);
pthread_mutex_lock(&g_log_mutex);
LOGEntry& entry = g_log_entries[key]; // 会自动 insert 或取已有
entry.id = id;
entry.level = level;
entry.logtype = type;
entry.min_grade = grade_level;
entry.countdown = 60; // 重置倒计时