120 lines
3.5 KiB
Rust
120 lines
3.5 KiB
Rust
use crate::service::SensorService;
|
|
use anyhow::Result;
|
|
use attune_common::config::{Config, SensorConfig};
|
|
use tokio::signal::unix::{signal, SignalKind};
|
|
use tracing::{error, info};
|
|
|
|
pub fn init_tracing(log_level: tracing::Level) {
|
|
tracing_subscriber::fmt()
|
|
.with_max_level(log_level)
|
|
.with_target(false)
|
|
.with_thread_ids(true)
|
|
.with_file(true)
|
|
.with_line_number(true)
|
|
.init();
|
|
}
|
|
|
|
pub fn set_config_path(config_path: Option<&str>) {
|
|
if let Some(config_path) = config_path {
|
|
info!("Loading configuration from: {}", config_path);
|
|
std::env::set_var("ATTUNE_CONFIG", config_path);
|
|
}
|
|
}
|
|
|
|
pub fn apply_sensor_name_override(config: &mut Config, name: String) {
|
|
if let Some(ref mut sensor_config) = config.sensor {
|
|
sensor_config.worker_name = Some(name);
|
|
} else {
|
|
config.sensor = Some(SensorConfig {
|
|
worker_name: Some(name),
|
|
host: None,
|
|
capabilities: None,
|
|
max_concurrent_sensors: None,
|
|
heartbeat_interval: 30,
|
|
poll_interval: 30,
|
|
sensor_timeout: 30,
|
|
shutdown_timeout: 30,
|
|
});
|
|
}
|
|
}
|
|
|
|
pub fn log_config_details(config: &Config) {
|
|
info!("Configuration loaded successfully");
|
|
info!("Environment: {}", config.environment);
|
|
info!("Database: {}", mask_connection_string(&config.database.url));
|
|
if let Some(ref mq_config) = config.message_queue {
|
|
info!("Message Queue: {}", mask_connection_string(&mq_config.url));
|
|
}
|
|
}
|
|
|
|
pub async fn run_sensor_service(config: Config, ready_message: &str) -> Result<()> {
|
|
let service = SensorService::new(config).await?;
|
|
|
|
info!("Sensor Service initialized successfully");
|
|
info!("Starting Sensor Service components...");
|
|
service.start().await?;
|
|
info!("{}", ready_message);
|
|
|
|
let mut sigint = signal(SignalKind::interrupt())?;
|
|
let mut sigterm = signal(SignalKind::terminate())?;
|
|
|
|
tokio::select! {
|
|
_ = sigint.recv() => {
|
|
info!("Received SIGINT signal");
|
|
}
|
|
_ = sigterm.recv() => {
|
|
info!("Received SIGTERM signal");
|
|
}
|
|
}
|
|
|
|
info!("Shutting down gracefully...");
|
|
|
|
if let Err(e) = service.stop().await {
|
|
error!("Error during shutdown: {}", e);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Mask sensitive parts of connection strings for logging.
|
|
pub fn mask_connection_string(url: &str) -> String {
|
|
if let Some(at_pos) = url.find('@') {
|
|
if let Some(proto_end) = url.find("://") {
|
|
let protocol = &url[..proto_end + 3];
|
|
let host_and_path = &url[at_pos..];
|
|
return format!("{}***:***{}", protocol, host_and_path);
|
|
}
|
|
}
|
|
"***:***@***".to_string()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_mask_connection_string() {
|
|
let url = "postgresql://user:password@localhost:5432/attune";
|
|
let masked = mask_connection_string(url);
|
|
assert!(!masked.contains("user"));
|
|
assert!(!masked.contains("password"));
|
|
assert!(masked.contains("@localhost"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_mask_connection_string_no_credentials() {
|
|
let url = "postgresql://localhost:5432/attune";
|
|
let masked = mask_connection_string(url);
|
|
assert_eq!(masked, "***:***@***");
|
|
}
|
|
|
|
#[test]
|
|
fn test_mask_rabbitmq_connection() {
|
|
let url = "amqp://admin:secret@rabbitmq:5672/%2F";
|
|
let masked = mask_connection_string(url);
|
|
assert!(!masked.contains("admin"));
|
|
assert!(!masked.contains("secret"));
|
|
assert!(masked.contains("@rabbitmq"));
|
|
}
|
|
}
|