use std::{cell::RefCell, marker::PhantomData};
use crate::
{
error::SyRes,
formatters::{DefaultSyslogFormatter, SyslogFormatter},
sync::{syslog_sync_internal::SyslogSocketLockless, LogItems, SyStream},
LogFacility,
LogStat,
Priority,
SyStreamApi,
SyslogApi,
SyslogDestination,
};
#[cfg(target_family = "unix")]
use crate::SyslogLocal;
#[cfg(target_family = "windows")]
use crate::WindowsEvent;
#[cfg(target_family = "unix")]
pub type DefaultLocalSyslogDestination = SyslogLocal;
#[cfg(target_family = "windows")]
pub type DefaultLocalSyslogDestination = WindowsEvent;
#[derive(Debug)]
pub struct SingleSyslog<F = DefaultSyslogFormatter, D = DefaultLocalSyslogDestination>
where
F: SyslogFormatter,
D: SyslogDestination,
{
log_items: RefCell<LogItems>,
stream: RefCell<SyslogSocketLockless<D>>,
_p: PhantomData<F>,
_p_not_ss: PhantomData<*const ()>
}
impl SingleSyslog
{
pub
fn openlog(ident: Option<&str>, logstat: LogStat, facility: LogFacility, net_tap_prov: DefaultLocalSyslogDestination) -> SyRes<Self>
{
let log_items =
LogItems::new(ident, 0xff, logstat, facility);
let stream =
SyslogSocketLockless::<DefaultLocalSyslogDestination>::new(logstat, net_tap_prov)?;
return Ok(
Self
{
log_items: RefCell::new(log_items),
stream: RefCell::new(stream),
_p: PhantomData,
_p_not_ss: PhantomData
}
);
}
}
impl<F, D> SingleSyslog<F, D>
where F: SyslogFormatter, D: SyslogDestination
{
pub
fn openlog_with(ident: Option<&str>, logstat: LogStat, facility: LogFacility, net_tap_prov: D) -> SyRes<Self>
{
let log_items =
LogItems::new(ident, 0xff, logstat, facility);
let stream =
SyslogSocketLockless::<D>::new(logstat, net_tap_prov)?;
return Ok(
Self
{
log_items: RefCell::new(log_items),
stream: RefCell::new(stream),
_p: PhantomData,
_p_not_ss: PhantomData
}
);
}
}
impl<F, D> SyslogApi<F, D> for SingleSyslog<F, D>
where F: SyslogFormatter, D: SyslogDestination
{
#[inline]
fn connectlog(&self) -> SyRes<()>
{
return
self
.stream
.borrow_mut()
.connectlog();
}
#[inline]
fn setlogmask(&self, logmask: i32) -> SyRes<i32>
{
return Ok(
self
.log_items
.borrow_mut()
.set_logmask(logmask)
);
}
#[inline]
fn closelog(&self) -> SyRes<()>
{
return
self
.stream
.borrow_mut()
.disconnectlog();
}
#[inline]
fn syslog(&self, pri: Priority, fmt: F)
{
let Some((formatted_msg, logstat)) =
self.log_items.borrow().vsyslog1_msg::<F, D>(pri, &fmt)
else { return };
self.stream.borrow_mut().vsyslog1(logstat, formatted_msg);
return;
}
#[inline]
fn change_identity(&self, ident: Option<&str>) -> SyRes<()>
{
self.log_items.borrow_mut().set_identity(ident);
return Ok(());
}
#[inline]
fn reconnect(&self) -> SyRes<()>
{
return
self
.stream
.borrow_mut()
.reconnectlog();
}
#[inline]
fn update_tap_data(&self, tap_data: D) -> SyRes<()>
{
return
self
.stream
.borrow_mut()
.update_tap_data(tap_data.clone());
}
}
impl<'stream, F: SyslogFormatter, D: SyslogDestination> SyStreamApi<'stream, F, D, SingleSyslog<F, D>>
for SingleSyslog<F, D>
{
fn stream(&'stream self, pri: Priority) -> SyStream<'stream, D, F, SingleSyslog<F, D>>
{
return
SyStream
{
inner: self,
pri: pri,
_p: PhantomData,
_p1: PhantomData
};
}
}
#[cfg(target_family = "unix")]
#[cfg(test)]
mod tests
{
use std::{cell::RefCell, time::Instant};
use crate::{sync::syslog_threadlocal::SingleSyslog, LogFacility, LogStat, Priority, SyStreamApi, SyslogApi, SyslogLocal};
#[test]
fn test_thread_single1()
{
thread_local!
{
static SYSLOG: RefCell<SingleSyslog> =
RefCell::new(SingleSyslog::openlog_with(Some("test"), LogStat::LOG_PID ,
LogFacility::LOG_DAEMON, SyslogLocal::new()).unwrap());
}
let thread =
std::thread::spawn(move ||
{
for i in 0..10
{
let fmms = format!("test message {} from thread {:?}", i, std::thread::current().name());
let s = Instant::now();
SYSLOG
.with_borrow_mut(|syslog|
syslog
.syslog(
Priority::LOG_ERR,
fmms.into()
)
);
let e = s.elapsed();
println!("{:?}", e);
}
}
);
SYSLOG
.with_borrow_mut(|syslog|
syslog
.syslog(
Priority::LOG_DEBUG,
format!("main test message from thread {:?}", std::thread::current().name()).into()
)
);
thread.join().unwrap();
return;
}
#[test]
fn test_single_stream_test()
{
use std::fmt::Write;
let log =
SingleSyslog::openlog(
Some("test1"),
LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
LogFacility::LOG_DAEMON,
SyslogLocal::new());
assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
let log = log.unwrap();
write!(log.stream(Priority::LOG_DEBUG), "test stream singlesyslog").unwrap();
for i in 0..3
{
let s = Instant::now();
write!(log.stream(Priority::LOG_DEBUG), "test stream singlesyslog {}", i).unwrap();
let e = s.elapsed();
println!("{:?}", e);
}
}
}
#[cfg(target_family = "windows")]
#[cfg(test)]
mod tests
{
use std::{cell::RefCell, time::Instant};
use crate::{sync::syslog_threadlocal::SingleSyslog, LogFacility, LogStat, Priority, SyStreamApi, SyslogApi, WindowsEvent};
#[test]
fn test_thread_signalling()
{
thread_local!
{
static SYSLOG: RefCell<SingleSyslog> =
RefCell::new(SingleSyslog::openlog_with(Some("test"), LogStat::LOG_PID ,
LogFacility::LOG_DAEMON, WindowsEvent::new()).unwrap());
}
let thread =
std::thread::spawn(move ||
{
for i in 0..10
{
let fmms = format!("test message {} from thread {:?}", i, std::thread::current().name());
let s = Instant::now();
SYSLOG
.with_borrow_mut(|syslog|
syslog
.syslog(
Priority::LOG_ERR,
fmms.into()
)
);
let e = s.elapsed();
println!("{:?}", e);
}
}
);
SYSLOG
.with_borrow_mut(|syslog|
syslog
.syslog(
Priority::LOG_DEBUG,
format!("main test message from thread {:?}", std::thread::current().name()).into()
)
);
thread.join().unwrap();
return;
}
#[test]
fn test_single_stream_test()
{
use std::fmt::Write;
let log =
SingleSyslog::openlog(
Some("test1"),
LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID,
LogFacility::LOG_DAEMON,
WindowsEvent::new());
assert_eq!(log.is_ok(), true, "{}", log.err().unwrap());
let log = log.unwrap();
write!(log.stream(Priority::LOG_DEBUG), "test stream singlesyslog").unwrap();
for i in 0..3
{
let s = Instant::now();
write!(log.stream(Priority::LOG_DEBUG), "test stream singlesyslog {}", i).unwrap();
let e = s.elapsed();
println!("{:?}", e);
}
}
}