优化agent

This commit is contained in:
imengying committed 2026-08-28 00:54:37 +08:00
1 parent 0cdcbe40f4
commit 09db33d5fa
12 files changed
+206 -103

No files matched your search

+5 -11
View File
@@ -60,7 +60,6 @@ pub(crate) fn metric_history_ddl(table: &str) -> String {
disk_utilization REAL NOT NULL DEFAULT 0,
sample_count INTEGER NOT NULL DEFAULT 1 CHECK(sample_count > 0),
latest_timestamp INTEGER NOT NULL,
latest_json TEXT NOT NULL CHECK(json_valid(latest_json)),
latency_json TEXT NOT NULL DEFAULT '[]' CHECK(json_valid(latency_json)),
PRIMARY KEY(server_id, timestamp)
) WITHOUT ROWID"#
@@ -1028,14 +1027,14 @@ pub async fn save_reports_with_history(
tcp_connections, udp_connections, gpu_usage,
disk_read_bps, disk_write_bps, disk_read_iops, disk_write_iops,
disk_await_ms, disk_utilization, sample_count,
latest_timestamp, latest_json, latency_json
latest_timestamp, latency_json
) SELECT
?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14,
?15, ?16, ?17, ?18, ?19, ?20, ?21, ?22, ?23, ?24, ?25, ?26,
?27, ?28, ?29, ?30
?27, ?28, ?29
WHERE NOT EXISTS (
SELECT 1 FROM server_latest_state
WHERE server_id = ?1 AND last_batch_id = ?31
WHERE server_id = ?1 AND last_batch_id = ?30
) ON CONFLICT(server_id, timestamp) DO UPDATE SET
cpu=(metric_history.cpu * metric_history.sample_count +
excluded.cpu * excluded.sample_count) /
@@ -1074,9 +1073,6 @@ pub async fn save_reports_with_history(
disk_utilization=MAX(metric_history.disk_utilization, excluded.disk_utilization),
sample_count=metric_history.sample_count + excluded.sample_count,
latest_timestamp=MAX(metric_history.latest_timestamp, excluded.latest_timestamp),
latest_json=CASE
WHEN excluded.latest_timestamp >= metric_history.latest_timestamp THEN excluded.latest_json
ELSE metric_history.latest_json END,
latency_json=CASE
WHEN json_array_length(excluded.latency_json) = 0 THEN metric_history.latency_json
ELSE (
@@ -1161,7 +1157,6 @@ pub async fn save_reports_with_history(
number(history_point.disk_utilization),
number(sample_count.max(1)),
number(latest_timestamp),
text(&latest_json),
text(&latency_json),
text(batch_id),
])?;
@@ -1657,14 +1652,14 @@ pub async fn cleanup_history(db: &D1Database, retention_days: i64) -> Result<()>
net_rx_total, net_tx_total, processes, tcp_connections, udp_connections,
gpu_usage, disk_read_bps, disk_write_bps, disk_read_iops, disk_write_iops,
disk_await_ms, disk_utilization, sample_count,
latest_timestamp, latest_json, latency_json
latest_timestamp, latency_json
) SELECT
m.server_id, m.bucket, m.cpu, m.load1, m.load5, m.load15, m.mem_used,
m.mem_total, m.swap_used, m.swap_total, m.disk_used, m.disk_total,
m.net_in, m.net_out, m.net_rx_total, m.net_tx_total, m.processes,
m.tcp_connections, m.udp_connections, m.gpu_usage, m.disk_read_bps,
m.disk_write_bps, m.disk_read_iops, m.disk_write_iops, m.disk_await_ms,
m.disk_utilization, m.sample_count, m.latest_timestamp, '{}',
m.disk_utilization, m.sample_count, m.latest_timestamp,
COALESCE(l.latency_json, '[]')
FROM metrics m LEFT JOIN latency_packed l
ON l.server_id = m.server_id AND l.bucket = m.bucket
@@ -1693,7 +1688,6 @@ pub async fn cleanup_history(db: &D1Database, retention_days: i64) -> Result<()>
disk_utilization=excluded.disk_utilization,
sample_count=excluded.sample_count,
latest_timestamp=excluded.latest_timestamp,
latest_json=excluded.latest_json,
latency_json=excluded.latency_json"#,
)
.bind(&[number(cutoff), number(complete_hours_before)])?;
+52 -3
View File
@@ -28,6 +28,25 @@ const MAX_ALERT_WINDOW_SAMPLES: usize = 24 * 60 + 1;
const ALERT_STORAGE_PREFIX: &str = "resource-alert:";
const DASHBOARD_HUB_NAME: &str = "dashboard";
/// 机器身份字段,一批里逐条重复且几乎不变,实时样本不带它们。
///
/// 前端 `mergeServerLive` 是 `{ ...server, ...live.metrics }`,样本里缺的键会露出
/// bootstrap 那份,而 `SERVER_SELECT` 从 `server_latest_state.latest_json` 里
/// `json_extract` 出这七个字段,所以前端不需要任何改动。
///
/// 代价:agent 升级后这些值要等下一次 bootstrap 轮询才刷新。
/// 只影响展示,不影响任何判定 —— 告警和持久化读的是 `AgentReport` 本身,
/// 剥离只发生在发往浏览器的副本上。
const BROWSER_OMITTED_REPORT_FIELDS: [&str; 7] = [
"cpu_model",
"os",
"kernel",
"arch",
"virtualization",
"gpu_model",
"agent_version",
];
fn server_hub_name(server_id: &str) -> String {
format!("server:{server_id}")
}
@@ -427,6 +446,9 @@ fn batch_update_parts_at(
let mut data = serde_json::to_value(report)?;
if let Some(data) = data.as_object_mut() {
data.remove("timestamp");
for key in BROWSER_OMITTED_REPORT_FIELDS {
data.remove(key);
}
}
samples.push(CachedLiveSample {
ts: timestamp,
@@ -1382,9 +1404,10 @@ mod tests {
consume_agent_message_budget, finish_d1_flush, live_ack_payload, next_d1_write_ms,
outbound_close_code, trim_cached_live_samples, trim_socket_attachment, update_alert_window,
AgentMessageBudget, AlertEvaluationServer, AlertWindowSample, CachedLiveSample,
SocketAttachment, TrafficAttachment, ALERT_WINDOW_SECONDS, CACHED_LIVE_TTL_SECONDS,
MAX_AGENT_BYTES_PER_WINDOW, MAX_AGENT_MESSAGES_PER_WINDOW, MAX_AGENT_SAMPLES_PER_WINDOW,
MAX_CACHED_LIVE_BYTES, MAX_CACHED_LIVE_SAMPLES, MAX_SERIALIZED_ATTACHMENT_BYTES,
SocketAttachment, TrafficAttachment, ALERT_WINDOW_SECONDS, BROWSER_OMITTED_REPORT_FIELDS,
CACHED_LIVE_TTL_SECONDS, MAX_AGENT_BYTES_PER_WINDOW, MAX_AGENT_MESSAGES_PER_WINDOW,
MAX_AGENT_SAMPLES_PER_WINDOW, MAX_CACHED_LIVE_BYTES, MAX_CACHED_LIVE_SAMPLES,
MAX_SERIALIZED_ATTACHMENT_BYTES,
};
use crate::db::HistoryMetricAggregate;
use crate::latency::LatencyMetricAggregates;
@@ -1510,6 +1533,32 @@ mod tests {
assert!(payload["updates"][0]["samples"][0]["data"]
.get("timestamp")
.is_none());
// 身份字段不上线:前端靠 bootstrap 那份。fixture 里 cpu_model="CPU"、
// agent_version="test" 都是非空的,所以这几条断言不是空转。
for field in BROWSER_OMITTED_REPORT_FIELDS {
assert!(
payload["updates"][0]["samples"][0]["data"]
.get(field)
.is_none(),
"{field} 不应出现在发往浏览器的样本里"
);
}
// 同一批的动态字段必须留着,别把剥离范围扩大了
for field in [
"cpu",
"mem_used",
"net_in",
"uptime",
"cpu_cores",
"gpu_usage",
] {
assert!(
payload["updates"][0]["samples"][0]["data"]
.get(field)
.is_some(),
"{field} 是动态字段,不该被剥离"
);
}
let attachment = SocketAttachment {
role: "agent".to_string(),
server_id: Some("node-a".to_string()),