use std::{fmt, time::Duration};
mod alert;
pub mod canopy;
pub mod commands;
mod daemon;
mod events;
mod glob_resolver;
pub mod http_server;
mod loader;
mod metrics;
pub mod scheduler;
pub mod state_file;
mod targets;
pub mod templates;
#[cfg(windows)]
pub mod windows_service;
pub use alert::{AlertDefinition, AlwaysSend, InternalContext, TicketSource, WhenChanged};
pub use daemon::{run, run_with_shutdown, run_with_shutdown_and_reload};
pub use events::EventType;
pub use targets::{
AlertTargets, ExternalTarget, ResolvedTarget, SendTarget, TargetConnection, TargetEmail,
};
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
#[derive(Debug, Clone)]
pub struct EmailConfig {
pub from: String,
pub mailgun_api_key: String,
pub mailgun_domain: String,
}
#[derive(Clone)]
pub struct DaemonConfig {
pub alert_globs: Vec<String>,
pub database_url: String,
pub email: Option<EmailConfig>,
pub device_key_pem: Option<Redacted<String>>,
pub dry_run: bool,
pub no_server: bool,
pub server_addrs: Vec<std::net::SocketAddr>,
pub watchdog_timeout: Option<Duration>,
}
impl fmt::Debug for DaemonConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("DaemonConfig")
.field("alert_globs", &self.alert_globs)
.field("database_url", &self.database_url)
.field("email", &self.email)
.field("device_key_pem", &self.device_key_pem)
.field("dry_run", &self.dry_run)
.field("no_server", &self.no_server)
.field("server_addrs", &self.server_addrs)
.field("watchdog_timeout", &self.watchdog_timeout)
.finish()
}
}
#[derive(Clone)]
pub struct Redacted<T>(pub T);
impl<T> fmt::Debug for Redacted<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("<redacted>")
}
}
impl<T> std::ops::Deref for Redacted<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl DaemonConfig {
pub fn new(alert_globs: Vec<String>, database_url: String) -> Self {
Self {
alert_globs,
database_url,
email: None,
device_key_pem: None,
dry_run: false,
no_server: false,
server_addrs: Vec::new(),
watchdog_timeout: Some(Duration::from_secs(10 * 60)),
}
}
pub fn with_email(mut self, email: EmailConfig) -> Self {
self.email = Some(email);
self
}
pub fn with_device_key_pem(mut self, pem: String) -> Self {
self.device_key_pem = Some(Redacted(pem));
self
}
pub fn with_dry_run(mut self, dry_run: bool) -> Self {
self.dry_run = dry_run;
self
}
pub fn with_no_server(mut self, no_server: bool) -> Self {
self.no_server = no_server;
self
}
pub fn with_server_addrs(mut self, server_addrs: Vec<std::net::SocketAddr>) -> Self {
self.server_addrs = server_addrs;
self
}
pub fn with_watchdog_timeout(mut self, watchdog_timeout: Option<Duration>) -> Self {
self.watchdog_timeout = watchdog_timeout;
self
}
}
pub(crate) struct LogError<'a>(pub &'a miette::Report);
impl fmt::Display for LogError<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use miette::ReportHandler;
let handler = miette::NarratableReportHandler::new();
if let Err(e) = handler.debug(self.0.as_ref(), f) {
write!(f, "{}: {}", self.0, e)
} else {
Ok(())
}
}
}