Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Adding Slog Logger to Actix Web
Praveen Chaudhary
Praveen Chaudhary

Posted on

     

Adding Slog Logger to Actix Web

We will learn how to use slog logger for logging in Actix web.
Actix web is a powerful, pragmatic, and extremely fast web framework for Rust andSlog is an ecosystem of reusable components for structured, extensible, composable logging for Rust. We will be using two crates of slog :slog-async andslog-term with the core Slog Core Package.

Why Slog over default log crate?

  • extensible
  • composable
  • flexible
  • structured and both human and machine-readable
  • contextual

Crates used

Crated Version and Code

Simply paste the code in thecargo.toml file

slog = "2.7.0"slog-term = "2.9.0"slog-async = "2.7.0"
Enter fullscreen modeExit fullscreen mode

Default template for Actix web

It is a defaulthello world program of Actix web

use actix_web::{ web, App, HttpServer};async fn index() -> &'static str {    "Hello world!"}#[actix_web::main]async fn main() -> std::io::Result<()> {    println!("Starting the server at 127.0.0.1:8080");    HttpServer::new(|| {        App::new()            .service(web::resource("/index.html").to(|| async { "Hello world!" }))            .service(web::resource("/").to(index))    })    .bind(("127.0.0.1", 8080))?    .run()    .await}
Enter fullscreen modeExit fullscreen mode

Configure Logger

use slog;use slog::{Logger,o,Drain,info};use slog_term;use slog_async;fn configure_log()->Logger{    let decorator = slog_term::TermDecorator::new().build();    let console_drain = slog_term::FullFormat::new(decorator).build().fuse();    // It is used for Synchronization    let console_drain = slog_async::Async::new(console_drain).build().fuse();    // Root logger    slog::Logger::root(console_drain,o!("v"=>env!("CARGO_PKG_VERSION")))}
Enter fullscreen modeExit fullscreen mode

Let's break the configuration function and understand what is happening behind the scene.

  • TermDecorator Decorator : IT is used for formatting terminal output implemented usingterm crate. This decorator will add nice formatting to the logs it’s outputting.Note It does not deal with serialization so is !Sync. Run in a separate thread with slog_async::Async. We will be using the slog async with it. We canother decorator like CompactFormat, PlainRecordDecorator etc according to need.
  • FullFormat : It is a Drain that will takeDecorator as an argument, used for terminal output. Decorator is for formatting and Drain is for outputting.
  • Synchronization via Async Slog : They are three ways slog to do synchronization out of whichPlainSyncDecorator andslog_async are the efficient one depending on the need. Other than the two, the lastSynchronization via Mutex is not efficient. You can read morehere. We are using the synchronization with slog_async.
  • Logger::root :Logger is used to execute logging statements. It takes two arguments
    1. drain - destination where to forward logging Records for processing.
    2. context - list of key-value pairs associated with it.
  • o! : Macro for building group of key-value pairs used as a content in Logger.

fuse() : It is used for panicking if something went wrong. It is necessary to call fuse as the root logger must take a Drain which is error free.

Passing log instance to the handlers

Add the following line of code in main function

let log = configure_log();
Enter fullscreen modeExit fullscreen mode

It will configure the logger and ready to use now.

Passing a log instance

HttpServer::new(move || {        App::new()            .app_data(web::Data::new(log.clone()))            .service(web::resource("/index.html").to(|| async { "Hello world!" }))            .service(web::resource("/").to(index))    })    .bind(("127.0.0.1", 8080))?    .run()    .await
Enter fullscreen modeExit fullscreen mode

web::Data::new(log.clone()) : It is an application data stored with App::app_data() method available through the HttpRequest::app_data method at runtime.

Accessing the Log instance in function handlers

async fn index(log: web::Data<Logger>) -> &'static str {    info!(log,        "Inside Hello World"    );    "Hello world!"}
Enter fullscreen modeExit fullscreen mode

info! : It is a macro used for the building Info Level Record Or Context(key-value pair) used by Logger to output. They are a bunch of macros you can be used fordifferent level records

log: web::Data : -
Essentials helper functions and types for application registration.

Request Extractors

  • Data: Application data item
  • ReqData: Request-local data item
  • Path: URL path parameters / dynamic segments
  • Query: URL query parameters
  • Header: Typed header
  • Json: JSON payload
  • Form: URL-encoded payload
  • Bytes: Raw payload

We are using theData method to access the application data initialised in server instance in main function.

Complete Code

use actix_web::{web, App, HttpServer};// IT is used as a logging middleware. We can even use the default logger with actix.use slog;use slog::{Logger,o,Drain,info};use slog_term;use slog_async;fn configure_log()->Logger{    // Formatting the output https://docs.rs/slog-term/2.9.0/slog_term/index.html#    let decorator = slog_term::TermDecorator::new().build();    // Drain for outputting https://docs.rs/slog-term/2.9.0/slog_term/index.html#structs    // fuse is used for panicking if something went wrong. It is necessary to call fuse as the root logger must take a Drain which is error free.    let console_drain = slog_term::FullFormat::new(decorator).build().fuse();    // It is used for Synchronization https://docs.rs/slog-term/2.9.0/slog_term/index.html#structs    let console_drain = slog_async::Async::new(console_drain).build().fuse();    slog::Logger::root(console_drain,o!("v"=>env!("CARGO_PKG_VERSION")))}async fn index(log: web::Data<Logger>) -> &'static str {    info!(log,        "Inside Hello World"    );    "Hello world!"}#[actix_web::main]async fn main() -> std::io::Result<()> {    let log = configure_log();    info!(log,        "Starting the server at http://127.0.0.1:8080/"    );    HttpServer::new(move || {        App::new()            .app_data(web::Data::new(log.clone()))            .service(web::resource("/index.html").to(|| async { "Hello world!" }))            .service(web::resource("/").to(index))    })    .bind(("127.0.0.1", 8080))?    .run()    .await}
Enter fullscreen modeExit fullscreen mode

Logging Output

Image description

Source Code

GitHub Source Code

Added Comments for your quick revision and understanding.

Feel free to ask any questions or provide suggestions. I am too learning. So will be glad to get your feedback. Happy Hacking! Rustaceans!

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
beastabhi199 profile image
Abhishek Chaudhary🇮🇳
  • Education
    Bcom (Hons)
  • Work
    CA Aspirant
  • Joined

Very interesting and easy to understand.. Thanks for sharing this ..
💯💯😍😍🔥

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

SSE at Infoedge | Prev - SDE 2 - Sigmoid, SDE at India Today| Rust🦀 and Python🐍 enthusiast | Full stack developer | API & App developer| Performance & Acceptance Tester
  • Location
    Faridabad, Haryana, India
  • Education
    Guru Gobind Singh Indraprastha University
  • Pronouns
    He/Him
  • Work
    SSE at InfoEdge
  • Joined

More fromPraveen Chaudhary

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp