enable conf serde and test the toml format with our current schema
This commit is contained in:
Generated
+54
-2
@@ -185,6 +185,7 @@ checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"phf",
|
"phf",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1284,7 +1285,7 @@ version = "3.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
|
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"toml_edit",
|
"toml_edit 0.23.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1614,6 +1615,15 @@ dependencies = [
|
|||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@@ -1687,6 +1697,7 @@ dependencies = [
|
|||||||
"syslog_rfc5424",
|
"syslog_rfc5424",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
@@ -1927,6 +1938,27 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime 0.6.11",
|
||||||
|
"toml_edit 0.22.27",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
@@ -1936,6 +1968,20 @@ dependencies = [
|
|||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime 0.6.11",
|
||||||
|
"toml_write",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.23.7"
|
version = "0.23.7"
|
||||||
@@ -1943,7 +1989,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d"
|
checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"toml_datetime",
|
"toml_datetime 0.7.3",
|
||||||
"toml_parser",
|
"toml_parser",
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
@@ -1957,6 +2003,12 @@ dependencies = [
|
|||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_write"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
|
|||||||
+3
-2
@@ -26,8 +26,8 @@ prometheus-http-client = { path = "prometheus-http-client", default-features = f
|
|||||||
|
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
chrono = { version = "0.4", default-features = false, features = ["clock", "serde", "std"] }
|
chrono = { version = "0.4", default-features = false, features = ["clock", "serde", "std"] }
|
||||||
chrono-tz = "0.10"
|
chrono-tz = { version = "0.10", features = ["serde"] }
|
||||||
conf = "0.4"
|
conf = { version = "0.4", features = ["serde"] }
|
||||||
conf-extra = "0.1"
|
conf-extra = "0.1"
|
||||||
displaydoc = "0.2"
|
displaydoc = "0.2"
|
||||||
dotenvy = "0.15"
|
dotenvy = "0.15"
|
||||||
@@ -46,6 +46,7 @@ serde = { version = "1", features = ["derive"] }
|
|||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
syslog_rfc5424 = "0.10"
|
syslog_rfc5424 = "0.10"
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
|
toml = "0.8"
|
||||||
tokio = { version = "1", features = ["macros", "net", "sync", "time"] }
|
tokio = { version = "1", features = ["macros", "net", "sync", "time"] }
|
||||||
tokio-util = { version = "0.7", features = ["codec"] }
|
tokio-util = { version = "0.7", features = ["codec"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
|||||||
@@ -33,3 +33,6 @@ tokio = { workspace = true, features = ["rt-multi-thread", "signal"] }
|
|||||||
tokio-util = { workspace = true }
|
tokio-util = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
toml = { workspace = true }
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
/// Configuration for the admin HTTP client
|
/// Configuration for the admin HTTP client
|
||||||
#[derive(Clone, Conf, Debug)]
|
#[derive(Clone, Conf, Debug)]
|
||||||
|
#[conf(serde)]
|
||||||
pub struct AdminHttpConfig {
|
pub struct AdminHttpConfig {
|
||||||
/// URL to POST admin commands to
|
/// URL to POST admin commands to
|
||||||
#[conf(long, env)]
|
#[conf(long, env)]
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use tokio::{
|
|||||||
|
|
||||||
/// Configuration for the admin netcat TCP client
|
/// Configuration for the admin netcat TCP client
|
||||||
#[derive(Clone, Conf, Debug)]
|
#[derive(Clone, Conf, Debug)]
|
||||||
|
#[conf(serde)]
|
||||||
pub struct AdminNetcatConfig {
|
pub struct AdminNetcatConfig {
|
||||||
/// TCP address to forward admin commands to
|
/// TCP address to forward admin commands to
|
||||||
#[conf(long, env)]
|
#[conf(long, env)]
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ use json_lines::read_json_lines_value;
|
|||||||
///
|
///
|
||||||
/// See [`JsonLogMessage`] for the JSON schema.
|
/// See [`JsonLogMessage`] for the JSON schema.
|
||||||
#[derive(Clone, Conf, Debug)]
|
#[derive(Clone, Conf, Debug)]
|
||||||
|
#[conf(serde)]
|
||||||
pub struct JsonConfig {
|
pub struct JsonConfig {
|
||||||
/// Socket address to listen for JSON log messages.
|
/// Socket address to listen for JSON log messages.
|
||||||
/// Both UDP and TCP listeners are started on this address.
|
/// Both UDP and TCP listeners are started on this address.
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ use json::JsonConfig;
|
|||||||
|
|
||||||
/// Admin message handler configuration - select how non-command messages are handled
|
/// Admin message handler configuration - select how non-command messages are handled
|
||||||
#[derive(Clone, Debug, Subcommands)]
|
#[derive(Clone, Debug, Subcommands)]
|
||||||
|
#[conf(serde)]
|
||||||
enum AdminHandlerCommand {
|
enum AdminHandlerCommand {
|
||||||
/// Forward (unhandled) admin messages to a TCP endpoint (netcat-style)
|
/// Forward (unhandled) admin messages to a TCP endpoint (netcat-style)
|
||||||
/// Useful if an http server would be heavy in the target process
|
/// Useful if an http server would be heavy in the target process
|
||||||
@@ -45,8 +46,10 @@ impl AdminHandlerCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Top-level configuration for signal-gateway.
|
||||||
#[derive(Conf, Debug)]
|
#[derive(Conf, Debug)]
|
||||||
struct Config {
|
#[conf(serde)]
|
||||||
|
pub struct Config {
|
||||||
/// If true, just validate config and don't start
|
/// If true, just validate config and don't start
|
||||||
#[conf(long)]
|
#[conf(long)]
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
@@ -60,7 +63,7 @@ struct Config {
|
|||||||
/// Optional admin message handler (netcat or http)
|
/// Optional admin message handler (netcat or http)
|
||||||
#[conf(subcommands)]
|
#[conf(subcommands)]
|
||||||
admin_handler: Option<AdminHandlerCommand>,
|
admin_handler: Option<AdminHandlerCommand>,
|
||||||
#[conf(flatten)]
|
#[conf(flatten, serde(flatten))]
|
||||||
gateway: GatewayConfig,
|
gateway: GatewayConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,3 +176,84 @@ fn start_http_task(listener: TcpListener, gateway: Arc<Gateway>) -> tokio::task:
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use conf::Conf;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_toml_config() {
|
||||||
|
let toml_config = r#"
|
||||||
|
http_listen_addr = "0.0.0.0:8080"
|
||||||
|
signal_account = "+15551234567"
|
||||||
|
signal_cli_tcp_addr = "127.0.0.1:7583"
|
||||||
|
signal_cli_retry_delay = "10s"
|
||||||
|
|
||||||
|
[admin_safety_numbers]
|
||||||
|
"abc-123-uuid" = ["12345 67890 12345 67890 12345 67890"]
|
||||||
|
"def-456-uuid" = []
|
||||||
|
|
||||||
|
[syslog]
|
||||||
|
listen_addr = "0.0.0.0:1514"
|
||||||
|
sd_id = "tracing-meta@64700"
|
||||||
|
|
||||||
|
[json]
|
||||||
|
listen_addr = "0.0.0.0:5000"
|
||||||
|
|
||||||
|
[log_handler]
|
||||||
|
log_buffer_size = 128
|
||||||
|
overall_limits = [{ threshold = ">= 100 / 1h" }]
|
||||||
|
|
||||||
|
[[log_handler.route]]
|
||||||
|
alert_level = "warn"
|
||||||
|
msg_contains = "critical"
|
||||||
|
|
||||||
|
[[log_handler.route]]
|
||||||
|
alert_level = "error"
|
||||||
|
|
||||||
|
[[log_handler.route]]
|
||||||
|
msg_contains = "connection reset"
|
||||||
|
limits = [
|
||||||
|
{ threshold = ">= 5 / 1m" },
|
||||||
|
{ threshold = ">= 20 / 1h" },
|
||||||
|
]
|
||||||
|
"#;
|
||||||
|
|
||||||
|
// Parse TOML to a generic value, then use conf's builder to parse it
|
||||||
|
let doc: toml::Value = toml::from_str(toml_config).expect("Failed to parse TOML");
|
||||||
|
let empty_env: [(&str, &str); 0] = [];
|
||||||
|
let config: Config = Config::conf_builder()
|
||||||
|
.args(["."])
|
||||||
|
.env(empty_env)
|
||||||
|
.doc("test.toml", doc)
|
||||||
|
.try_parse()
|
||||||
|
.expect("Failed to parse config");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
config.http_listen_addr,
|
||||||
|
"0.0.0.0:8080".parse().unwrap()
|
||||||
|
);
|
||||||
|
assert_eq!(config.gateway.signal_account, "+15551234567");
|
||||||
|
assert_eq!(
|
||||||
|
config.gateway.signal_cli_tcp_addr,
|
||||||
|
Some("127.0.0.1:7583".parse().unwrap())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
config.gateway.signal_cli_retry_delay,
|
||||||
|
Duration::from_secs(10)
|
||||||
|
);
|
||||||
|
assert_eq!(config.gateway.admin_safety_numbers.len(), 2);
|
||||||
|
assert!(config.gateway.admin_safety_numbers.contains_key("abc-123-uuid"));
|
||||||
|
|
||||||
|
let syslog = config.syslog.expect("syslog should be present");
|
||||||
|
assert_eq!(syslog.listen_addr, "0.0.0.0:1514".parse().unwrap());
|
||||||
|
|
||||||
|
let json = config.json.expect("json should be present");
|
||||||
|
assert_eq!(json.listen_addr, "0.0.0.0:5000".parse().unwrap());
|
||||||
|
|
||||||
|
assert_eq!(config.gateway.log_handler.log_buffer_size, 128);
|
||||||
|
assert_eq!(config.gateway.log_handler.routes.len(), 3);
|
||||||
|
assert_eq!(config.gateway.log_handler.overall_limits.len(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use tracing::{error, info, trace};
|
|||||||
|
|
||||||
/// Configuration for the syslog listener (supports both UDP and TCP).
|
/// Configuration for the syslog listener (supports both UDP and TCP).
|
||||||
#[derive(Clone, Conf, Debug)]
|
#[derive(Clone, Conf, Debug)]
|
||||||
|
#[conf(serde)]
|
||||||
pub struct SyslogConfig {
|
pub struct SyslogConfig {
|
||||||
/// Socket address to listen for syslog messages.
|
/// Socket address to listen for syslog messages.
|
||||||
/// Both UDP and TCP listeners are started on this address.
|
/// Both UDP and TCP listeners are started on this address.
|
||||||
|
|||||||
@@ -153,12 +153,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> std::fmt::Debug for LazyMap<K, V> {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_struct("LazyMap").finish_non_exhaustive()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -49,9 +49,10 @@ impl fmt::Display for SuppressionReason {
|
|||||||
|
|
||||||
/// Config options related to the log handler, and what log messages it chooses to alert on.
|
/// Config options related to the log handler, and what log messages it chooses to alert on.
|
||||||
#[derive(Clone, Conf, Debug)]
|
#[derive(Clone, Conf, Debug)]
|
||||||
|
#[conf(serde)]
|
||||||
pub struct LogHandlerConfig {
|
pub struct LogHandlerConfig {
|
||||||
/// Routes for matching and rate-limiting log messages.
|
/// Routes for matching and rate-limiting log messages.
|
||||||
#[conf(long, env, value_parser = serde_json::from_str, default_value = "[]")]
|
#[conf(long, env, value_parser = serde_json::from_str, default_value = "[]", serde(alias = "route"))]
|
||||||
pub routes: Vec<Route>,
|
pub routes: Vec<Route>,
|
||||||
/// Overall rate limits applied after route checks pass.
|
/// Overall rate limits applied after route checks pass.
|
||||||
#[conf(long, env, value_parser = serde_json::from_str, default_value = "[]")]
|
#[conf(long, env, value_parser = serde_json::from_str, default_value = "[]")]
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ pub use crate::rate_limiter::{Limiter, RateThreshold};
|
|||||||
|
|
||||||
/// Configuration for the gateway.
|
/// Configuration for the gateway.
|
||||||
#[derive(Conf, Debug)]
|
#[derive(Conf, Debug)]
|
||||||
|
#[conf(serde)]
|
||||||
#[cfg_attr(unix, conf(one_of_fields(signal_cli_tcp_addr, signal_cli_socket_path)))]
|
#[cfg_attr(unix, conf(one_of_fields(signal_cli_tcp_addr, signal_cli_socket_path)))]
|
||||||
#[cfg_attr(not(unix), conf(one_of_fields(signal_cli_tcp_addr)))]
|
#[cfg_attr(not(unix), conf(one_of_fields(signal_cli_tcp_addr)))]
|
||||||
pub struct GatewayConfig {
|
pub struct GatewayConfig {
|
||||||
@@ -62,6 +63,9 @@ pub struct GatewayConfig {
|
|||||||
/// The phone number or UUID of the Signal account to use.
|
/// The phone number or UUID of the Signal account to use.
|
||||||
#[conf(long, env)]
|
#[conf(long, env)]
|
||||||
pub signal_account: String,
|
pub signal_account: String,
|
||||||
|
/// Delay before retrying connection to signal-cli after an error.
|
||||||
|
#[conf(long, env, default_value = "5s", value_parser = conf_extra::parse_duration, serde(use_value_parser))]
|
||||||
|
pub signal_cli_retry_delay: Duration,
|
||||||
/// Admin UUIDs mapped to their safety numbers (can be empty).
|
/// Admin UUIDs mapped to their safety numbers (can be empty).
|
||||||
/// Example: `{"uuid1": ["12345...", "67890..."], "uuid2": []}`
|
/// Example: `{"uuid1": ["12345...", "67890..."], "uuid2": []}`
|
||||||
#[conf(long, env, value_parser = serde_json::from_str)]
|
#[conf(long, env, value_parser = serde_json::from_str)]
|
||||||
@@ -279,7 +283,7 @@ impl Gateway {
|
|||||||
|
|
||||||
if let Err(err) = self.connect_and_run(&mut alert_rx).await {
|
if let Err(err) = self.connect_and_run(&mut alert_rx).await {
|
||||||
error!("Error with signal-cli, reconnecting: {err}");
|
error!("Error with signal-cli, reconnecting: {err}");
|
||||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
tokio::time::sleep(self.config.signal_cli_retry_delay).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ pub struct Route {
|
|||||||
|
|
||||||
/// Rate limits applied per-origin for messages matching this route.
|
/// Rate limits applied per-origin for messages matching this route.
|
||||||
/// Each limit specifies a filter and threshold for suppressing repeated alerts.
|
/// Each limit specifies a filter and threshold for suppressing repeated alerts.
|
||||||
#[serde(default)]
|
#[serde(default, alias = "limit")]
|
||||||
pub limit: Vec<Limit>,
|
pub limits: Vec<Limit>,
|
||||||
|
|
||||||
/// Global rate limits applied across all origins for this route.
|
/// Global rate limits applied across all origins for this route.
|
||||||
/// Each limit specifies a filter and threshold for suppressing repeated alerts.
|
/// Each limit specifies a filter and threshold for suppressing repeated alerts.
|
||||||
#[serde(default)]
|
#[serde(default, alias = "global_limit")]
|
||||||
pub global_limit: Vec<Limit>,
|
pub global_limits: Vec<Limit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_alert_level() -> Level {
|
fn default_alert_level() -> Level {
|
||||||
@@ -80,8 +80,8 @@ fn default_alert_level() -> Level {
|
|||||||
impl Route {
|
impl Route {
|
||||||
/// Create a limiter set from this route's limit configurations.
|
/// Create a limiter set from this route's limit configurations.
|
||||||
pub fn make_limiter_set(&self) -> LimiterSet {
|
pub fn make_limiter_set(&self) -> LimiterSet {
|
||||||
let limits = self.limit.clone();
|
let limits = self.limits.clone();
|
||||||
let global_limiters = self.global_limit.iter().map(|l| l.make_limiter()).collect();
|
let global_limiters = self.global_limits.iter().map(|l| l.make_limiter()).collect();
|
||||||
LimiterSet::new(
|
LimiterSet::new(
|
||||||
move || limits.iter().map(|l| l.make_limiter()).collect(),
|
move || limits.iter().map(|l| l.make_limiter()).collect(),
|
||||||
global_limiters,
|
global_limiters,
|
||||||
@@ -95,8 +95,8 @@ impl Default for Route {
|
|||||||
alert_level: default_alert_level(),
|
alert_level: default_alert_level(),
|
||||||
filter: LogFilter::default(),
|
filter: LogFilter::default(),
|
||||||
destination: None,
|
destination: None,
|
||||||
limit: Vec::new(),
|
limits: Vec::new(),
|
||||||
global_limit: Vec::new(),
|
global_limits: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use tracing::error;
|
|||||||
|
|
||||||
/// Configuration for log message formatting.
|
/// Configuration for log message formatting.
|
||||||
#[derive(Clone, Conf, Debug, Default)]
|
#[derive(Clone, Conf, Debug, Default)]
|
||||||
|
#[conf(serde)]
|
||||||
pub struct LogFormatConfig {
|
pub struct LogFormatConfig {
|
||||||
/// Include the module path in formatted output.
|
/// Include the module path in formatted output.
|
||||||
#[conf(long, env)]
|
#[conf(long, env)]
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ use std::{path::PathBuf, str::FromStr, time::Duration};
|
|||||||
|
|
||||||
/// Configures our prometheus API client
|
/// Configures our prometheus API client
|
||||||
#[derive(Clone, Conf, Debug)]
|
#[derive(Clone, Conf, Debug)]
|
||||||
|
#[conf(serde)]
|
||||||
pub struct PrometheusConfig {
|
pub struct PrometheusConfig {
|
||||||
/// Address of prometheus host. Should start with http and usually indicate port 9090
|
/// Address of prometheus host. Should start with http and usually indicate port 9090
|
||||||
#[conf(long, env)]
|
#[conf(long, env)]
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ pub use prometheus_http_client::{
|
|||||||
|
|
||||||
/// Configuration for plots generated from prometheus data
|
/// Configuration for plots generated from prometheus data
|
||||||
#[derive(Clone, Conf, Debug)]
|
#[derive(Clone, Conf, Debug)]
|
||||||
#[conf(at_most_one_of_fields(utc_offset, timezone))]
|
#[conf(serde, at_most_one_of_fields(utc_offset, timezone))]
|
||||||
pub struct PlotConfig {
|
pub struct PlotConfig {
|
||||||
/// Working directory for temporary plot files
|
/// Working directory for temporary plot files
|
||||||
#[conf(long, env, default_value = "/tmp")]
|
#[conf(long, env, default_value = "/tmp")]
|
||||||
@@ -24,11 +24,11 @@ pub struct PlotConfig {
|
|||||||
age_limit: Duration,
|
age_limit: Duration,
|
||||||
/// Fixed timezone offset for plot timestamps, e.g. "+05:30" or "-08:00".
|
/// Fixed timezone offset for plot timestamps, e.g. "+05:30" or "-08:00".
|
||||||
/// Mutually exclusive with --timezone.
|
/// Mutually exclusive with --timezone.
|
||||||
#[conf(long, env)]
|
#[conf(long, env, serde(use_value_parser))]
|
||||||
utc_offset: Option<FixedOffset>,
|
utc_offset: Option<FixedOffset>,
|
||||||
/// Timezone name for plot timestamps, e.g. "US/Mountain" or "Europe/Paris".
|
/// Timezone name for plot timestamps, e.g. "US/Mountain" or "Europe/Paris".
|
||||||
/// Mutually exclusive with --utc-offset.
|
/// Mutually exclusive with --utc-offset.
|
||||||
#[conf(long, env)]
|
#[conf(long, env, serde(use_value_parser))]
|
||||||
timezone: Option<Tz>,
|
timezone: Option<Tz>,
|
||||||
/// Stroke width for plot lines
|
/// Stroke width for plot lines
|
||||||
#[conf(long, env, default_value = "2")]
|
#[conf(long, env, default_value = "2")]
|
||||||
|
|||||||
Reference in New Issue
Block a user