Skip to content

Commit 36d8ff8

Browse files
committed
Implement logger adapter
1 parent a67ddbd commit 36d8ff8

5 files changed

Lines changed: 167 additions & 8 deletions

File tree

examples/server_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ const SERVER: &str = "127.0.0.1:12351";
1212
fn server() -> Result<(), ErrorKind> {
1313
let mut socket = Socket::bind(SERVER)?;
1414
let (sender, receiver) = (socket.get_packet_sender(), socket.get_event_receiver());
15-
let _thread = thread::spawn(move || socket.start_polling());
1615

1716
loop {
17+
socket.manual_poll(Instant::now());
1818
if let Ok(event) = receiver.recv() {
1919
match event {
2020
SocketEvent::Packet(packet) => {

src/config.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use crate::log;
12
use crate::net::constants::{DEFAULT_MTU, FRAGMENT_SIZE_DEFAULT, MAX_FRAGMENTS_DEFAULT};
2-
use std::{default::Default, time::Duration};
3+
use std::{default::Default, rc::Rc, time::Duration};
34

45
#[derive(Clone, Debug)]
56
/// Contains the configuration options to configure laminar for special use-cases.
@@ -54,6 +55,8 @@ pub struct Config {
5455
/// When we send a reliable packet, it is stored locally until an acknowledgement comes back to
5556
/// us, if that store grows to a size
5657
pub max_packets_in_flight: u16,
58+
/// Logger used for this instance of laminar. See [log::LaminarLogger] for more details.
59+
pub logger: Rc<dyn log::LaminarLogger>,
5760
}
5861

5962
impl Default for Config {
@@ -72,6 +75,7 @@ impl Default for Config {
7275
socket_event_buffer_size: 1024,
7376
socket_polling_timeout: Some(Duration::from_millis(1)),
7477
max_packets_in_flight: 512,
78+
logger: Rc::new(log::DefaultLogger),
7579
}
7680
}
7781
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ mod config;
2626
mod either;
2727
mod error;
2828
mod infrastructure;
29+
pub mod log;
2930
mod net;
3031
mod packet;
3132
mod protocol_version;

src/log.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//! Logging adapter for Laminar
2+
//!
3+
//! This module implements a simple, threaded-logger-friendly logging adapter. Logging adapters are
4+
//! used to attach an arbitrary logger into Laminar.
5+
use std::fmt;
6+
use std::sync::Arc;
7+
8+
/// Logger trait for laminar
9+
///
10+
/// Any user of Laminar can implement this trait to attach their favorite logger to an instance of
11+
/// laminar. The log levels correspond to the same log levels as in the `log` crate.
12+
pub trait LaminarLogger {
13+
/// Log a trace message
14+
fn trace(&self, disp: Displayer);
15+
/// Log a debug message
16+
fn debug(&self, disp: Displayer);
17+
/// Log an info message
18+
fn info(&self, disp: Displayer);
19+
/// Log a warning message
20+
fn warn(&self, disp: Displayer);
21+
/// Log an error message
22+
fn error(&self, disp: Displayer);
23+
}
24+
25+
// ---
26+
27+
/// Holds a handle to a formatter function while implementing the [fmt::Display] trait.
28+
pub struct Displayer {
29+
data: Arc<dyn Fn(&mut ::std::fmt::Formatter) -> ::std::fmt::Result + Send + Sync>,
30+
}
31+
32+
impl Displayer {
33+
pub(crate) fn new(
34+
delegate: Arc<dyn Fn(&mut ::std::fmt::Formatter) -> ::std::fmt::Result + Send + Sync>,
35+
) -> Self {
36+
Self { data: delegate }
37+
}
38+
}
39+
40+
impl fmt::Display for Displayer {
41+
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
42+
(self.data)(f)
43+
}
44+
}
45+
46+
// ---
47+
48+
pub(crate) struct DefaultLogger;
49+
50+
impl LaminarLogger for DefaultLogger {
51+
fn trace(&self, _: Displayer) {}
52+
fn debug(&self, _: Displayer) {}
53+
fn info(&self, _: Displayer) {}
54+
fn warn(&self, _: Displayer) {}
55+
fn error(&self, _: Displayer) {}
56+
}
57+
58+
// ---
59+
60+
impl fmt::Debug for dyn LaminarLogger {
61+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62+
write![f, "LaminarLogger"]
63+
}
64+
}
65+
66+
// ---
67+
68+
/// Format-friendly form of [log::LaminarLogger::trace]
69+
#[macro_export]
70+
macro_rules! trace {
71+
($logger:expr, $($fmt:expr),* $(,)?) => {{
72+
$logger.trace($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
73+
}};
74+
}
75+
76+
/// Format-friendly form of [log::LaminarLogger::debug]
77+
#[macro_export]
78+
macro_rules! debug {
79+
($logger:expr, $($fmt:expr),* $(,)?) => {{
80+
$logger.debug($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
81+
}};
82+
}
83+
84+
/// Format-friendly form of [log::LaminarLogger::info]
85+
#[macro_export]
86+
macro_rules! info {
87+
($logger:expr, $($fmt:expr),* $(,)?) => {{
88+
$logger.info($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
89+
}};
90+
}
91+
92+
/// Format-friendly form of [log::LaminarLogger::warn]
93+
#[macro_export]
94+
macro_rules! warn {
95+
($logger:expr, $($fmt:expr),* $(,)?) => {{
96+
$logger.warn($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
97+
}};
98+
}
99+
100+
/// Format-friendly form of [log::LaminarLogger::error]
101+
#[macro_export]
102+
macro_rules! error {
103+
($logger:expr, $($fmt:expr),* $(,)?) => {{
104+
$logger.error($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
105+
}};
106+
}

src/net/socket.rs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use crate::either::Either::{Left, Right};
2+
use crate::error;
23
use crate::{
34
config::Config,
45
error::{ErrorKind, Result},
56
net::{connection::ActiveConnections, events::SocketEvent, link_conditioner::LinkConditioner},
67
packet::{DeliveryGuarantee, Outgoing, Packet},
78
};
89
use crossbeam_channel::{self, unbounded, Receiver, SendError, Sender, TryRecvError};
9-
use log::error;
1010
use std::{
1111
self, io,
1212
net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket},
@@ -142,7 +142,10 @@ impl Socket {
142142
match self.recv_from(time) {
143143
Ok(UdpSocketState::MaybeMore) => continue,
144144
Ok(UdpSocketState::MaybeEmpty) => break,
145-
Err(e) => error!("Encountered an error receiving data: {:?}", e),
145+
Err(e) => error!(
146+
self.config.logger,
147+
"Encountered an error receiving data: {:?}", e
148+
),
146149
}
147150
}
148151

@@ -151,14 +154,20 @@ impl Socket {
151154
if let Err(e) = self.send_to(p, time) {
152155
match e {
153156
ErrorKind::IOError(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
154-
_ => error!("There was an error sending packet: {:?}", e),
157+
_ => error!(
158+
self.config.logger,
159+
"There was an error sending packet: {:?}", e
160+
),
155161
}
156162
}
157163
}
158164

159165
// Check for idle clients
160166
if let Err(e) = self.handle_idle_clients(time) {
161-
error!("Encountered an error when sending TimeoutEvent: {:?}", e);
167+
error!(
168+
self.config.logger,
169+
"Encountered an error when sending TimeoutEvent: {:?}", e
170+
);
162171
}
163172

164173
// Handle any dead clients
@@ -169,7 +178,10 @@ impl Socket {
169178
if let Err(e) = self.send_heartbeat_packets(heartbeat_interval, time) {
170179
match e {
171180
ErrorKind::IOError(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
172-
_ => error!("There was an error sending a heartbeat packet: {:?}", e),
181+
_ => error!(
182+
self.config.logger,
183+
"There was an error sending a heartbeat packet: {:?}", e
184+
),
173185
}
174186
}
175187
}
@@ -320,7 +332,11 @@ impl Socket {
320332
}
321333
Err(e) => {
322334
if e.kind() != io::ErrorKind::WouldBlock {
323-
error!("Encountered an error receiving data: {:?}", e);
335+
let err = format!["{:?}", e];
336+
error!(
337+
self.config.logger,
338+
"Encountered an error receiving data: {}", err
339+
);
324340
return Err(e.into());
325341
} else {
326342
return Ok(UdpSocketState::MaybeEmpty);
@@ -1204,4 +1220,36 @@ mod tests {
12041220

12051221
assert_eq!["99999", last_payload];
12061222
}
1223+
1224+
#[test]
1225+
fn log_adapter() {
1226+
use crate::log::{Displayer, LaminarLogger};
1227+
use std::{rc::Rc, sync::Arc};
1228+
1229+
let mut cfg = Config::default();
1230+
1231+
struct MyAdapter {}
1232+
1233+
impl LaminarLogger for MyAdapter {
1234+
fn trace(&self, disp: Displayer) {
1235+
println!["trace: {}", disp];
1236+
}
1237+
fn debug(&self, disp: Displayer) {
1238+
println!["debug: {}", disp];
1239+
}
1240+
fn info(&self, disp: Displayer) {
1241+
println!["info: {}", disp];
1242+
}
1243+
fn warn(&self, disp: Displayer) {
1244+
println!["warn: {}", disp];
1245+
}
1246+
fn error(&self, disp: Displayer) {
1247+
println!["An error! {}", disp];
1248+
}
1249+
}
1250+
1251+
cfg.logger = Rc::new(MyAdapter { });
1252+
1253+
Socket::bind_any_with_config(cfg).unwrap();
1254+
}
12071255
}

0 commit comments

Comments
 (0)