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 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 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 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