finished logging chapter

This commit is contained in:
Andre Heber
2024-02-19 11:12:46 +01:00
parent a0aa12872d
commit 39b6e11885
9 changed files with 317 additions and 30 deletions

View File

@ -1,4 +1,5 @@
use config::Config;
use secrecy::{ExposeSecret, Secret};
#[derive(serde::Deserialize)]
pub struct Settings {
@ -9,25 +10,25 @@ pub struct Settings {
#[derive(serde::Deserialize)]
pub struct DatabaseSettings {
pub username: String,
pub password: String,
pub password: Secret<String>,
pub port: u16,
pub host: String,
pub database_name: String,
}
impl DatabaseSettings {
pub fn connection_string(&self) -> String {
format!(
pub fn connection_string(&self) -> Secret<String> {
Secret::new(format!(
"postgres://{}:{}@{}:{}/{}",
self.username, self.password, self.host, self.port, self.database_name
)
self.username, self.password.expose_secret(), self.host, self.port, self.database_name
))
}
pub fn connection_string_without_db(&self) -> String {
format!(
pub fn connection_string_without_db(&self) -> Secret<String> {
Secret::new(format!(
"postgres://{}:{}@{}:{}",
self.username, self.password, self.host, self.port
)
self.username, self.password.expose_secret(), self.host, self.port
))
}
}

View File

@ -1,3 +1,4 @@
pub mod configuration;
pub mod routes;
pub mod startup;
pub mod telemetry;

View File

@ -1,13 +1,18 @@
use std::net::TcpListener;
use secrecy::ExposeSecret;
use sqlx::postgres::PgPoolOptions;
use zero2prod::configuration::get_configuration;
use zero2prod::startup::run;
use zero2prod::telemetry::{get_subscriber, init_subscriber};
#[tokio::main]
async fn main() -> std::io::Result<()> {
let subscriber = get_subscriber("zero2prod".into(), "info".into(), std::io::stdout);
init_subscriber(subscriber);
let config = get_configuration().expect("Failed to read configuration");
let connection_pool = PgPoolOptions::new()
.max_connections(10).connect(&config.database.connection_string()).await.expect("Failed to connect to Postgres.");
.max_connections(10).connect(config.database.connection_string().expose_secret()).await.expect("Failed to connect to Postgres.");
let address = format!("127.0.0.1:{}", config.application_port);
let listener = TcpListener::bind(address).expect("Failed to bind random port");

View File

@ -10,8 +10,28 @@ pub struct FormData {
pub name: String,
}
#[tracing::instrument(
name = "Adding a new subscriber",
skip(form, connection_pool),
fields(
subscriber_email = %form.email,
subscriber_name = %form.name
)
)]
pub async fn subscribe(form: web::Form<FormData>, connection_pool: web::Data<Pool<Postgres>>) -> HttpResponse {
match query!(
match insert_subscriber(&form, &connection_pool).await
{
Ok(_) => HttpResponse::Ok().finish(),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}
#[tracing::instrument(
name = "Saving new subscriber details in the database",
skip(form, connection_pool)
)]
async fn insert_subscriber(form: &FormData, connection_pool: &Pool<Postgres>) -> Result<(), sqlx::Error> {
query!(
r#"
INSERT INTO subscriptions (id, email, name, subscribed_at)
VALUES ($1, $2, $3, $4)
@ -21,12 +41,11 @@ pub async fn subscribe(form: web::Form<FormData>, connection_pool: web::Data<Poo
form.name,
Utc::now()
)
.execute(connection_pool.get_ref())
.await {
Ok(_) => HttpResponse::Ok().finish(),
Err(e) => {
println!("Failed to execute query: {:?}", e);
HttpResponse::InternalServerError().finish()
}
}
.execute(connection_pool)
.await
.map_err(|e| {
tracing::error!("Failed to execute query: {:?}", e);
e
})?;
Ok(())
}

View File

@ -1,6 +1,7 @@
use actix_web::dev::Server;
use actix_web::{web, App, HttpServer};
use sqlx::{Pool, Postgres};
use tracing_actix_web::TracingLogger;
use std::net::TcpListener;
use crate::routes::{health_check, subscribe};
@ -9,6 +10,7 @@ pub fn run(listener: TcpListener, connection_pool: Pool<Postgres>) -> Result<Ser
let connection_pool = web::Data::new(connection_pool);
let server = HttpServer::new(move || {
App::new()
.wrap(TracingLogger::default())
.route("/health_check", web::get().to(health_check))
.route("/subscriptions", web::post().to(subscribe))
.app_data(connection_pool.clone())

20
src/telemetry.rs Normal file
View File

@ -0,0 +1,20 @@
// use std::io::Sink;
// use tokio::io::Sink;
use tracing::dispatcher::set_global_default;
use tracing::Subscriber;
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
use tracing_log::LogTracer;
use tracing_subscriber::{fmt::MakeWriter, prelude::*, registry::Registry, EnvFilter};
pub fn get_subscriber<Sink>(name: String, env_filter: String, sink: Sink) -> impl Subscriber + Send + Sync
where Sink: for <'a> MakeWriter<'a> + Send + Sync + 'static {
let env_filter = EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new(env_filter));
let formatting_layer = BunyanFormattingLayer::new(name, sink);
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.into()).expect("Failed to set subscriber.");
}