Example

We will crate a tiny application that writes logs to a file and to a console. Create a new crate and add the following dependencies:

slog = "2.4"
slog-async = "2.3"
slog-json = "2.3"
slog-term = "2.4"

We need slog as the main logging crate for the application. The slog-async crate helps to move log processing to a separate thread. slog-json provides a logger that writes records in JSON format. slog-term provides formats to write messages to a Terminal.

We will import the following types:

use slog::{crit, debug, error, Drain, Duplicate, Level, LevelFilter};
use slog_async::Async;
use slog_term::{CompactFormat, PlainDecorator};
use slog_json::Json;
use std::fs::OpenOptions;
use std::sync::Mutex;

From the main slog crate, we will use the crit, debug, and error macros, which are an alternative to the logging macro of the log crate. Drain is the main trait that provides logging functionality. Ultimately, we must create a Drain instance to log something. Duplicate is a kind of Drain that duplicates records to two Drain instances. Level and LevelFilter allow us to filter records by desired level.

From the slog-async crate, we will use the Async type, which is a Drain that moves records processing to a separate thread. PlainDecorator, which is imported from the slog-term crate, prints logs without any coloring. Also, we imported the CompactFormat type, which is a Drain that writes records in a short format.From the slog-json crate, we imported the Json form of Drain that writes logs in JSON format.

Please note that the Drain trait has a default implementation for Mutex values that contains a value that has already implemented the Drain trait. It allows us to wrap any Drain with a Mutex to make it safe for use in multiple threads. The OpenOptions type is imported to open a file for writing and truncate the contents of it.

Now, we can add the main function with sample logging:

fn main() {
let log_path = "app.log";
let file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(log_path)
.unwrap();

let drain = Mutex::new(Json::default(file)).fuse();
let file_drain = LevelFilter::new(drain, Level::Error);

let decorator = PlainDecorator::new(std::io::stderr());
let err_drain = CompactFormat::new(decorator).build().fuse();

let drain_pair = Duplicate::new(file_drain, err_drain).fuse();
let drain = Async::new(drain_pair).build().fuse();

let log = slog::Logger::root(drain, slog::o!(
"version" => env!("CARGO_PKG_VERSION"),
"host" => "localhost",
"port" => 8080,
));
debug!(log, "started");
debug!(log, "{} workers", 2;);
debug!(log, "request"; "from" => "example.com");
error!(log, "worker failed"; "worker_id" => 1);
crit!(log, "server can't continue to work");
}

This function opens a file and creates two Drain instances. The first is a Json wrapped with a Mutex, because Json is not a thread-safe type. We also wrap it with LevelFilter to filter messages at a level lower than Error.

After this, we used PlainDecorator to write logs to the stderr stream. It implements the Decorator trait, which can be used as a stream for creating Drain instances. We wrap it with CompactFormat and now we have two Drain instances that we will combine.

We use Duplicate to duplicate records to the two created Drain instances, but we also wrap it with Async to move logs that are processing to a separate thread. Now, we can create a Logger instance and fill it with basic information about the application.

We use the root method to create the root logger. This method can also get a map of values, which will be added to records. We used the o! macro to create a map. After this, we added calls of different macros to show you how to use a structural logger.

Any logging macro expects some arguments—a reference to a Logger instance, a message, optional parameters to fill a message, or a key-value map with extra parameters that can be extracted later from logs for analysis.

The demo application is ready and we can start to test it.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.98.250