From 3eda0d0968e9c931b0cedad39c15cc46029032ce Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 12 Nov 2024 09:23:56 +0800 Subject: [PATCH] feat: impl send_formatted (#4) Signed-off-by: tison --- README.md | 8 +++--- src/facility.rs | 4 +-- src/format.rs | 4 +-- src/lib.rs | 8 +++--- src/sender/internal.rs | 45 ++++++++++++++++++++++++++++++ src/sender/mod.rs | 14 ++++++++++ src/sender/tcp.rs | 37 +++++++------------------ src/sender/udp.rs | 31 ++++----------------- src/sender/unix.rs | 63 ++++++++---------------------------------- src/severity.rs | 2 +- 10 files changed, 100 insertions(+), 116 deletions(-) create mode 100644 src/sender/internal.rs diff --git a/README.md b/README.md index 43fca47..36a604a 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ Client library written in Rust to send messages to a Syslog server. Support implementations: -* RFC-3164 Formatter: [The BSD syslog Protocol](http://tools.ietf.org/html/rfc3164) -* RFC-5424 Formatter: [The Syslog Protocol](http://tools.ietf.org/html/rfc5424) -* `UdpSender`: [RFC 5426 - Transmission of Syslog Messages over UDP](http://tools.ietf.org/html/rfc5426) -* `TcpSender`: [RFC 6587 - Transmission of Syslog Messages over TCP](http://tools.ietf.org/html/rfc6587) +* RFC-3164 Formatter: [The BSD syslog Protocol](https://datatracker.ietf.org/doc/html/rfc3164) +* RFC-5424 Formatter: [The Syslog Protocol](https://datatracker.ietf.org/doc/html/rfc5424) +* `UdpSender`: [RFC 5426 - Transmission of Syslog Messages over UDP](https://datatracker.ietf.org/doc/html/rfc5426) +* `TcpSender`: [RFC 6587 - Transmission of Syslog Messages over TCP](https://datatracker.ietf.org/doc/html/rfc6587) * (unix only) Unix domain socket sender (datagram or stream) ## Getting Started diff --git a/src/facility.rs b/src/facility.rs index 0e0725c..b671733 100644 --- a/src/facility.rs +++ b/src/facility.rs @@ -19,8 +19,8 @@ use std::str::FromStr; /// /// See also [RFC 5427] (Textual Conventions for Syslog Management) for the labels. /// -/// [RFC 5424]: https://tools.ietf.org/html/rfc5424. -/// [RFC 5427]: https://tools.ietf.org/html/rfc5427. +/// [RFC 5424]: https://datatracker.ietf.org/doc/html/rfc5424. +/// [RFC 5427]: https://datatracker.ietf.org/doc/html/rfc5427. #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] #[repr(u8)] pub enum Facility { diff --git a/src/format.rs b/src/format.rs index fe091f7..f9edc42 100644 --- a/src/format.rs +++ b/src/format.rs @@ -134,7 +134,7 @@ fn nullable_value(value: Option<&str>) -> &str { /// Format the Syslog message as [RFC-3164] (BSD syslog Protocol). /// -/// [RFC-3164]: https://tools.ietf.org/html/rfc3164 +/// [RFC-3164]: https://datatracker.ietf.org/doc/html/rfc3164 #[derive(Debug)] pub struct RFC3164Formatter<'a, M> { context: &'a SyslogContext, @@ -170,7 +170,7 @@ where /// Format the Syslog message as [RFC 5424] (The Syslog Protocol) /// -/// [RFC 5424]: https://tools.ietf.org/html/rfc5424 +/// [RFC 5424]: https://datatracker.ietf.org/doc/html/rfc5424 #[derive(Debug)] pub struct RFC5424Formatter<'a, M> { context: &'a SyslogContext, diff --git a/src/lib.rs b/src/lib.rs index 373ea76..d87901d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,10 +20,10 @@ //! //! This crate provides facilities to send log messages via syslog. Support implementations: //! -//! * [RFC-3164 Formatter]: [The BSD syslog Protocol](http://tools.ietf.org/html/rfc3164) -//! * [RFC-5424 Formatter]: [The Syslog Protocol](http://tools.ietf.org/html/rfc5424) -//! * [`UdpSender`]: [RFC 5426 - Transmission of Syslog Messages over UDP](http://tools.ietf.org/html/rfc5426) -//! * [`TcpSender`]: [RFC 6587 - Transmission of Syslog Messages over TCP](http://tools.ietf.org/html/rfc6587) +//! * [RFC-3164 Formatter]: [The BSD syslog Protocol](https://datatracker.ietf.org/doc/html/rfc3164) +//! * [RFC-5424 Formatter]: [The Syslog Protocol](https://datatracker.ietf.org/doc/html/rfc5424) +//! * [`UdpSender`]: [RFC 5426 - Transmission of Syslog Messages over UDP](https://datatracker.ietf.org/doc/html/rfc5426) +//! * [`TcpSender`]: [RFC 6587 - Transmission of Syslog Messages over TCP](https://datatracker.ietf.org/doc/html/rfc6587) //! * (unix only) Unix domain socket sender (datagram or stream) //! //! [RFC-3164 Formatter]: format::RFC3164Formatter diff --git a/src/sender/internal.rs b/src/sender/internal.rs new file mode 100644 index 0000000..03ebd0d --- /dev/null +++ b/src/sender/internal.rs @@ -0,0 +1,45 @@ +// Copyright 2024 FastLabs Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +macro_rules! impl_syslog_sender_common { + ($sender:ident) => { + impl $sender { + /// Send a message with the given severity as defined in RFC-3164. + pub fn send_rfc3164( + &mut self, + severity: $crate::Severity, + message: M, + ) -> io::Result<()> { + let message = self.context.format_rfc3164(severity, Some(message)); + self.send_formatted(message.to_string().as_bytes()) + } + + /// Send a message with the given severity as defined in RFC-5424. + pub fn send_rfc5424, M: std::fmt::Display>( + &mut self, + severity: $crate::Severity, + msgid: Option, + elements: Vec<$crate::SDElement>, + message: M, + ) -> io::Result<()> { + let message = self + .context + .format_rfc5424(severity, msgid, elements, Some(message)); + self.send_formatted(message.to_string().as_bytes()) + } + } + }; +} + +pub(crate) use impl_syslog_sender_common; diff --git a/src/sender/mod.rs b/src/sender/mod.rs index 3591351..8badd0c 100644 --- a/src/sender/mod.rs +++ b/src/sender/mod.rs @@ -31,6 +31,8 @@ pub use tcp::*; mod udp; pub use udp::*; +pub(crate) mod internal; + /// Static dispatch for the different sender types. #[derive(Debug)] pub enum SyslogSender { @@ -81,6 +83,18 @@ impl SyslogSender { } } + /// Send a pre-formatted message. + pub fn send_formatted(&mut self, formatted: &[u8]) -> io::Result<()> { + match self { + SyslogSender::Tcp(sender) => sender.send_formatted(formatted), + SyslogSender::Udp(sender) => sender.send_formatted(formatted), + #[cfg(unix)] + SyslogSender::UnixDatagram(sender) => sender.send_formatted(formatted), + #[cfg(unix)] + SyslogSender::UnixStream(sender) => sender.send_formatted(formatted), + } + } + /// Flush the underlying writer if needed. pub fn flush(&mut self) -> io::Result<()> { match self { diff --git a/src/sender/tcp.rs b/src/sender/tcp.rs index 04157af..2434ff8 100644 --- a/src/sender/tcp.rs +++ b/src/sender/tcp.rs @@ -15,12 +15,12 @@ use std::borrow::Cow; use std::io; use std::io::BufWriter; +use std::io::Write; use std::net::TcpStream; use std::net::ToSocketAddrs; use crate::format::SyslogContext; -use crate::SDElement; -use crate::Severity; +use crate::sender::internal::impl_syslog_sender_common; /// Create a TCP sender that sends messages to the well-known port (601). /// @@ -59,7 +59,7 @@ impl TcpSender { /// /// This is generally '\r\n' as defined in [RFC-6587] ยง3.4.2. /// - /// [RFC-6587]: https://tools.ietf.org/html/rfc6587 + /// [RFC-6587]: https://datatracker.ietf.org/doc/html/rfc6587 pub fn set_postfix(&mut self, postfix: impl Into>) { self.postfix = postfix.into(); } @@ -74,30 +74,11 @@ impl TcpSender { &mut self.context } - /// Send a message with the given severity as defined in RFC-3164. - pub fn send_rfc3164( - &mut self, - severity: Severity, - message: M, - ) -> io::Result<()> { - use std::io::Write; - let message = self.context.format_rfc3164(severity, Some(message)); - write!(&mut self.writer, "{}{}", message, self.postfix) - } - - /// Send a message with the given severity as defined in RFC-5424. - pub fn send_rfc5424, M: std::fmt::Display>( - &mut self, - severity: Severity, - msgid: Option, - elements: Vec, - message: M, - ) -> io::Result<()> { - use std::io::Write; - let message = self - .context - .format_rfc5424(severity, msgid, elements, Some(message)); - write!(&mut self.writer, "{}{}", message, self.postfix) + /// Send a pre-formatted message. + pub fn send_formatted(&mut self, formatted: &[u8]) -> io::Result<()> { + self.writer.write_all(formatted)?; + self.writer.write_all(self.postfix.as_bytes())?; + Ok(()) } /// Flush the writer. @@ -106,3 +87,5 @@ impl TcpSender { self.writer.flush() } } + +impl_syslog_sender_common!(TcpSender); diff --git a/src/sender/udp.rs b/src/sender/udp.rs index d469bec..e6e0cc6 100644 --- a/src/sender/udp.rs +++ b/src/sender/udp.rs @@ -17,8 +17,7 @@ use std::net::ToSocketAddrs; use std::net::UdpSocket; use crate::format::SyslogContext; -use crate::SDElement; -use crate::Severity; +use crate::sender::internal::impl_syslog_sender_common; /// Create a UDP sender that sends messages to the well-known port (514). /// @@ -62,29 +61,11 @@ impl UdpSender { &mut self.context } - /// Send a message with the given severity as defined in RFC-3164. - pub fn send_rfc3164( - &mut self, - severity: Severity, - message: M, - ) -> io::Result<()> { - let message = self.context.format_rfc3164(severity, Some(message)); - self.socket.send(message.to_string().as_bytes())?; - Ok(()) - } - - /// Send a message with the given severity as defined in RFC-5424. - pub fn send_rfc5424, M: std::fmt::Display>( - &mut self, - severity: Severity, - msgid: Option, - elements: Vec, - message: M, - ) -> io::Result<()> { - let message = self - .context - .format_rfc5424(severity, msgid, elements, Some(message)); - self.socket.send(message.to_string().as_bytes())?; + /// Send a pre-formatted message. + pub fn send_formatted(&mut self, formatted: &[u8]) -> io::Result<()> { + self.socket.send(formatted)?; Ok(()) } } + +impl_syslog_sender_common!(UdpSender); diff --git a/src/sender/unix.rs b/src/sender/unix.rs index 72e8bec..8804d36 100644 --- a/src/sender/unix.rs +++ b/src/sender/unix.rs @@ -14,14 +14,14 @@ use std::io; use std::io::BufWriter; +use std::io::Write; use std::os::unix::net::UnixDatagram; use std::os::unix::net::UnixStream; use std::path::Path; use crate::format::SyslogContext; +use crate::sender::internal::impl_syslog_sender_common; use crate::sender::SyslogSender; -use crate::SDElement; -use crate::Severity; /// Create a Unix datagram sender that sends messages to the given path. pub fn unix_datagram(path: impl AsRef) -> io::Result { @@ -95,33 +95,15 @@ impl UnixDatagramSender { &mut self.context } - /// Send a message with the given severity as defined in RFC-3164. - pub fn send_rfc3164( - &mut self, - severity: Severity, - message: M, - ) -> io::Result<()> { - let message = self.context.format_rfc3164(severity, Some(message)); - self.socket.send(message.to_string().as_bytes())?; - Ok(()) - } - - /// Send a message with the given severity as defined in RFC-5424. - pub fn send_rfc5424, M: std::fmt::Display>( - &mut self, - severity: Severity, - msgid: Option, - elements: Vec, - message: M, - ) -> io::Result<()> { - let message = self - .context - .format_rfc5424(severity, msgid, elements, Some(message)); - self.socket.send(message.to_string().as_bytes())?; + /// Send a pre-formatted message. + pub fn send_formatted(&mut self, formatted: &[u8]) -> io::Result<()> { + self.socket.send(formatted)?; Ok(()) } } +impl_syslog_sender_common!(UnixDatagramSender); + /// A syslog sender that sends messages to a Unix stream socket. /// /// Typically, this sender is used to send messages to the local syslog daemon. Typical paths are @@ -152,32 +134,9 @@ impl UnixStreamSender { &mut self.context } - /// Send a message with the given severity as defined in RFC-3164. - pub fn send_rfc3164( - &mut self, - severity: Severity, - message: M, - ) -> io::Result<()> { - use std::io::Write; - let message = self.context.format_rfc3164(severity, Some(message)); - write!(&mut self.writer, "{}", message)?; - self.writer.write_all(&[0; 1])?; - Ok(()) - } - - /// Send a message with the given severity as defined in RFC-5424. - pub fn send_rfc5424, M: std::fmt::Display>( - &mut self, - severity: Severity, - msgid: Option, - elements: Vec, - message: M, - ) -> io::Result<()> { - use std::io::Write; - let message = self - .context - .format_rfc5424(severity, msgid, elements, Some(message)); - write!(&mut self.writer, "{}", message)?; + /// Send a pre-formatted message. + pub fn send_formatted(&mut self, formatted: &[u8]) -> io::Result<()> { + self.writer.write_all(formatted)?; self.writer.write_all(&[0; 1])?; Ok(()) } @@ -188,3 +147,5 @@ impl UnixStreamSender { self.writer.flush() } } + +impl_syslog_sender_common!(UnixStreamSender); diff --git a/src/severity.rs b/src/severity.rs index df9c7ad..217e21e 100644 --- a/src/severity.rs +++ b/src/severity.rs @@ -17,7 +17,7 @@ use std::str::FromStr; /// Syslog severity as defined in [RFC 5424] (The Syslog Protocol). /// -/// [RFC 5424]: https://tools.ietf.org/html/rfc5424. +/// [RFC 5424]: https://datatracker.ietf.org/doc/html/rfc5424. #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] #[repr(u8)] pub enum Severity {