From 2839aec0404b386b35d969dff9440e5102cf9ac0 Mon Sep 17 00:00:00 2001 From: Nick Bland Date: Tue, 12 Mar 2024 23:22:27 +1000 Subject: [PATCH] Chapter 4.5 + Add in logging + Move logging functions to new telemetry.rs file --- Cargo.lock | 144 +++++++++++++++++++++++++++++++++++- Cargo.toml | 4 + src/lib.rs | 1 + src/main.rs | 6 +- src/routes/subscriptions.rs | 14 +++- src/startup.rs | 2 + src/telemetry.rs | 19 +++++ 7 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 src/telemetry.rs diff --git a/Cargo.lock b/Cargo.lock index 868c171..8a00784 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -787,6 +787,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" @@ -1154,9 +1164,22 @@ dependencies = [ "serde", "sqlx", "tokio", + "tracing", + "tracing-bunyan-formatter", + "tracing-log 0.1.4", + "tracing-subscriber", "uuid", ] +[[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" @@ -1245,6 +1268,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-bigint-dig" version = "0.8.4" @@ -1361,6 +1394,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.12.1" @@ -1521,8 +1560,17 @@ checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.3.7", + "regex-syntax 0.7.5", +] + +[[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]] @@ -1533,9 +1581,15 @@ checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.5", ] +[[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.5" @@ -1812,6 +1866,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2181,6 +2244,16 @@ dependencies = [ "syn 2.0.32", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "time" version = "0.3.28" @@ -2319,6 +2392,24 @@ dependencies = [ "syn 2.0.32", ] +[[package]] +name = "tracing-bunyan-formatter" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5c266b9ac83dedf0e0385ad78514949e6d89491269e7065bee51d2bb8ec7373" +dependencies = [ + "ahash", + "gethostname", + "log", + "serde", + "serde_json", + "time", + "tracing", + "tracing-core", + "tracing-log 0.1.4", + "tracing-subscriber", +] + [[package]] name = "tracing-core" version = "0.1.31" @@ -2326,6 +2417,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log 0.2.0", ] [[package]] @@ -2411,6 +2543,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" diff --git a/Cargo.toml b/Cargo.toml index 31809b5..0fc11a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,10 @@ serde = { version = "1", features = ["derive"] } config = { version = "0.13", default-features = false, features = ["yaml"] } 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" [dependencies.sqlx] version = "0.7" diff --git a/src/lib.rs b/src/lib.rs index 5d1dce7..9079ef9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ pub mod configuration; pub mod routes; pub mod startup; +pub mod telemetry; diff --git a/src/main.rs b/src/main.rs index 6d94cba..1cfaac9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,10 +1,14 @@ use mail_app::configuration::get_configuration; use mail_app::startup::run; -use sqlx::PgPool; +use mail_app::telemetry::{get_subscriber, init_subscriber}; +use sqlx::postgres::PgPool; use std::net::TcpListener; #[tokio::main] async fn main() -> Result<(), std::io::Error> { + let subscriber = get_subscriber("mail_app".into(), "info".into()); + init_subscriber(subscriber); + let configuration = get_configuration().expect("Failed to read configuration"); let connection_pool = PgPool::connect(&configuration.database.connection_string()) .await diff --git a/src/routes/subscriptions.rs b/src/routes/subscriptions.rs index 936f478..bdd930b 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; #[derive(serde::Deserialize)] @@ -10,6 +11,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 to database"); match sqlx::query!( r#" INSERT INTO subscriptions (id, email, name, subscribed_at) @@ -21,11 +32,12 @@ pub async fn subscribe(form: web::Form, pool: web::Data) -> Ht Utc::now() ) .execute(pool.get_ref()) + .instrument(query_span) .await { Ok(_) => HttpResponse::Ok().finish(), Err(e) => { - println!("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 49563aa..b53e6b9 100644 --- a/src/startup.rs +++ b/src/startup.rs @@ -1,5 +1,6 @@ use crate::routes::{health_check, subscribe}; use actix_web::dev::Server; +use actix_web::middleware::Logger; use actix_web::{web, App, HttpServer}; use sqlx::PgPool; use std::net::TcpListener; @@ -8,6 +9,7 @@ pub fn run(listener: TcpListener, db_pool: PgPool) -> Result impl Subscriber + Send + Sync { + let env_filter = + EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(env_filter)); + let formatting_layer = BunyanFormattingLayer::new(name, std::io::stdout); + Registry::default() + .with(env_filter) + .with(JsonStorageLayer) + .with(formatting_layer) +} + +pub fn init_subscriber(subscriber: impl Subscriber + Send + Sync) { + LogTracer::init().expect("Failed to set logger."); + set_global_default(subscriber).expect("Failed to set subscriber."); +}