Establish config loading and logging infrastructure
First working milestone of the Rust rewrite. Implements the two foundational systems every other component depends on: - TOML-based layered config (beds.toml + env.toml override) replacing the PHP XML config system, fully deserialized into typed structs via serde — no runtime string key lookups, shape enforced at compile time - Structured logging via tracing + tracing-journald, with optional console mirror, initialized from config before any services start Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
19
src/config/mod.rs
Normal file
19
src/config/mod.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
mod structs;
|
||||
pub use structs::BedsConfig;
|
||||
|
||||
use config::{Config, File, FileFormat};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ConfigError {
|
||||
#[error("Failed to load configuration: {0}")]
|
||||
LoadError(#[from] config::ConfigError),
|
||||
}
|
||||
|
||||
pub fn load() -> Result<BedsConfig, ConfigError> {
|
||||
let cfg = Config::builder()
|
||||
.add_source(File::new("config/beds.toml", FileFormat::Toml))
|
||||
.add_source(File::new("config/env.toml", FileFormat::Toml).required(false))
|
||||
.build()?;
|
||||
|
||||
Ok(cfg.try_deserialize()?)
|
||||
}
|
||||
50
src/config/structs.rs
Normal file
50
src/config/structs.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BedsConfig {
|
||||
pub id: IdConfig,
|
||||
pub debug: bool,
|
||||
pub syslog: bool,
|
||||
pub syslog_mirror_console: bool,
|
||||
pub audit_on: bool,
|
||||
pub journal_on: bool,
|
||||
pub broker_services: BrokerServicesConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct IdConfig {
|
||||
pub env_name: String,
|
||||
pub version: String,
|
||||
pub wbid: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BrokerServicesConfig {
|
||||
pub queue_tag : String,
|
||||
pub vhost: String,
|
||||
pub timer_violation: u32,
|
||||
pub records_per_xfer: u32,
|
||||
pub keepalive: bool,
|
||||
pub heartbeat: u32,
|
||||
pub use_ssl: bool,
|
||||
pub cert_path: String,
|
||||
pub app_server: BrokerNodeConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BrokerNodeConfig {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
pub api_port: Option<u16>,
|
||||
pub user: String,
|
||||
pub pass: String,
|
||||
pub rpi: u32,
|
||||
pub instances: BrokerInstancesConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BrokerInstancesConfig {
|
||||
pub r_broker: u32,
|
||||
pub w_broker: u32,
|
||||
pub m_broker: u32,
|
||||
}
|
||||
26
src/logging.rs
Normal file
26
src/logging.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||
|
||||
pub fn init_from_config(syslog: bool, mirror_console: bool) {
|
||||
let registry = tracing_subscriber::registry()
|
||||
.with(EnvFilter::try_from_default_env()
|
||||
.unwrap_or_else(|_| EnvFilter::new("info")));
|
||||
|
||||
let journald_layer = if syslog {
|
||||
tracing_journald::layer().ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let console_layer = if !syslog || mirror_console {
|
||||
Some(tracing_subscriber::fmt::layer()
|
||||
.with_target(false)
|
||||
.compact())
|
||||
}else {
|
||||
None
|
||||
};
|
||||
|
||||
registry
|
||||
.with(journald_layer)
|
||||
.with(console_layer)
|
||||
.init();
|
||||
}
|
||||
@@ -1,3 +1,10 @@
|
||||
mod config;
|
||||
mod logging;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
let cfg = config::load().expect("Failed to load config");
|
||||
|
||||
logging::init_from_config(cfg.syslog, cfg.syslog_mirror_console);
|
||||
tracing::info!("BEDS starting, env={}", cfg.id.env_name);
|
||||
tracing::info!("Logging initialized");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user