syslog

A lightweight Rust crate for sending log messages to syslog over Unix sockets, UDP, or TCP.

Library
Cargo
v7.0.0
124stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
36/100Needs Attention
Development Activity0
Maintenance0
Community72
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
65/100Good
Architecture70
Code Quality60
Innovation65
Learning Curve75

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)
  • Formatter3164 and Formatter5424 types implementing the LogFormat trait for RFC 3164 and RFC 5424 message encoding respectively
  • Connection helpers (unix, unix_custom, udp, tcp) that return a ready-to-use Logger over the chosen transport
  • A BasicLogger adapter implementing log::Log so the crate can act as a backend for the standard log facade
  • A typed Facility enum covering every standard syslog facility, with FromStr parsing 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.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search