Crate tracing_rfc_5424

source ·
Expand description

A tracing-subscriber Layer implementation for sending tracing Spans and Events to a syslog daemon

Introduction

The tracing crate is a “scoped, structured logging and diagnostics system”. It provides a superset of the features offered by logging crates such as fern and log4rs particularly suited to asynchronous programming. Of particular interest here is that it makes a very clear distinction between producers of events & their consumers (Subscribers, in tracing parlance); so much so that the tracing crate provides no support for consuming events, other than the definition of the Subscriber trait.

The tracing-subscriber crate (also part of the 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 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 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, and so on.

This could easily give rise to a geometric explosion in types: LogFile, LogFileWithStdout, LogFileWithLogStash, LogFileWithLogStashAndStdout, and so forth. The idea behind Layers is to decompose each facet of event handling into its own type, and then “stack them up” in a Subscriber as the application developer desires. In a sense, this design pattern is reminiscent of Alexanrescu’s concept of traits classes in C++– a way of decomposing functionality into distinct facets and composing them linearly rather than geometrically.

This crate provides a Layer implementation for dispatching tracing events to a syslog daemon.

Usage

tracing-syslog’s Layer comes with sane defaults:

use tracing::info;
use tracing_rfc_5424::{
    layer::Layer,
    rfc5424::Rfc5424,
    tracing::TrivialTracingFormatter,
    transport::UdpTransport,
};
use tracing_subscriber::registry::Registry;
use tracing_subscriber::layer::SubscriberExt; // Needed to get `with()`

// The default configuration is to format syslog messages as per RFC 5424
// and to send them via UDP to port 514 on the localhost.
let subscriber = Registry::default()
    .with(Layer::<tracing_subscriber::Registry, Rfc5424, TrivialTracingFormatter, UdpTransport>::try_default().unwrap());

info!("Hello, world!");

Will produce syslog entries that look something like this:

Jun 23 16:10:55 hostname appname[pid] Hello, world!

That said, the transport layer, the syslog formatting and the means of formatting tracing Events & Spans are configurable:

use tracing::info;
use tracing_rfc_5424::layer::Layer;
use tracing_rfc_5424::transport::UdpTransport;
use tracing_subscriber::registry::Registry;
use tracing_subscriber::layer::SubscriberExt; // Needed to get `with()`

// The default configuration is to format syslog messages as per RFC 5424
// and to send them via UDP to port 514 on the localhost.
let subscriber = Registry::default().with(Layer::with_transport(
    UdpTransport::new("some.other.host:5514").unwrap()));

info!("Hello, world!");

Will send the syslog packet to a daemon on port 5514 on some.other.host.

Modules