diff --git a/Cargo.lock b/Cargo.lock index 8b9efd0..f58243f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -731,6 +731,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -1057,6 +1067,15 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "md-5" version = "0.10.5" @@ -1133,6 +1152,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-traits" version = "0.2.16" @@ -1211,6 +1240,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.11.2" @@ -1386,8 +1421,17 @@ checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.3.6", + "regex-syntax 0.7.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -1398,9 +1442,15 @@ checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.4", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.7.4" @@ -1633,6 +1683,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1860,6 +1919,16 @@ dependencies = [ "syn 2.0.29", ] +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" version = "0.3.27" @@ -1994,9 +2063,39 @@ dependencies = [ "cfg-if", "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.29", +] + +[[package]] +name = "tracing-bunyan-formatter" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5c266b9ac83dedf0e0385ad78514949e6d89491269e7065bee51d2bb8ec7373" +dependencies = [ + "ahash 0.8.3", + "gethostname", + "log", + "serde", + "serde_json", + "time", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", +] + [[package]] name = "tracing-core" version = "0.1.31" @@ -2004,6 +2103,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -2077,6 +2206,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2336,6 +2471,10 @@ dependencies = [ "serde", "sqlx", "tokio", + "tracing", + "tracing-bunyan-formatter", + "tracing-log", + "tracing-subscriber", "uuid", ] diff --git a/Cargo.toml b/Cargo.toml index 01ec5e6..a730dd3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,10 @@ config = { version = "0.13", default-features = false, features = ["yaml"] } sqlx = { version = "0.6", default-features = false, features = ["runtime-actix-rustls", "macros", "postgres", "uuid", "chrono", "migrate"] } uuid = { version = "1", features = ["v4"] } chrono = { version = "0.4.22", default-features = false, features = ["clock"] } +tracing = { version = "0.1", features = ["log"] } +tracing-subscriber = { version = "0.3", features = ["registry", "env-filter"] } +tracing-bunyan-formatter = "0.3" +tracing-log = "0.1" [dev-dependencies] reqwest = { version = "0.11", features = ["json"] } diff --git a/src/main.rs b/src/main.rs index 1d68d70..a747986 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,23 @@ use sqlx::PgPool; use std::net::TcpListener; +use tracing::subscriber::set_global_default; +use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer}; +use tracing_log::LogTracer; +use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; use zero2prod::{configurations::get_configuration, startup::run}; #[tokio::main] async fn main() -> Result<(), std::io::Error> { + // Logger setup + LogTracer::init().expect("Failed to set logger"); + // Info or above will be logged if the RUST_LOG environment variable is not set + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + let foirmatting_layer = BunyanFormattingLayer::new("zero2prod".into(), std::io::stdout); + let subscriber = Registry::default() + .with(env_filter) + .with(JsonStorageLayer) + .with(foirmatting_layer); + set_global_default(subscriber).expect("Failed to set subscriber"); // We want to panic if we cannot read the configuration let configuration = get_configuration().expect("Failed to read configurations"); let connection = PgPool::connect(&configuration.database.get_connnection_string()) diff --git a/src/routes/subscriptions.rs b/src/routes/subscriptions.rs index 7dfa4e2..25f8f95 100644 --- a/src/routes/subscriptions.rs +++ b/src/routes/subscriptions.rs @@ -1,6 +1,7 @@ use actix_web::{web, HttpResponse}; use chrono::Utc; use sqlx::PgPool; +use tracing::Instrument; use uuid::Uuid; #[allow(dead_code)] @@ -11,6 +12,16 @@ pub struct FormData { } pub async fn subscribe(form: web::Form, pool: web::Data) -> HttpResponse { + let request_id = Uuid::new_v4(); + let request_span = tracing::info_span!( + " Adding a new subscriber", + %request_id, + subscriber_email = %form.email, + subscriber_name = %form.name, + ); + let _request_span_guard = request_span.enter(); + + let query_span = tracing::info_span!("Saving new subscriber details in the database"); match sqlx::query!( r#" INSERT INTO subscriptions (id, email, name, subscribed_at) @@ -24,11 +35,12 @@ pub async fn subscribe(form: web::Form, pool: web::Data) -> Ht // We use `get_ref` to get an immutable reference to the `PgConnection` // wrapped by `web::Data`. .execute(pool.get_ref()) + .instrument(query_span) .await { Ok(_) => HttpResponse::Ok().finish(), Err(e) => { - eprintln!("Failed to execute query: {}", e); + tracing::error!("Failed to execute query: {:?}", e); HttpResponse::InternalServerError().finish() } } diff --git a/src/startup.rs b/src/startup.rs index 1273de5..991fbd3 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -1,6 +1,6 @@ use std::net::TcpListener; -use actix_web::{dev::Server, web, App, HttpServer}; +use actix_web::{dev::Server, middleware::Logger, web, App, HttpServer}; use sqlx::PgPool; use crate::routes::{health_check, subscribe}; @@ -9,6 +9,7 @@ pub fn run(listener: TcpListener, db_pool: PgPool) -> Result