syslog
A lightweight Rust crate for sending log messages to syslog over Unix sockets, UDP, or TCP.
Repository Health
Technical Analysis
syslog is a small, focused Rust library for sending log messages to a local or remote syslog daemon. It supports connecting over Unix domain sockets (for local syslog via /dev/log or /var/run/syslog), UDP, or TCP, and formats messages according to either the classic RFC 3164 (BSD syslog) format or the newer, structured RFC 5424 format.
The crate’s Logger type implements the standard log::Log trait through its BasicLogger wrapper, so it can be dropped in as a backend for the ubiquitous log facade with a single log::set_boxed_logger call, making it straightforward to route an existing application’s log output straight to the system syslog service.
What You Get
- A generic
Logger<Backend, Formatter>struct with severity-level methods (emerg,alert,crit,err,warning,notice,info,debug) Formatter3164andFormatter5424types implementing theLogFormattrait for RFC 3164 and RFC 5424 message encoding respectively- Connection helpers (
unix,unix_custom,udp,tcp) that return a ready-to-useLoggerover the chosen transport - A
BasicLoggeradapter implementinglog::Logso the crate can act as a backend for the standardlogfacade - A typed
Facilityenum covering every standard syslog facility, withFromStrparsing from names like “local0” or “daemon”
Common Use Cases
- Rust daemons and system services that need to emit logs to the local syslog service consumed by journald or rsyslog
- Applications shipping logs to a centralized remote syslog collector over TCP or UDP
- Services that need structured, machine-parseable RFC 5424 log entries with custom structured-data fields
Under The Hood
Architecture: The crate is organized into four small modules — lib.rs holds the public Logger<Backend, Formatter> struct plus the unix/unix_custom/udp/tcp connection constructors and the init* convenience functions that wire a logger into the log crate; format.rs defines the LogFormat trait and its two implementations, Formatter3164 and Formatter5424; facility.rs holds the Facility enum; and errors.rs defines a small Error enum unifying I/O and initialization failures. The central abstraction is LoggerBackend, an enum over the four possible transports (Unix datagram, Unix stream fallback, UDP socket, buffered TCP stream) that implements std::io::Write, letting Logger stay generic over the backend while unix() transparently falls back from a datagram to a stream socket when EPROTOTYPE is returned (a quirk of some syslog daemon implementations). BasicLogger wraps a Logger<LoggerBackend, Formatter3164> in an Arc<Mutex<..>> and implements log::Log, bridging the crate into the ecosystem-standard logging facade.
Tech Stack: The crate targets Rust with a minimal dependency footprint declared in Cargo.toml: log (for the Log/Record/Level trait integration), time (for RFC 3164 timestamp formatting, using its local-offset and formatting features), libc (for the raw EPROTOTYPE errno check during Unix socket fallback), and hostname (for automatic hostname detection in formatter defaults). Platform-specific code is gated behind #[cfg(unix)]/#[cfg(not(unix))], with non-Unix builds returning an UnsupportedPlatform error from the Unix-socket-only functions rather than failing to compile.
Code Quality: src/tests.rs (compiled only under #[cfg(test)]) exercises the Unix-socket path end-to-end by spinning up a real UnixListener, writing all eight severity levels through a Logger, and asserting the received bytes match the RFC 3164 wire format; format.rs carries its own unit tests for RFC 5424 structured-data escaping and for the Default impls of both formatters. Error handling is centralized in a single Error enum (Initialization, Write, Io) with std::error::Error and Display impls rather than relying on an external crate like thiserror. There is no test coverage for the UDP or TCP transport paths, and no fuzzing or property-based testing.
API Design: The public surface is small and consistent: three top-level constructors (unix, udp, tcp) each return a Result<Logger<..>>, and the Formatter3164/Formatter5424 structs are plain, publicly-fielded structs (facility, hostname, process, pid) that can be built directly or via Default::default(), which auto-detects the process name, PID, and hostname. Getting started requires constructing a formatter struct and calling one connection function — modest boilerplate for a systems-level logging crate. The init/init_unix/init_udp/init_tcp family additionally wires straight into the log crate’s global logger in one call, and the crate’s own module-level rustdoc includes both a standalone and a log-crate-integrated example.