1#![warn(missing_docs)]
6#![warn(clippy::pedantic)]
7#![allow(clippy::module_name_repetitions)]
8#![allow(clippy::missing_errors_doc)]
9#![allow(clippy::missing_panics_doc)]
10
11pub mod cache;
12pub mod cli;
13pub mod config;
14pub mod error;
15pub mod server;
16pub mod tools;
17pub mod utils;
18
19pub use crate::config::{AppConfig, ServerConfig};
20pub use crate::error::{Error, Result};
22pub use crate::server::CratesDocsServer;
23
24pub const VERSION: &str = env!("CARGO_PKG_VERSION");
26
27pub const NAME: &str = "crates-docs";
29
30#[deprecated(note = "Please use init_logging_with_config instead")]
35pub fn init_logging(debug: bool) -> Result<()> {
36 use tracing_subscriber::{fmt, prelude::*, EnvFilter};
37
38 let filter = if debug {
39 EnvFilter::new("debug")
40 } else {
41 EnvFilter::new("info")
42 };
43
44 let fmt_layer = fmt::layer()
45 .with_target(true)
46 .with_thread_ids(true)
47 .with_thread_names(true)
48 .compact();
49
50 tracing_subscriber::registry()
51 .with(filter)
52 .with(fmt_layer)
53 .try_init()
54 .map_err(|e| error::Error::Initialization(e.to_string()))?;
55
56 Ok(())
57}
58
59pub fn init_logging_with_config(config: &crate::config::LoggingConfig) -> Result<()> {
64 use tracing_subscriber::{fmt, prelude::*, EnvFilter};
65
66 let level = match config.level.to_lowercase().as_str() {
68 "trace" => "trace",
69 "debug" => "debug",
70 "warn" => "warn",
71 "error" => "error",
72 _ => "info",
73 };
74
75 let filter = EnvFilter::new(level);
76
77 match (config.enable_console, config.enable_file, &config.file_path) {
79 (true, true, Some(file_path)) => {
81 let log_dir = std::path::Path::new(file_path)
83 .parent()
84 .filter(|p| !p.as_os_str().is_empty())
85 .unwrap_or_else(|| std::path::Path::new("."));
86 let log_file_name = std::path::Path::new(file_path)
87 .file_name()
88 .unwrap_or(std::ffi::OsStr::new("crates-docs.log"));
89
90 std::fs::create_dir_all(log_dir).map_err(|e| {
92 error::Error::Initialization(format!("Failed to create log directory: {e}"))
93 })?;
94
95 let file_appender = tracing_appender::rolling::daily(log_dir, log_file_name);
97
98 tracing_subscriber::registry()
99 .with(filter)
100 .with(
101 fmt::layer()
102 .with_target(true)
103 .with_thread_ids(true)
104 .with_thread_names(true)
105 .compact(),
106 )
107 .with(
108 fmt::layer()
109 .with_writer(file_appender)
110 .with_target(true)
111 .with_thread_ids(true)
112 .with_thread_names(true)
113 .compact(),
114 )
115 .try_init()
116 .map_err(|e| error::Error::Initialization(e.to_string()))?;
117 }
118
119 (true, _, _) | (false, false, _) => {
121 tracing_subscriber::registry()
122 .with(filter)
123 .with(
124 fmt::layer()
125 .with_target(true)
126 .with_thread_ids(true)
127 .with_thread_names(true)
128 .compact(),
129 )
130 .try_init()
131 .map_err(|e| error::Error::Initialization(e.to_string()))?;
132 }
133
134 (false, true, Some(file_path)) => {
136 let log_dir = std::path::Path::new(file_path)
138 .parent()
139 .filter(|p| !p.as_os_str().is_empty())
140 .unwrap_or_else(|| std::path::Path::new("."));
141 let log_file_name = std::path::Path::new(file_path)
142 .file_name()
143 .unwrap_or(std::ffi::OsStr::new("crates-docs.log"));
144
145 std::fs::create_dir_all(log_dir).map_err(|e| {
147 error::Error::Initialization(format!("Failed to create log directory: {e}"))
148 })?;
149
150 let file_appender = tracing_appender::rolling::daily(log_dir, log_file_name);
152
153 tracing_subscriber::registry()
154 .with(filter)
155 .with(
156 fmt::layer()
157 .with_writer(file_appender)
158 .with_target(true)
159 .with_thread_ids(true)
160 .with_thread_names(true)
161 .compact(),
162 )
163 .try_init()
164 .map_err(|e| error::Error::Initialization(e.to_string()))?;
165 }
166
167 _ => {
169 tracing_subscriber::registry()
170 .with(filter)
171 .with(
172 fmt::layer()
173 .with_target(true)
174 .with_thread_ids(true)
175 .with_thread_names(true)
176 .compact(),
177 )
178 .try_init()
179 .map_err(|e| error::Error::Initialization(e.to_string()))?;
180 }
181 }
182
183 Ok(())
184}