[[https://github.com/sp1ff/syslog-tracing/tracing-rfc-5424][tracing-rfc-5424]] is a [[https://docs.rs/tracing-subscriber/latest/tracingsubscriber/index.html][tracing-subscriber]] [[https://docs.rs/tracing-subscriber/latest/tracingsubscriber/layer/trait.Layer.html][Layer]] implementation that sends [[https://docs.rs/tracing/latest/tracing/index.html][tracing ]][[https://docs.rs/tracing/latest/tracing/struct.Event.html][Event]]s & [[https://docs.rs/tracing/latest/tracing/struct.Span.html][Span]]s to a [[https://en.wikipedia.org/wiki/Syslog][syslog]] [[https://en.wikipedia.org/wiki/Daemon_(computing)][daemon]].
The [[https://docs.rs/tracing/latest/tracing/index.html][tracing]] crate is a "scoped, structured logging and diagnostics system". It provides a superset of the features offered by logging crates such as [[https://docs.rs/fern/latest/fern/index.html][fern]] and [[https://docs.rs/log4rs/latest/log4rs/][log4rs]] particularly suited to asynchronous programming. Of particular interest is that it makes a very clear distinction between producers of events & their consumers ([[https://docs.rs/tracing/0.1.34/tracing/trait.Subscriber.html][Subscriber]]s, in [[https://docs.rs/tracing/latest/tracing/index.html][tracing]] parlance); so much so that the [[https://docs.rs/tracing/latest/tracing/index.html][tracing]] crate provides no support for consuming events, other than the definition of the [[https://docs.rs/tracing/0.1.34/tracing/trait.Subscriber.html][Subscriber]] trait.
The [[https://docs.rs/tracing-subscriber/0.3.11/tracingsubscriber/index.html][tracing-subscriber]] crate (also part of the [[https://tokio.rs/][Tokio]] project) provides a few basic implementations along with "utilities for implementing and composing tracing subscribers." A key notion introduced by this crate is the idea of a [[https://docs.rs/tracing-subscriber/0.3.11/tracingsubscriber/layer/trait.Layer.html][Layer]]. "Unlike Subscribers, which implement a complete strategy for how trace data is collected, Layers provide modular implementations of specific behaviors." The concern here is that, in general, a consumer of [[https://docs.rs/tracing/latest/tracing/index.html][tracing]] event data may want to do various things at the same time with that data: write it to a log file, just write it to =stdout=, shuttle it off to a log collection daemon, produce metrics based on it, and so on.
This could easily give rise to a geometric explosion in types: =LogFile=, =LogFileWithStdout=, =LogFileWithLogStash=, =LogFileWithLogStashAndStdout=, and so forth. The idea behind [[https://docs.rs/tracing-subscriber/0.3.11/tracingsubscriber/layer/trait.Layer.html][Layer]]s is to decompose each facet of event handling into its own type, and then "stack them up" in a [[https://docs.rs/tracing/0.1.34/tracing/trait.Subscriber.html][Subscriber]] as the application developer desires. In a sense, this design pattern is reminiscent of [[https://en.wikipedia.org/wiki/AndreiAlexandrescu][Alexandrescu]]'s concept of [[https://erdani.com/publications/traits.html][traits classes]] in C++-- a way of decomposing functionality into orthogonal facets and composing them linearly rather than geometrically. * Prerequisites
Other than [[https://github.com/tokio-rs/tracing][tracing]] and a syslog daemon, none. [[https://github.com/sp1ff/syslog-tracing/tracing-rfc-5424][tracing-rfc-5424]] was developed against rust 1.58.1, although [[https://github.com/tokio-rs/tracing][tracing]] requires 1.49. * Usage
I'm in the process of submitting [[https://github.com/sp1ff/syslog-tracing][tracing-rfc-5424]] to [[https://crates.io][crates.io]] at the moment, so you'll have to pull it directly from here:
[dependencies] tracing-rfc-5424 = { git = "https://github.com/sp1ff/syslog-tracing" }
** Examples
Then, to talk to a local syslog daemon over UDP:
use tracing::info;
use tracingrfc5424::{
layer::Layer, rfc5424::Rfc5424, tracing::TrivialTracingFormatter, transport::UdpTransport,
};
use tracing_subscriber::{
layer::SubscriberExt, // Needed to get with()
registry::Registry,
};
// Setup the subsriber...
let subscriber = Registry::default()
.with(Layer::
info!("Hello, world!"); // Will produce a syslog line something like: // Jun 23 16:10:55 my-host my-app[pid] Hello, world!
This is a preliminary release; the version number (0.0.x) is intended to convey that. Additional features to be implemented:
The name =tracing-syslog= seemed most natural to me, but has been already claimed (by an empty project) on [[https://crates.io][crates.io]]. I've reached-out to the author, but haven't heard anything back. I moved on to =syslog-tracing=, but before I published the crate, that was claimed, [[https://crates.io/crates/syslog-tracing][too]] (by an implementation with a very different implementation apporach-- FFI straight to the =libc= support for syslog). I wound-up re-factoring the repo into a library package & a test package and I've taken the opportunity to rename the library crate to =tracing-rfc-5424= (after the RFC governing the modern syslog message format).
This project got started when I needed to log to a local syslog daemon from an app that uses [[https://github.com/tokio-rs/tracing][tracing]]. I started down the same path recommended by [[https://users.rust-lang.org/u/endsofthreads/summary][David Barsky]] in this [[https://users.rust-lang.org/][rust-lang]] [[https://users.rust-lang.org/t/using-tracing-with-syslog/64499][thread]]: "Hey, there's this [[https://github.com/Geal/rust-syslog][syslog]] [[https://docs.rs/syslog/latest/syslog/][crate]], why not just call it from a Layer you write?"
I started down that path and found that that crate's =Logger= abstraction takes =&mut self= on all it's methods, which makes it difficult to use in a =Layer= implementation (which only gets =&self=). I opened an issue [[https://github.com/Geal/rust-syslog/issues/68][here]]. "No problem," I thought, "the transport piece is easy. I can still make make use of the underlying components. Hmmmm.... what the heck are RFCs 5424 & 3164? The crate gives no guidance on which to use, so I need to understand them. Oh... [[https://docs.rs/syslog/latest/syslog/struct.Formatter5424.html][Formatter5424]] represents the hostname as a =String=, well having read the RFC I know that's not right... oh the heck with it."
Bugs, comments, problems, criticism, PRs, feature requests &c welcome at [[mailto:sp1ff@pobox.com][sp1ff@pobox.com]] and in the [[https://github.com/sp1ff/syslog-tracing/issues][issues]].