From 00ab3e9252b98319f31c51b1ddf4b2018acaf1a4 Mon Sep 17 00:00:00 2001 From: Luca Palmieri Date: Mon, 30 Aug 2021 16:28:01 +0200 Subject: [PATCH] Do not lose context when using spawn blocking. --- src/routes/newsletters.rs | 38 ++++++++++++++++++++++++++------------ src/telemetry.rs | 10 ++++++++++ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/routes/newsletters.rs b/src/routes/newsletters.rs index 242f35c..a21d3ca 100644 --- a/src/routes/newsletters.rs +++ b/src/routes/newsletters.rs @@ -1,6 +1,7 @@ use crate::domain::SubscriberEmail; use crate::email_client::EmailClient; use crate::routes::error_chain_fmt; +use crate::telemetry::spawn_blocking_with_tracing; use actix_web::http::{HeaderMap, HeaderValue, StatusCode}; use actix_web::{web, HttpResponse, ResponseError}; use anyhow::Context; @@ -114,23 +115,36 @@ async fn validate_credentials( .map_err(PublishError::UnexpectedError)? .ok_or_else(|| PublishError::AuthError(anyhow::anyhow!("Unknown username.")))?; - let expected_password_hash = PasswordHash::new(&expected_password_hash) - .context("Failed to parse hash in PHC string format.") - .map_err(PublishError::UnexpectedError)?; - - tracing::info_span!("Verify password hash") - .in_scope(|| { - Argon2::default() - .verify_password(credentials.password.as_bytes(), &expected_password_hash) - }) - .context("Invalid password.") - .map_err(PublishError::AuthError)?; + spawn_blocking_with_tracing(move || { + verify_password_hash(expected_password_hash, credentials.password) + }) + .await + .context("Failed to spawn blocking task.") + .map_err(PublishError::UnexpectedError)??; Ok(user_id) } #[tracing::instrument( - name = "Publish a newsletter issue", + name = "Validate credentials", + skip(expected_password_hash, password_candidate) +)] +fn verify_password_hash( + expected_password_hash: String, + password_candidate: String, +) -> Result<(), PublishError> { + let expected_password_hash = PasswordHash::new(&expected_password_hash) + .context("Failed to parse hash in PHC string format.") + .map_err(PublishError::UnexpectedError)?; + + Argon2::default() + .verify_password(password_candidate.as_bytes(), &expected_password_hash) + .context("Invalid password.") + .map_err(PublishError::AuthError) +} + +#[tracing::instrument( +name = "Publish a newsletter issue", skip(body, pool, email_client, request), fields(username=tracing::field::Empty, user_id=tracing::field::Empty) )] diff --git a/src/telemetry.rs b/src/telemetry.rs index f8646a4..2a8cb18 100644 --- a/src/telemetry.rs +++ b/src/telemetry.rs @@ -1,3 +1,4 @@ +use actix_web::rt::task::JoinHandle; use tracing::subscriber::set_global_default; use tracing::Subscriber; use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer}; @@ -32,3 +33,12 @@ 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"); } + +pub fn spawn_blocking_with_tracing(f: F) -> JoinHandle +where + F: FnOnce() -> R + Send + 'static, + R: Send + 'static, +{ + let current_span = tracing::Span::current(); + actix_web::rt::task::spawn_blocking(move || current_span.in_scope(f)) +}