refactor(style): sweep variant call sites — struct → tuple syntax

Follow-up to 3acd2eb error/log variant redesign. Updates 15 call sites
across adapter/persistence, telegram, correlation, detection,
notification, SOAR, audit, and Suricata to match the new tuple-style
traceable!/loggable! variant signatures. No behavior change; net -25 lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
DaLaw2 2026-04-17 01:07:55 +08:00
parent 3acd2ebf96
commit c4ac70fbe1
15 changed files with 70 additions and 95 deletions

View File

@ -26,7 +26,7 @@ impl AccessControlPort for EbpfAccessControlAdapter {
async fn block_ip(&self, ip: &str) -> Result<(), Error> {
let addr: IpAddr = ip
.parse()
.map_err(|_| Error::from(EbpfError::InvalidIpAddress { ip: ip.to_string() }))?;
.map_err(|_| Error::from(EbpfError::InvalidIpAddress(ip.to_string())))?;
match addr {
IpAddr::V4(v4) => {
let socket = SocketAddrV4::new(v4, 0);
@ -46,7 +46,7 @@ impl AccessControlPort for EbpfAccessControlAdapter {
async fn unblock_ip(&self, ip: &str) -> Result<(), Error> {
let addr: IpAddr = ip
.parse()
.map_err(|_| Error::from(EbpfError::InvalidIpAddress { ip: ip.to_string() }))?;
.map_err(|_| Error::from(EbpfError::InvalidIpAddress(ip.to_string())))?;
match addr {
IpAddr::V4(v4) => {
let socket = SocketAddrV4::new(v4, 0);

View File

@ -620,10 +620,7 @@ impl Database {
)
.map_err(|e| -> Error {
if e.to_string().contains("UNIQUE constraint") {
DatabaseError::UserAlreadyExists {
username: username.to_string(),
}
.into()
DatabaseError::UserAlreadyExists(username.to_string()).into()
} else {
e.into()
}

View File

@ -130,10 +130,7 @@ impl TelegramAdapter {
if status.as_u16() == 401 || status.as_u16() == 403 {
let body = resp.text().await.unwrap_or_default();
if body.contains("chat not found") || body.contains("CHAT_NOT_FOUND") {
return Err(NotificationError::TelegramChatNotFound {
chat_id: chat_id.to_string(),
}
.into());
return Err(NotificationError::TelegramChatNotFound(chat_id.to_string()).into());
}
return Err(NotificationError::TelegramAuthError.into());
}
@ -156,10 +153,7 @@ impl TelegramAdapter {
sleep(Duration::from_secs(retry_after)).await;
continue;
} else {
return Err(NotificationError::TelegramRateLimited {
retry_after_secs: retry_after,
}
.into());
return Err(NotificationError::TelegramRateLimited(retry_after).into());
}
}

View File

@ -74,11 +74,11 @@ impl BotnetDetector {
};
if let Some(unique_sources) = should_alert {
log!(DetectionLog::BotnetDetected {
dst_ip: key.clone(),
log!(DetectionLog::BotnetDetected(
key.clone(),
unique_sources,
window_secs: BOTNET_WINDOW_SECS,
});
BOTNET_WINDOW_SECS,
));
// source_ip = the latest attacker; dest_ip = the victim being targeted.
// SOAR blocks source_ip, so we must NOT put the victim here.

View File

@ -72,7 +72,7 @@ impl CorrelationEngine {
fn cleanup(&self) {
let removed = self.botnet.cleanup() + self.scan.cleanup() + self.lateral.cleanup();
if removed > 0 {
log!(DetectionLog::CorrelationCleanup { removed });
log!(DetectionLog::CorrelationCleanup(removed));
}
}
}

View File

@ -74,11 +74,11 @@ impl LateralMovementDetector {
};
if let Some(unique_dests) = should_alert {
log!(DetectionLog::LateralMovementDetected {
src_ip: key.clone(),
log!(DetectionLog::LateralMovementDetected(
key.clone(),
unique_dests,
window_secs: LATERAL_WINDOW_SECS,
});
LATERAL_WINDOW_SECS,
));
let event = DetectionEvent {
source: DetectionSource::Correlation,

View File

@ -72,11 +72,7 @@ impl ScanDetector {
};
if let Some((unique_ports, last_dst_ip)) = should_alert {
log!(DetectionLog::ScanDetected {
src_ip: key.clone(),
unique_ports,
window_secs: SCAN_WINDOW_SECS,
});
log!(DetectionLog::ScanDetected(key.clone(), unique_ports, SCAN_WINDOW_SECS,));
let event = DetectionEvent {
source: DetectionSource::Correlation,

View File

@ -126,13 +126,13 @@ impl BeaconingDetector {
// Phase 2: selective write-lock only for entries that need last_alerted update.
for (key, cv, count) in alerts {
let (src_ip, dst_ip, dst_port) = &key;
log!(DetectionLog::BeaconingDetected {
src_ip: src_ip.clone(),
dst_ip: dst_ip.clone(),
dst_port: *dst_port,
log!(DetectionLog::BeaconingDetected(
src_ip.clone(),
dst_ip.clone(),
*dst_port,
cv,
count,
});
));
let event = DetectionEvent {
source: DetectionSource::Beaconing,

View File

@ -104,10 +104,7 @@ impl DetectionOrchestrator {
entry.sources.push(event.source.clone());
}
}
log!(DetectionLog::DetectionDeduplicated {
source_ip: event.source_ip,
attack_type: event.attack_type,
});
log!(DetectionLog::DetectionDeduplicated(event.source_ip, event.attack_type,));
return;
}
@ -115,15 +112,15 @@ impl DetectionOrchestrator {
let threat_event = self.enrich(&event).await;
let sources = vec![event.source.clone()];
log!(DetectionLog::DetectionEmitted {
source_ip: event.source_ip.clone(),
attack_type: event.attack_type.clone(),
confidence: event.confidence,
ae_score: event.ae_score,
anomaly_score: event.anomaly_score,
c2_score: event.c2_score,
sources_count: sources.len(),
});
log!(DetectionLog::DetectionEmitted(
event.source_ip.clone(),
event.attack_type.clone(),
event.confidence,
event.ae_score,
event.anomaly_score,
event.c2_score,
sources.len(),
));
// Record dedup entry (LRU-bounded)
self.dedup.put(

View File

@ -77,19 +77,18 @@ impl NotificationService {
/// Send a test email using current SMTP config.
pub fn test_smtp(&self) -> Result<String, Error> {
let smtp_client = SmtpClient::from_database(self.repo.as_ref(), Some(self.secrets.as_ref()))?;
let smtp = smtp_client.ok_or_else(|| MiscError::ValidationError {
message: "SMTP not configured. Set smtp_host, smtp_port, smtp_username, smtp_password first. \
If smtp_username is not an email address, also set smtp_sender."
.into(),
let smtp = smtp_client.ok_or_else(|| {
MiscError::ValidationError(
"SMTP not configured. Set smtp_host, smtp_port, smtp_username, smtp_password first. \
If smtp_username is not an email address, also set smtp_sender.",
)
})?;
let recipient = self
.repo
.get_setting("smtp_recipient")?
.filter(|r| !r.is_empty())
.ok_or_else(|| MiscError::ValidationError {
message: "No smtp_recipient configured.".into(),
})?;
.ok_or_else(|| MiscError::ValidationError("No smtp_recipient configured."))?;
smtp.send(
&recipient,

View File

@ -138,10 +138,10 @@ impl SoarEngine {
action_order: order,
action_type: atype,
params: serde_json::from_str(&params_str).unwrap_or_else(|e| {
log!(SoarLog::PlaybookError {
name: pb.name.clone(),
error: format!("Malformed action params JSON: {}", e),
});
log!(SoarLog::PlaybookError(
pb.name.clone(),
format!("Malformed action params JSON: {e}"),
));
Value::Object(Default::default())
}),
});

View File

@ -162,10 +162,10 @@ impl System {
log!(MLLog::ModelsLoaded(
self.app_services.ml_models.get_model_info("classifier")
));
log!(MLLog::ConfigLoaded {
features: self.inference_config.num_ae_features(),
attacks: self.inference_config.num_attack_types()
});
log!(MLLog::ConfigLoaded(
self.inference_config.num_ae_features(),
self.inference_config.num_attack_types(),
));
// aya_log_init + attach_xdp only make sense if the eBPF objects
// loaded. When eBPF is unavailable we skip both; the rest of the

View File

@ -32,7 +32,7 @@ impl AuditLogger {
this.handle_audit_event(&event);
}
Err(RecvError::Lagged(n)) => {
log!(AuditLog::AuditLagged { count: n });
log!(AuditLog::AuditLagged(n));
}
Err(RecvError::Closed) => {
log!(AuditLog::AuditChannelClosed);
@ -55,7 +55,7 @@ impl AuditLogger {
this.handle_drift_event(&event);
}
Err(RecvError::Lagged(n)) => {
log!(AuditLog::AuditLagged { count: n });
log!(AuditLog::AuditLagged(n));
}
Err(RecvError::Closed) => {
log!(AuditLog::AuditChannelClosed);
@ -71,18 +71,15 @@ impl AuditLogger {
fn handle_audit_event(&self, event: &AuditEvent) {
// Always emit a structured log line
log!(AuditLog::AuditEvent {
actor: event.actor.clone(),
action: event.action.clone()
});
log!(AuditLog::AuditEvent(event.actor.clone(), event.action.clone(),));
// Attempt DB insert; on failure, log a warning but do not panic
if let Err(e) = self.db.insert_audit_log(&event.actor, &event.action, &event.detail) {
log!(AuditLog::AuditDbWriteFailed {
error: e.to_string(),
actor: event.actor.clone(),
action: event.action.clone()
});
log!(AuditLog::AuditDbWriteFailed(
e.to_string(),
event.actor.clone(),
event.action.clone(),
));
}
}
@ -93,12 +90,10 @@ impl AuditLogger {
})
.to_string();
log!(AuditLog::AuditDriftEvent {
count: event.drifted_features.len()
});
log!(AuditLog::AuditDriftEvent(event.drifted_features.len()));
if let Err(e) = self.db.insert_audit_log("system", "ml_drift_detected", &detail) {
log!(AuditLog::AuditDriftDbWriteFailed { error: e.to_string() });
log!(AuditLog::AuditDriftDbWriteFailed(e.to_string()));
}
}
}

View File

@ -87,25 +87,22 @@ impl SuricataManager {
let pid = child.id().unwrap_or(0);
*self.health.write() = SuricataHealth::Running { pid };
log!(SuricataLog::Started { pid });
log!(SuricataLog::Started(pid));
tokio::select! {
exit = child.wait() => {
let reason = match exit {
Ok(status) => format!("exited with {}", status),
Err(e) => format!("wait error: {}", e),
Ok(status) => format!("exited with {status}"),
Err(e) => format!("wait error: {e}"),
};
if self.config.suricata.auto_restart_on_crash {
let backoff = self.config.suricata.restart_backoff_secs;
log!(SuricataLog::CrashedRestartPending {
reason: reason.clone(),
backoff,
});
log!(SuricataLog::CrashedRestartPending(reason.clone(), backoff));
*self.health.write() = SuricataHealth::Stopped { reason };
sleep(Duration::from_secs(backoff)).await;
continue;
} else {
log!(SuricataLog::Stopped { reason: reason.clone() });
log!(SuricataLog::Stopped(reason.clone()));
*self.health.write() = SuricataHealth::Stopped { reason };
return;
}
@ -138,11 +135,11 @@ impl SuricataManager {
let sc = &self.config.suricata;
let iface = &self.config.network.ingress_ifname;
log!(SuricataLog::Spawning {
binary: sc.binary_path.clone(),
config: sc.config_path.clone(),
iface: iface.clone(),
});
log!(SuricataLog::Spawning(
sc.binary_path.clone(),
sc.config_path.clone(),
iface.clone(),
));
let mut cmd = Command::new(&sc.binary_path);
cmd.arg("-c")

View File

@ -63,7 +63,7 @@ impl SuricataMonitor {
// Wait until the file exists — Suricata spawns asynchronously and
// may take a few seconds to create eve.json.
if !Path::new(&path).exists() {
log!(SuricataLog::MonitorWaitingForFile { path: path.clone() });
log!(SuricataLog::MonitorWaitingForFile(path.clone()));
while !Path::new(&path).exists() {
sleep(FILE_WAIT_INTERVAL).await;
}
@ -79,7 +79,7 @@ impl SuricataMonitor {
// Seek to end so we only see new content from this point. Suricata
// writes a large volume at startup that we don't want to replay.
let mut pos: u64 = file.seek(SeekFrom::End(0)).await.unwrap_or_default();
log!(SuricataLog::MonitorAttached { path: path.clone() });
log!(SuricataLog::MonitorAttached(path.clone()));
let mut reader = BufReader::new(file);
let mut line = String::new();
@ -161,12 +161,12 @@ impl SuricataMonitor {
_ => 0.50,
};
log!(SuricataLog::AlertForwarded {
log!(SuricataLog::AlertForwarded(
sid,
src: src_ip.clone(),
dst: dest_ip.clone(),
src_ip.clone(),
dest_ip.clone(),
signature,
});
));
Some(DetectionEvent {
source: DetectionSource::Suricata,