You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
7.9 KiB
Rust
248 lines
7.9 KiB
Rust
use std::fs;
|
|
use std::path::Path;
|
|
|
|
use console_subscriber::ConsoleLayer;
|
|
use opentelemetry::sdk::Resource;
|
|
use opentelemetry::{sdk, KeyValue};
|
|
use rolling_file::RollingConditionBasic;
|
|
use tracing::Level;
|
|
use tracing_appender::non_blocking::{NonBlocking, WorkerGuard};
|
|
use tracing_flame::FlameLayer;
|
|
use tracing_log::LogTracer;
|
|
use tracing_subscriber::filter::{self, Targets};
|
|
use tracing_subscriber::fmt::format::FmtSpan;
|
|
use tracing_subscriber::layer::SubscriberExt;
|
|
use tracing_subscriber::util::SubscriberInitExt;
|
|
use tracing_subscriber::{
|
|
fmt::{self},
|
|
Layer, Registry,
|
|
};
|
|
|
|
use mediarepo_core::settings::LoggingSettings;
|
|
use mediarepo_core::tracing_layer_list::DynLayerList;
|
|
|
|
#[allow(dyn_drop)]
|
|
pub type DropGuard = Box<dyn Drop>;
|
|
|
|
pub fn init_tracing(repo_path: &Path, log_cfg: &LoggingSettings) -> Vec<DropGuard> {
|
|
LogTracer::init().expect("failed to subscribe to log entries");
|
|
let log_path = repo_path.join("logs");
|
|
let mut guards = Vec::new();
|
|
let mut layer_list = DynLayerList::new();
|
|
|
|
if !log_path.exists() {
|
|
fs::create_dir(&log_path).expect("failed to create directory for log files");
|
|
}
|
|
|
|
add_stdout_layer(&mut guards, &mut layer_list);
|
|
add_sql_layer(log_cfg, &log_path, &mut guards, &mut layer_list);
|
|
add_bromine_layer(log_cfg, &log_path, &mut guards, &mut layer_list);
|
|
add_app_log_layer(log_cfg, &log_path, &mut guards, &mut layer_list);
|
|
|
|
if log_cfg.telemetry {
|
|
add_telemetry_layer(log_cfg, &mut layer_list);
|
|
}
|
|
|
|
let tokio_console_enabled = std::env::var("TOKIO_CONSOLE")
|
|
.map(|v| v.eq_ignore_ascii_case("true"))
|
|
.unwrap_or(false);
|
|
|
|
if tokio_console_enabled {
|
|
add_tokio_console_layer(&mut layer_list);
|
|
}
|
|
|
|
let registry = Registry::default().with(layer_list);
|
|
tracing::subscriber::set_global_default(registry).expect("Failed to initialize tracing");
|
|
|
|
guards
|
|
}
|
|
|
|
fn add_tokio_console_layer(layer_list: &mut DynLayerList<Registry>) {
|
|
let console_layer = ConsoleLayer::builder().with_default_env().spawn();
|
|
layer_list.add(console_layer);
|
|
}
|
|
|
|
fn add_telemetry_layer(log_cfg: &LoggingSettings, layer_list: &mut DynLayerList<Registry>) {
|
|
match opentelemetry_jaeger::new_pipeline()
|
|
.with_agent_endpoint(&log_cfg.telemetry_endpoint)
|
|
.with_trace_config(
|
|
sdk::trace::Config::default()
|
|
.with_resource(Resource::new(vec![KeyValue::new(
|
|
"service.name",
|
|
"mediarepo-daemon",
|
|
)]))
|
|
.with_max_attributes_per_span(1),
|
|
)
|
|
.with_instrumentation_library_tags(false)
|
|
.with_service_name("mediarepo-daemon")
|
|
.install_batch(opentelemetry::runtime::Tokio)
|
|
{
|
|
Ok(tracer) => {
|
|
let telemetry_layer = tracing_opentelemetry::layer()
|
|
.with_tracer(tracer)
|
|
.with_filter(
|
|
filter::Targets::new()
|
|
.with_target("tokio", Level::INFO)
|
|
.with_target("h2", Level::INFO)
|
|
.with_target("sqlx", Level::ERROR)
|
|
.with_target("sea_orm", Level::INFO),
|
|
);
|
|
layer_list.add(telemetry_layer);
|
|
}
|
|
Err(e) => {
|
|
eprintln!("Failed to initialize telemetry tracing: {}", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn add_app_log_layer(
|
|
log_cfg: &LoggingSettings,
|
|
log_path: &Path,
|
|
guards: &mut Vec<DropGuard>,
|
|
layer_list: &mut DynLayerList<Registry>,
|
|
) {
|
|
let (app_log_writer, guard) = get_application_log_writer(log_path);
|
|
guards.push(Box::new(guard) as DropGuard);
|
|
|
|
let app_log_layer = fmt::layer()
|
|
.with_writer(app_log_writer)
|
|
.pretty()
|
|
.with_ansi(false)
|
|
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
|
|
.with_filter(get_app_targets(log_cfg.level.clone().into()));
|
|
layer_list.add(app_log_layer);
|
|
}
|
|
|
|
fn add_bromine_layer(
|
|
log_cfg: &LoggingSettings,
|
|
log_path: &Path,
|
|
guards: &mut Vec<DropGuard>,
|
|
layer_list: &mut DynLayerList<Registry>,
|
|
) {
|
|
let (bromine_writer, guard) = get_bromine_log_writer(log_path);
|
|
guards.push(Box::new(guard) as DropGuard);
|
|
|
|
let bromine_layer = fmt::layer()
|
|
.with_writer(bromine_writer)
|
|
.pretty()
|
|
.with_ansi(false)
|
|
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
|
|
.with_filter(get_bromine_targets(log_cfg.trace_api_calls));
|
|
layer_list.add(bromine_layer);
|
|
}
|
|
|
|
fn add_sql_layer(
|
|
log_cfg: &LoggingSettings,
|
|
log_path: &Path,
|
|
guards: &mut Vec<DropGuard>,
|
|
layer_list: &mut DynLayerList<Registry>,
|
|
) {
|
|
let (sql_writer, guard) = get_sql_log_writer(log_path);
|
|
guards.push(Box::new(guard) as DropGuard);
|
|
|
|
let sql_layer = fmt::layer()
|
|
.with_writer(sql_writer)
|
|
.pretty()
|
|
.with_ansi(false)
|
|
.with_span_events(FmtSpan::NONE)
|
|
.with_filter(get_sql_targets(log_cfg.trace_sql));
|
|
|
|
layer_list.add(sql_layer);
|
|
}
|
|
|
|
fn add_stdout_layer(guards: &mut Vec<DropGuard>, layer_list: &mut DynLayerList<Registry>) {
|
|
let (stdout_writer, guard) = tracing_appender::non_blocking(std::io::stdout());
|
|
guards.push(Box::new(guard) as DropGuard);
|
|
|
|
let stdout_layer = fmt::layer()
|
|
.with_thread_names(false)
|
|
.with_target(true)
|
|
.with_writer(stdout_writer)
|
|
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
|
|
.with_filter(
|
|
std::env::var("RUST_LOG")
|
|
.unwrap_or_else(|_| String::from("info,sqlx=warn"))
|
|
.parse::<filter::Targets>()
|
|
.unwrap_or_else(|_| {
|
|
filter::Targets::new()
|
|
.with_default(Level::INFO)
|
|
.with_target("sqlx", Level::WARN)
|
|
}),
|
|
);
|
|
layer_list.add(stdout_layer);
|
|
}
|
|
|
|
fn get_sql_log_writer(log_path: &Path) -> (NonBlocking, WorkerGuard) {
|
|
tracing_appender::non_blocking(
|
|
rolling_file::BasicRollingFileAppender::new(
|
|
log_path.join("sql.log"),
|
|
RollingConditionBasic::new().max_size(1024 * 1024),
|
|
3,
|
|
)
|
|
.expect("failed to create sql log file"),
|
|
)
|
|
}
|
|
|
|
fn get_bromine_log_writer(log_path: &Path) -> (NonBlocking, WorkerGuard) {
|
|
tracing_appender::non_blocking(
|
|
rolling_file::BasicRollingFileAppender::new(
|
|
log_path.join("bromine.log"),
|
|
RollingConditionBasic::new().max_size(1024 * 1024 * 10),
|
|
2,
|
|
)
|
|
.expect("failed to create bromine log file"),
|
|
)
|
|
}
|
|
|
|
fn get_application_log_writer(log_path: &Path) -> (NonBlocking, WorkerGuard) {
|
|
tracing_appender::non_blocking(
|
|
rolling_file::BasicRollingFileAppender::new(
|
|
log_path.join("repo.log"),
|
|
RollingConditionBasic::new().max_size(1024 * 1024 * 10),
|
|
3,
|
|
)
|
|
.expect("failed to create repo log file"),
|
|
)
|
|
}
|
|
|
|
fn get_app_targets(level: Option<Level>) -> Targets {
|
|
filter::Targets::new()
|
|
.with_target("bromine", Level::WARN)
|
|
.with_target("sqlx", Level::WARN)
|
|
.with_target("sea_orm", Level::WARN)
|
|
.with_target("tokio", Level::WARN)
|
|
.with_target("console_subscriber", Level::ERROR)
|
|
.with_target("h2", Level::WARN)
|
|
.with_default(level)
|
|
}
|
|
|
|
fn get_sql_targets(trace_sql: bool) -> Targets {
|
|
if trace_sql {
|
|
filter::Targets::new()
|
|
.with_target("sqlx", Level::WARN)
|
|
.with_target("sea_orm", Level::TRACE)
|
|
.with_target("mediarepo_database", Level::TRACE)
|
|
} else {
|
|
filter::Targets::new().with_default(None)
|
|
}
|
|
}
|
|
|
|
fn get_bromine_targets(trace_bromine: bool) -> Targets {
|
|
if trace_bromine {
|
|
filter::Targets::new().with_target("bromine", Level::DEBUG)
|
|
} else {
|
|
filter::Targets::new().with_default(None)
|
|
}
|
|
}
|
|
|
|
pub fn init_tracing_flame() -> DropGuard {
|
|
let fmt_layer = fmt::Layer::default();
|
|
let (flame_layer, guard) = FlameLayer::with_file("./tracing.folded").unwrap();
|
|
tracing_subscriber::registry()
|
|
.with(fmt_layer)
|
|
.with(flame_layer)
|
|
.init();
|
|
|
|
Box::new(guard)
|
|
}
|