use opentelemetry::KeyValue;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::trace::{self, Sampler};
use opentelemetry_sdk::Resource;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry};
use ferrox_errors::AppError;
pub mod sanitizer;
pub mod dp;
pub mod weekly_report;
pub mod merkle;
pub mod merkle_audit_chain;
pub use merkle_audit_chain::{AuditLogRecord, MerkleAuditChain};
#[derive(Clone, serde::Deserialize)]
pub struct LoggerConfig {
pub service_name: String,
pub environment: String,
pub otlp_endpoint: Option<String>,
pub sentry_dsn: Option<String>,
pub log_level: String,
}
impl Default for LoggerConfig {
fn default() -> Self {
Self {
service_name: "ferrox-app".to_string(),
environment: "development".to_string(),
otlp_endpoint: None,
sentry_dsn: None,
log_level: "info".to_string(),
}
}
}
pub fn setup_logger(config: LoggerConfig) -> Result<Option<sentry::ClientInitGuard>, AppError> {
let env_filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new(&config.log_level));
let formatting_layer = tracing_subscriber::fmt::layer()
.json()
.with_file(true)
.with_line_number(true)
.with_target(false);
let subscriber = Registry::default().with(env_filter).with(formatting_layer);
let mut sentry_guard = None;
if let Some(dsn) = config.sentry_dsn {
sentry_guard = Some(sentry::init((
dsn,
sentry::ClientOptions {
release: sentry::release_name!(),
traces_sample_rate: 1.0,
environment: Some(config.environment.into()),
..Default::default()
},
)));
}
let _ = subscriber.try_init();
tracing::info!("ferrox-logger initialized: Structured JSON logging enabled for service '{}'.", config.service_name);
Ok(sentry_guard)
}