rokkett_logger/
client.rs

1pub mod conn;
2pub mod man;
3
4use crate::protocol::{Command, LogMessage, RequestPackage, Status};
5use conn::ClientConnection;
6use man::ConnectionManager;
7
8use log::{LevelFilter, Log};
9use r2d2::Pool;
10use std::net::SocketAddr;
11
12#[derive(Debug)]
13pub struct RokkettLogger {
14	service: String,
15	pool: Pool<ConnectionManager>,
16}
17
18impl RokkettLogger {
19	/// Creates and initializes the new RokkettLogger.
20	///
21	/// - **addr**: the address of the logging server in <host>:<port> format
22	/// - **service**: The name of the application
23	/// - **token**: auth token
24	pub fn new(addr: &str, service: &str, token: Option<&str>) -> anyhow::Result<()> {
25		let ipaddr: SocketAddr = addr.parse()?;
26		let token = match token {
27			Some(token) => token.to_owned(),
28			None => "".to_owned(),
29		};
30
31		// test connection before creating a pool
32		ClientConnection::new(&ipaddr)?.is_valid()?;
33
34		let max_size = num_cpus::get() as u32 * 2;
35		let logger = RokkettLogger {
36			service: service.to_owned(),
37			pool: r2d2::Pool::builder()
38				.max_size(max_size)
39				.build(ConnectionManager::new(ipaddr, token))?,
40		};
41		log::set_boxed_logger(Box::new(logger))?;
42		log::set_max_level(LevelFilter::Debug);
43		Ok(())
44	}
45}
46
47impl Log for RokkettLogger {
48	fn enabled(&self, metadata: &log::Metadata) -> bool {
49		metadata.level() > LevelFilter::Off
50	}
51
52	fn log(&self, record: &log::Record) {
53		if self.enabled(record.metadata()) {
54			let log_msg = LogMessage::from_log_record(record, &self.service);
55			let package = RequestPackage {
56				command: Command::Log(log_msg),
57			};
58			let pool = self.pool.clone();
59
60			// TODO: fix blocking everything inside tasks
61			let task = move || {
62				let mut conn = match pool.get() {
63					Ok(conn) => conn,
64					Err(err) => return eprintln!("failed to get connection from pool. err = {err}"),
65				};
66				match conn.send(package) {
67					Ok(status) => {
68						match status {
69							Status::Ok => {}
70							status => eprintln!("failed to send log. status = {status}"),
71						};
72					}
73					Err(err) => eprintln!("failed to send log. err = {err}"),
74				}
75			};
76
77			#[cfg(not(feature = "tokio"))]
78			std::thread::spawn(task);
79
80			#[cfg(feature = "tokio")]
81			tokio::task::spawn(async { (task)() });
82		}
83	}
84
85	fn flush(&self) {}
86}
87
88// #[cfg(test)]
89// mod tests {
90// 	use super::*;
91
92// 	#[test]
93// 	fn test() {
94// 		assert!(true);
95// 	}
96// }