lxy 0.1.1

A convenient async http and RPC framework in Rust
Documentation
use std::path::Path;

use tracing_appender::non_blocking::{NonBlocking, WorkerGuard};

use super::config::*;

pub(crate) fn create_stdout_writer() -> (NonBlocking, WorkerGuard) {
  tracing_appender::non_blocking(std::io::stdout())
}

pub(crate) fn create_rolling_file_writer(opts: &FileLayerOptions) -> (NonBlocking, WorkerGuard) {
  let (dir, file_name) = parse_file_path(&opts.path);

  ensure_log_directory_exists(dir);

  let rolling_appender = match opts.rotation {
    Some(RotationPeriod::Daily) => tracing_appender::rolling::daily(dir, file_name),
    Some(RotationPeriod::Hourly) => tracing_appender::rolling::hourly(dir, file_name),
    Some(RotationPeriod::Weekly) => tracing_appender::rolling::weekly(dir, file_name),
    None => tracing_appender::rolling::never(dir, file_name),
  };

  tracing_appender::non_blocking(rolling_appender)
}

/// Parses a file path into directory and file name components.
fn parse_file_path(path: &str) -> (&Path, &str) {
  let path = Path::new(path);
  let dir = path.parent().unwrap_or(Path::new("."));
  let file_name = path
    .file_name()
    .and_then(|s| s.to_str())
    .unwrap_or("app.log");

  (dir, file_name)
}

fn ensure_log_directory_exists(path: &Path) {
  if !path.as_os_str().is_empty() {
    std::fs::create_dir_all(path)
      .unwrap_or_else(|e| panic!("Failed to create log directory '{:?}': {}", path, e));
  }
}

#[cfg(test)]
mod tests {
  use std::path::Path;

  use super::*;

  #[test]
  fn test_parse_file_path() {
    let (dir, name) = parse_file_path("logs/app.log");
    assert_eq!(dir, Path::new("logs"));
    assert_eq!(name, "app.log");

    let (dir, name) = parse_file_path("app.log");
    assert_eq!(dir.to_str().unwrap_or(""), "");
    assert_eq!(name, "app.log");

    let (dir, name) = parse_file_path("/var/log/myapp");
    assert_eq!(dir, Path::new("/var/log"));
    assert_eq!(name, "myapp");
  }
}