capnweb_server/
logging.rs

1use std::path::Path;
2use tracing_appender::rolling::{RollingFileAppender, Rotation};
3use tracing_subscriber::{
4    fmt::{self, time::ChronoUtc},
5    prelude::*,
6    EnvFilter,
7};
8
9/// Initialize logging with file output and console output
10pub fn init_logging(log_dir: impl AsRef<Path>, log_prefix: &str) -> anyhow::Result<()> {
11    let log_dir_path = log_dir.as_ref();
12
13    // Create log directory if it doesn't exist
14    std::fs::create_dir_all(log_dir_path)?;
15
16    // Create rolling file appender (daily rotation)
17    let file_appender = RollingFileAppender::builder()
18        .rotation(Rotation::DAILY)
19        .filename_prefix(log_prefix)
20        .build(log_dir_path)?;
21
22    // Create non-blocking writer for file output
23    let (file_writer, _guard) = tracing_appender::non_blocking(file_appender);
24
25    // Set up environment filter with sensible defaults
26    let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
27        // Default to info level for our crates, warn for others
28        EnvFilter::new("capnweb=debug,tower_http=debug,axum=debug,hyper=debug,warn")
29    });
30
31    // Create console subscriber
32    let console_layer = fmt::layer()
33        .with_target(true)
34        .with_thread_ids(true)
35        .with_timer(ChronoUtc::rfc_3339())
36        .with_writer(std::io::stderr);
37
38    // Create file subscriber
39    let file_layer = fmt::layer()
40        .with_target(true)
41        .with_thread_ids(true)
42        .with_timer(ChronoUtc::rfc_3339())
43        .with_ansi(false) // No color codes in files
44        .with_writer(file_writer);
45
46    // Combine layers
47    tracing_subscriber::registry()
48        .with(env_filter)
49        .with(console_layer)
50        .with(file_layer)
51        .init();
52
53    // Keep the guard alive by leaking it
54    std::mem::forget(_guard);
55
56    tracing::info!("Logging initialized with file output to {:?}", log_dir_path);
57    Ok(())
58}
59
60/// Initialize simple console-only logging for tests
61pub fn init_test_logging() {
62    let _ = tracing_subscriber::fmt()
63        .with_env_filter(
64            EnvFilter::try_from_default_env()
65                .unwrap_or_else(|_| EnvFilter::new("capnweb=trace,debug")),
66        )
67        .try_init();
68}