Skip to content

Commit

Permalink
Implement logger adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
kstrafe committed Sep 9, 2019
1 parent a67ddbd commit 36d8ff8
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 8 deletions.
2 changes: 1 addition & 1 deletion examples/server_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ const SERVER: &str = "127.0.0.1:12351";
fn server() -> Result<(), ErrorKind> {
let mut socket = Socket::bind(SERVER)?;
let (sender, receiver) = (socket.get_packet_sender(), socket.get_event_receiver());
let _thread = thread::spawn(move || socket.start_polling());

loop {
socket.manual_poll(Instant::now());
if let Ok(event) = receiver.recv() {
match event {
SocketEvent::Packet(packet) => {
Expand Down
6 changes: 5 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::log;
use crate::net::constants::{DEFAULT_MTU, FRAGMENT_SIZE_DEFAULT, MAX_FRAGMENTS_DEFAULT};
use std::{default::Default, time::Duration};
use std::{default::Default, rc::Rc, time::Duration};

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

impl Default for Config {
Expand All @@ -72,6 +75,7 @@ impl Default for Config {
socket_event_buffer_size: 1024,
socket_polling_timeout: Some(Duration::from_millis(1)),
max_packets_in_flight: 512,
logger: Rc::new(log::DefaultLogger),
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod config;
mod either;
mod error;
mod infrastructure;
pub mod log;
mod net;
mod packet;
mod protocol_version;
Expand Down
106 changes: 106 additions & 0 deletions src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! Logging adapter for Laminar
//!
//! This module implements a simple, threaded-logger-friendly logging adapter. Logging adapters are
//! used to attach an arbitrary logger into Laminar.
use std::fmt;
use std::sync::Arc;

/// Logger trait for laminar
///
/// Any user of Laminar can implement this trait to attach their favorite logger to an instance of
/// laminar. The log levels correspond to the same log levels as in the `log` crate.
pub trait LaminarLogger {
/// Log a trace message
fn trace(&self, disp: Displayer);
/// Log a debug message
fn debug(&self, disp: Displayer);
/// Log an info message
fn info(&self, disp: Displayer);
/// Log a warning message
fn warn(&self, disp: Displayer);
/// Log an error message
fn error(&self, disp: Displayer);
}

// ---

/// Holds a handle to a formatter function while implementing the [fmt::Display] trait.
pub struct Displayer {
data: Arc<dyn Fn(&mut ::std::fmt::Formatter) -> ::std::fmt::Result + Send + Sync>,
}

impl Displayer {
pub(crate) fn new(
delegate: Arc<dyn Fn(&mut ::std::fmt::Formatter) -> ::std::fmt::Result + Send + Sync>,
) -> Self {
Self { data: delegate }
}
}

impl fmt::Display for Displayer {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
(self.data)(f)
}
}

// ---

pub(crate) struct DefaultLogger;

impl LaminarLogger for DefaultLogger {
fn trace(&self, _: Displayer) {}
fn debug(&self, _: Displayer) {}
fn info(&self, _: Displayer) {}
fn warn(&self, _: Displayer) {}
fn error(&self, _: Displayer) {}
}

// ---

impl fmt::Debug for dyn LaminarLogger {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write![f, "LaminarLogger"]
}
}

// ---

/// Format-friendly form of [log::LaminarLogger::trace]
#[macro_export]
macro_rules! trace {
($logger:expr, $($fmt:expr),* $(,)?) => {{
$logger.trace($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
}};
}

/// Format-friendly form of [log::LaminarLogger::debug]
#[macro_export]
macro_rules! debug {
($logger:expr, $($fmt:expr),* $(,)?) => {{
$logger.debug($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
}};
}

/// Format-friendly form of [log::LaminarLogger::info]
#[macro_export]
macro_rules! info {
($logger:expr, $($fmt:expr),* $(,)?) => {{
$logger.info($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
}};
}

/// Format-friendly form of [log::LaminarLogger::warn]
#[macro_export]
macro_rules! warn {
($logger:expr, $($fmt:expr),* $(,)?) => {{
$logger.warn($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
}};
}

/// Format-friendly form of [log::LaminarLogger::error]
#[macro_export]
macro_rules! error {
($logger:expr, $($fmt:expr),* $(,)?) => {{
$logger.error($crate::log::Displayer::new(::std::sync::Arc::new(move |f: &mut ::std::fmt::Formatter| { write![f, $($fmt),*] }) ));
}};
}
60 changes: 54 additions & 6 deletions src/net/socket.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::either::Either::{Left, Right};
use crate::error;
use crate::{
config::Config,
error::{ErrorKind, Result},
net::{connection::ActiveConnections, events::SocketEvent, link_conditioner::LinkConditioner},
packet::{DeliveryGuarantee, Outgoing, Packet},
};
use crossbeam_channel::{self, unbounded, Receiver, SendError, Sender, TryRecvError};
use log::error;
use std::{
self, io,
net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket},
Expand Down Expand Up @@ -142,7 +142,10 @@ impl Socket {
match self.recv_from(time) {
Ok(UdpSocketState::MaybeMore) => continue,
Ok(UdpSocketState::MaybeEmpty) => break,
Err(e) => error!("Encountered an error receiving data: {:?}", e),
Err(e) => error!(
self.config.logger,
"Encountered an error receiving data: {:?}", e
),
}
}

Expand All @@ -151,14 +154,20 @@ impl Socket {
if let Err(e) = self.send_to(p, time) {
match e {
ErrorKind::IOError(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
_ => error!("There was an error sending packet: {:?}", e),
_ => error!(
self.config.logger,
"There was an error sending packet: {:?}", e
),
}
}
}

// Check for idle clients
if let Err(e) = self.handle_idle_clients(time) {
error!("Encountered an error when sending TimeoutEvent: {:?}", e);
error!(
self.config.logger,
"Encountered an error when sending TimeoutEvent: {:?}", e
);
}

// Handle any dead clients
Expand All @@ -169,7 +178,10 @@ impl Socket {
if let Err(e) = self.send_heartbeat_packets(heartbeat_interval, time) {
match e {
ErrorKind::IOError(ref e) if e.kind() == io::ErrorKind::WouldBlock => {}
_ => error!("There was an error sending a heartbeat packet: {:?}", e),
_ => error!(
self.config.logger,
"There was an error sending a heartbeat packet: {:?}", e
),
}
}
}
Expand Down Expand Up @@ -320,7 +332,11 @@ impl Socket {
}
Err(e) => {
if e.kind() != io::ErrorKind::WouldBlock {
error!("Encountered an error receiving data: {:?}", e);
let err = format!["{:?}", e];
error!(
self.config.logger,
"Encountered an error receiving data: {}", err
);
return Err(e.into());
} else {
return Ok(UdpSocketState::MaybeEmpty);
Expand Down Expand Up @@ -1204,4 +1220,36 @@ mod tests {

assert_eq!["99999", last_payload];
}

#[test]
fn log_adapter() {
use crate::log::{Displayer, LaminarLogger};
use std::{rc::Rc, sync::Arc};

let mut cfg = Config::default();

struct MyAdapter {}

impl LaminarLogger for MyAdapter {
fn trace(&self, disp: Displayer) {
println!["trace: {}", disp];
}
fn debug(&self, disp: Displayer) {
println!["debug: {}", disp];
}
fn info(&self, disp: Displayer) {
println!["info: {}", disp];
}
fn warn(&self, disp: Displayer) {
println!["warn: {}", disp];
}
fn error(&self, disp: Displayer) {
println!["An error! {}", disp];
}
}

cfg.logger = Rc::new(MyAdapter { });

Socket::bind_any_with_config(cfg).unwrap();
}
}

0 comments on commit 36d8ff8

Please sign in to comment.