2026-03-22 03:30:21 +00:00
|
|
|
use crate::monitoring::types::{AlertRuleKind, FiredAlert};
|
|
|
|
|
use crate::webhooks::{self, WebhookEvent, WebhookPayload};
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
use tracing::info;
|
|
|
|
|
|
|
|
|
|
/// Push fired alerts as notifications to the state manager (broadcast via WebSocket).
|
|
|
|
|
pub(crate) async fn push_alert_notifications(
|
|
|
|
|
state_mgr: &Arc<crate::state::StateManager>,
|
|
|
|
|
alerts: &[FiredAlert],
|
|
|
|
|
) {
|
|
|
|
|
let (mut data, _rev) = state_mgr.get_snapshot().await;
|
|
|
|
|
for alert in alerts {
|
|
|
|
|
let level = match alert.kind {
|
|
|
|
|
AlertRuleKind::DiskUsage | AlertRuleKind::RamUsage => {
|
|
|
|
|
if alert.value > 95.0 {
|
|
|
|
|
crate::data_model::NotificationLevel::Error
|
|
|
|
|
} else {
|
|
|
|
|
crate::data_model::NotificationLevel::Warning
|
|
|
|
|
}
|
|
|
|
|
}
|
chore(ci): rustfmt + clippy clean-up to unblock the Rust CI job
The .github/workflows/ci.yml Rust job runs cargo fmt --check, clippy
with -D warnings, and tests. All three were failing. This commit:
- Applies rustfmt across the tree (the bulk of the diff — untouched
since the last toolchain bump, so a wide sweep was unavoidable).
- Fixes the correctness-level clippy errors:
container/bitcoin_simulator.rs wildcard-in-or-pattern
container/manifest.rs from_str rename to parse (reserved name)
container/podman_client.rs .get(0) -> .first()
container/runtime.rs manual += collapse
archipelago/src/constants.rs doc-comment → module-doc
api/rpc/package/install.rs stray /// comment above a non-item
container/docker_packages.rs redundant field init
streaming/advertisement.rs missing Metric import in tests
tests/orchestration_tests.rs `vec!` in non-Vec contexts
mesh/listener/dispatch.rs unused store_plain_message import
api/rpc/tor/mod.rs and mesh/steganography.rs: push-after-new → vec!
- Quiets wide legacy surfaces with crate-level allows in main.rs for
stylistic lints (too_many_arguments, type_complexity, doc indent,
enum variant prefix, wildcard-in-or, assertions-on-constants,
drop_non_drop, unused_io_amount, ptr_arg) — these fired in dozens
of places with no correctness payoff and have been churning every
toolchain bump.
- Tags intentional-dead-code helpers: wallet/ and streaming/ modules
are WIP, mesh::send_chunked_payload and DM_V1_MARKER are kept for
rollback compatibility, vpn::get_nostr_vpn_status is surface-area
for a not-yet-landed RPC.
cargo fmt --check, cargo clippy --all-targets --all-features
-- -D warnings, and cargo test --all-features now all pass locally.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 17:23:46 -04:00
|
|
|
AlertRuleKind::ContainerCrash => crate::data_model::NotificationLevel::Error,
|
2026-03-22 03:30:21 +00:00
|
|
|
_ => crate::data_model::NotificationLevel::Warning,
|
|
|
|
|
};
|
|
|
|
|
let notification = crate::data_model::Notification {
|
|
|
|
|
id: alert.id.clone(),
|
|
|
|
|
level,
|
|
|
|
|
title: format!("{:?} Alert", alert.kind),
|
|
|
|
|
message: alert.message.clone(),
|
|
|
|
|
timestamp: chrono::Utc::now().to_rfc3339(),
|
|
|
|
|
app_id: None,
|
|
|
|
|
};
|
|
|
|
|
data.notifications.push(notification);
|
|
|
|
|
}
|
|
|
|
|
// Keep max 20 notifications
|
|
|
|
|
while data.notifications.len() > 20 {
|
|
|
|
|
data.notifications.remove(0);
|
|
|
|
|
}
|
|
|
|
|
state_mgr.update_data(data).await;
|
|
|
|
|
info!("Fired {} alert(s)", alerts.len());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Deliver webhook notifications for alerts that map to webhook events.
|
|
|
|
|
pub(crate) async fn deliver_alert_webhooks(data_dir: &Path, alerts: &[FiredAlert]) {
|
|
|
|
|
for alert in alerts {
|
|
|
|
|
let event = match alert.kind {
|
|
|
|
|
AlertRuleKind::DiskUsage => Some(WebhookEvent::DiskWarning),
|
|
|
|
|
AlertRuleKind::ContainerCrash => Some(WebhookEvent::ContainerCrash),
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
|
|
|
|
if let Some(event) = event {
|
|
|
|
|
let payload = WebhookPayload {
|
|
|
|
|
event,
|
|
|
|
|
title: format!("{:?} Alert", alert.kind),
|
|
|
|
|
message: alert.message.clone(),
|
|
|
|
|
timestamp: chrono::Utc::now().to_rfc3339(),
|
|
|
|
|
node_id: String::new(),
|
|
|
|
|
details: Some(serde_json::json!({
|
|
|
|
|
"value": alert.value,
|
|
|
|
|
"threshold": alert.threshold,
|
|
|
|
|
})),
|
|
|
|
|
};
|
|
|
|
|
webhooks::send_webhook(data_dir, payload).await;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|