fix mq config and log control
This commit is contained in:
@@ -68,6 +68,15 @@ extern std::string intToString(int number);
|
||||
|
||||
//日志主题
|
||||
extern std::string G_LOG_TOPIC;
|
||||
|
||||
// 日志限流配置
|
||||
extern int G_LOG_RATE_RESET_SEC;
|
||||
extern int G_LOG_RATE_LIMIT_SEC;
|
||||
extern int G_LOG_RATE_KEEP_ALL_MS;
|
||||
extern int G_LOG_RATE_KEEP_BURST_MS;
|
||||
extern int G_LOG_RATE_KEEP_BURST_COUNT;
|
||||
extern int G_LOG_RATE_KEEP_HIGHFREQ_COUNT;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//log4命名空间
|
||||
using namespace log4cplus;
|
||||
@@ -337,7 +346,19 @@ protected:
|
||||
|
||||
// ③ 限频:同一条日志
|
||||
const std::string rkey = make_key(logger_name, level, code, msg);
|
||||
if (!should_emit(rkey)) return;
|
||||
|
||||
uint64_t suppressed_before_emit = 0;
|
||||
if (!should_emit(rkey, suppressed_before_emit)) return;
|
||||
|
||||
// 如果本次输出前压掉过日志,则在 log 文本后追加统计
|
||||
std::string final_msg = msg;
|
||||
if (suppressed_before_emit > 0) {
|
||||
std::ostringstream suppressed_oss;
|
||||
suppressed_oss << msg << " 【中间重复抑制 "
|
||||
<< suppressed_before_emit
|
||||
<< " 条】";
|
||||
final_msg = suppressed_oss.str();
|
||||
}
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "{\"processNo\":\"" << intToString(g_front_seg_index)
|
||||
@@ -348,7 +369,7 @@ protected:
|
||||
<< "\",\"logtype\":\"" << safe_logtype
|
||||
<< "\",\"frontType\":\"" << get_front_type_from_subdir()
|
||||
<< "\",\"code\":" << code
|
||||
<< ",\"log\":\"" << escape_json(msg) << "\"}";
|
||||
<< ",\"log\":\"" << escape_json(final_msg) << "\"}";
|
||||
|
||||
Ckafka_data_t connect_info;
|
||||
connect_info.strTopic = QString::fromStdString(G_LOG_TOPIC);
|
||||
@@ -386,12 +407,20 @@ public:
|
||||
//////////////////////////////////////////////////////////////////20260303添加日志上送控制 - 频率限制实现
|
||||
private:
|
||||
struct RateState {
|
||||
uint64_t hit_count;
|
||||
uint64_t pass_count; // 当前周期内已放行条数
|
||||
uint64_t suppressed_count; // 当前被抑制条数
|
||||
std::chrono::steady_clock::time_point last_emit;
|
||||
std::chrono::steady_clock::time_point last_seen;
|
||||
std::chrono::steady_clock::time_point last_reset;
|
||||
bool has_emit;
|
||||
|
||||
RateState() : hit_count(0), last_emit(), last_reset(), has_emit(false) {}
|
||||
RateState()
|
||||
: pass_count(0),
|
||||
suppressed_count(0),
|
||||
last_emit(),
|
||||
last_seen(),
|
||||
last_reset(),
|
||||
has_emit(false) {}
|
||||
};
|
||||
|
||||
static std::unordered_map<std::string, RateState> s_rate_map;
|
||||
@@ -403,52 +432,94 @@ private:
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
static bool should_emit(const std::string& key) {
|
||||
static bool should_emit(const std::string& key, uint64_t& suppressed_before_emit) {
|
||||
using namespace std::chrono;
|
||||
|
||||
const auto now = steady_clock::now();
|
||||
suppressed_before_emit = 0;
|
||||
|
||||
std::lock_guard<std::mutex> lk(s_rate_mutex);
|
||||
RateState& st = s_rate_map[key];
|
||||
|
||||
const int RESET_SEC = 3600;
|
||||
const int RESET_SEC = G_LOG_RATE_RESET_SEC ; // 1小时重置
|
||||
const int LIMIT_SEC = G_LOG_RATE_LIMIT_SEC ; // 进入限流后:1分钟1条
|
||||
|
||||
// 🚀 强制时间窗口重置(关键)
|
||||
if (st.has_emit) {
|
||||
// 初始化 / 强制每小时重置
|
||||
if (st.last_reset.time_since_epoch().count() == 0) {
|
||||
st.last_reset = now;
|
||||
} else {
|
||||
auto since_reset = duration_cast<seconds>(now - st.last_reset).count();
|
||||
if (since_reset >= RESET_SEC) {
|
||||
st.hit_count = 0;
|
||||
st.has_emit = false;
|
||||
st = RateState();
|
||||
st.last_reset = now;
|
||||
}
|
||||
}
|
||||
|
||||
// 计算当前频率档位(按“本次与上次看到该key的间隔”判断)
|
||||
// >=60秒/条:全部保留
|
||||
// [1秒, 60秒):保留前60条,然后1分钟1条
|
||||
// <1秒:保留前10条,然后1分钟1条
|
||||
int allow_burst = 0;
|
||||
|
||||
if (st.last_seen.time_since_epoch().count() == 0) {
|
||||
// 第一次看到,先按“全部保留”处理
|
||||
allow_burst = -1;
|
||||
} else {
|
||||
// 第一次初始化
|
||||
st.last_reset = now;
|
||||
auto gap_ms = duration_cast<milliseconds>(now - st.last_seen).count();
|
||||
|
||||
if (gap_ms >= G_LOG_RATE_KEEP_ALL_MS) {
|
||||
allow_burst = -1; // 全部保留
|
||||
} else if (gap_ms >= G_LOG_RATE_KEEP_BURST_MS) {
|
||||
allow_burst = G_LOG_RATE_KEEP_BURST_COUNT; // 前60条
|
||||
} else {
|
||||
allow_burst = G_LOG_RATE_KEEP_HIGHFREQ_COUNT; // 前10条
|
||||
}
|
||||
}
|
||||
|
||||
st.hit_count++;
|
||||
st.last_seen = now;
|
||||
|
||||
// 🚀 前20条:完全放行
|
||||
if (st.hit_count <= 20) {
|
||||
// 档位1:全部保留
|
||||
if (allow_burst == -1) {
|
||||
suppressed_before_emit = st.suppressed_count;
|
||||
st.suppressed_count = 0;
|
||||
st.pass_count++;
|
||||
st.last_emit = now;
|
||||
st.has_emit = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 🚀 超过20条:1分钟限1条
|
||||
const int period_sec = 60;
|
||||
// 档位2/3:先放前N条
|
||||
if (st.pass_count < (uint64_t)allow_burst) {
|
||||
suppressed_before_emit = st.suppressed_count;
|
||||
st.suppressed_count = 0;
|
||||
st.pass_count++;
|
||||
st.last_emit = now;
|
||||
st.has_emit = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 超过前N条后:进入 1分钟1条
|
||||
if (!st.has_emit) {
|
||||
suppressed_before_emit = st.suppressed_count;
|
||||
st.suppressed_count = 0;
|
||||
st.pass_count++;
|
||||
st.last_emit = now;
|
||||
st.has_emit = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto elapsed = duration_cast<seconds>(now - st.last_emit).count();
|
||||
if (elapsed >= period_sec) {
|
||||
auto elapsed = duration_cast<seconds>(now - st.last_emit).count();
|
||||
if (elapsed >= LIMIT_SEC) {
|
||||
suppressed_before_emit = st.suppressed_count;
|
||||
st.suppressed_count = 0;
|
||||
st.pass_count++;
|
||||
st.last_emit = now;
|
||||
st.has_emit = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 本条被抑制
|
||||
st.suppressed_count++;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user