diff --git a/src/lib.rs b/src/lib.rs index 7d0609b..fc9c78d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod configuation; pub mod routes; +pub mod telemetry; diff --git a/src/main.rs b/src/main.rs index f707dad..8045c98 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,32 +1,17 @@ -use std::{net::SocketAddr, time::Duration}; +use std::net::SocketAddr; -use axum::{ - body::Bytes, - extract::MatchedPath, - http::{HeaderMap, Request}, - response::Response, -}; use sqlx::postgres::PgPoolOptions; use tokio::net::TcpListener; -use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer}; -use tracing::{info_span, subscriber::set_global_default, Span}; -use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer}; -use tracing_log::LogTracer; -use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; -use zero2prod::{configuation::get_configuration, routes::route}; +use zero2prod::{ + configuation::get_configuration, + routes::route, + telemetry::{get_subscriber, init_subscriber}, +}; #[tokio::main] async fn main() -> Result<(), std::io::Error> { - LogTracer::init().expect("Failed to set logger"); - let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()); - let formatting_layer = BunyanFormattingLayer::new("zero2prod".into(), std::io::stdout); - let subscriber = Registry::default() - .with(env_filter) - .with(JsonStorageLayer) - .with(formatting_layer); - - set_global_default(subscriber).expect("Failed to set subscriber."); - + let subscriber = get_subscriber("zero2prod", "info"); + init_subscriber(subscriber); let configuation = get_configuration().expect("Failed to read configuation."); let pool = PgPoolOptions::new() .connect(&configuation.database.to_string()) @@ -37,16 +22,5 @@ async fn main() -> Result<(), std::io::Error> { .await .expect("Failed to bind port 8000."); - let route = route(pool) - .layer(TraceLayer::new_for_http().make_span_with(|request: &Request<_>| { - let matched_path = request.extensions().get::().map(MatchedPath::as_str); - info_span!("http-request", method = ?request.method(), matched_path, some_other_field= tracing::field::Empty,) - }) - .on_request(|_request: &Request<_>, _span: &Span | {}) - .on_response(|_response: &Response<_>, _latency: Duration, _span:&Span|{}) - .on_body_chunk(|_chunk: &Bytes, _latency: Duration, _span:&Span|{}) - .on_eos(|_trailers: Option<&HeaderMap>, _stream_duration: Duration, _span:&Span| {}) - .on_failure(|_error: ServerErrorsFailureClass, _latency: Duration, _span:&Span| {}) - ); - axum::serve(listener, route).await + axum::serve(listener, route(pool)).await } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 8da2be0..2cf8c9e 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,7 +1,13 @@ mod health_check; mod subscibtions; +use std::time::Duration; + use axum::{ + body::Bytes, + extract::MatchedPath, + http::{HeaderMap, Request}, + response::Response, routing::{get, post}, Router, }; @@ -9,10 +15,22 @@ use axum::{ pub use health_check::*; use sqlx::PgPool; pub use subscibtions::*; +use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer}; +use tracing::{info_span, Span}; pub fn route(state: PgPool) -> Router { Router::new() .route("/health_check", get(health_check)) .route("/subscriptions", post(subscribe)) .with_state(state) + .layer(TraceLayer::new_for_http().make_span_with(|request: &Request<_>| { + let matched_path = request.extensions().get::().map(MatchedPath::as_str); + info_span!("http-request", method = ?request.method(), matched_path, some_other_field= tracing::field::Empty,) + }) + .on_request(|_request: &Request<_>, _span: &Span | {}) + .on_response(|_response: &Response<_>, _latency: Duration, _span:&Span|{}) + .on_body_chunk(|_chunk: &Bytes, _latency: Duration, _span:&Span|{}) + .on_eos(|_trailers: Option<&HeaderMap>, _stream_duration: Duration, _span:&Span| {}) + .on_failure(|_error: ServerErrorsFailureClass, _latency: Duration, _span:&Span| {}) + ) } diff --git a/src/telemetry.rs b/src/telemetry.rs new file mode 100644 index 0000000..3e5ac7a --- /dev/null +++ b/src/telemetry.rs @@ -0,0 +1,18 @@ +use tracing::{subscriber::set_global_default, Subscriber}; +use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer}; +use tracing_log::LogTracer; +use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; + +pub fn get_subscriber(name: &str, env_filter: &str) -> impl Subscriber + Sync + Send { + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| env_filter.into()); + let formatting_layer = BunyanFormattingLayer::new(name.into(), std::io::stdout); + Registry::default() + .with(env_filter) + .with(JsonStorageLayer) + .with(formatting_layer) +} + +pub fn init_subscriber(subscriber: impl Subscriber + Sync + Send) { + LogTracer::init().expect("Failed to set logger"); + set_global_default(subscriber).expect("Failed to set subscriber."); +}