slog-gelf 0.1.2

GELF drain for slog
Documentation
use std::{io, net};

use chunked::{ChunkSize, ChunkedMessage};

pub struct UdpDestination {
    socket: net::UdpSocket,
    destination: net::SocketAddr,
    chunk_size: ChunkSize,
}

impl UdpDestination {
    pub fn new<T: net::ToSocketAddrs>(
        destination: T,
        chunk_size: ChunkSize,
    ) -> Result<Self, io::Error> {
        let destination = destination.to_socket_addrs()?.nth(0).ok_or(io::Error::new(
            io::ErrorKind::InvalidInput,
            "Invalid destination",
        ))?;

        let local = match destination {
            net::SocketAddr::V4(_) => "0.0.0.0:0",
            net::SocketAddr::V6(_) => "[::]:0",
        };

        let socket = net::UdpSocket::bind(local)?;

        Ok(UdpDestination {
            socket,
            destination,
            chunk_size,
        })
    }

    pub fn log(&self, message: Vec<u8>) -> Result<(), io::Error> {
        let chunked_message = ChunkedMessage::new(self.chunk_size, message)?;

        let sent_bytes = chunked_message
            .iter()
            .map(
                |chunk| match self.socket.send_to(&chunk, self.destination) {
                    Err(_) => 0,
                    Ok(size) => size,
                },
            )
            .fold(0_u64, |carry, size| carry + size as u64);

        if sent_bytes != chunked_message.len() {
            return Err(io::Error::new(
                io::ErrorKind::UnexpectedEof,
                "Invalid number of bytes sent",
            ));
        }

        Ok(())
    }
}