diff --git a/http-signature-normalization-actix/Cargo.toml b/http-signature-normalization-actix/Cargo.toml index c305d16..aa2acb4 100644 --- a/http-signature-normalization-actix/Cargo.toml +++ b/http-signature-normalization-actix/Cargo.toml @@ -41,4 +41,5 @@ tracing-futures = "0.2" [dev-dependencies] actix-rt = "2.1.0" -pretty_env_logger = "0.4" +tracing-actix-web = { version = "0.4.0-beta.12", git = "https://github.com/asonix/tracing-actix-web", branch = "asonix/root-span-expansion" } +tracing-subscriber = { version = "0.2", features = ["fmt"] } diff --git a/http-signature-normalization-actix/examples/client.rs b/http-signature-normalization-actix/examples/client.rs index ecff259..bb6d101 100644 --- a/http-signature-normalization-actix/examples/client.rs +++ b/http-signature-normalization-actix/examples/client.rs @@ -3,6 +3,9 @@ use awc::Client; use http_signature_normalization_actix::prelude::*; use sha2::{Digest, Sha256}; use std::time::SystemTime; +use tracing::{error, info}; +use tracing_error::ErrorLayer; +use tracing_subscriber::{layer::SubscriberExt, EnvFilter}; async fn request(config: Config) -> Result<(), Box> { let digest = Sha256::new(); @@ -13,30 +16,36 @@ async fn request(config: Config) -> Result<(), Box> { .append_header(("Accept", "text/plain")) .insert_header(actix_web::http::header::Date(SystemTime::now().into())) .signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| { - println!("Signing String\n{}", s); + info!("Signing String\n{}", s); Ok(base64::encode(s)) as Result<_, MyError> }) .await? .send() .await .map_err(|e| { - eprintln!("Error, {}", e); + error!("Error, {}", e); MyError::SendRequest })?; let body = response.body().await.map_err(|e| { - eprintln!("Error, {}", e); + error!("Error, {}", e); MyError::Body })?; - println!("{:?}", body); + info!("{:?}", body); Ok(()) } #[actix_rt::main] async fn main() -> Result<(), Box> { - std::env::set_var("RUST_LOG", "info"); - pretty_env_logger::init(); + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + + let subscriber = tracing_subscriber::Registry::default() + .with(env_filter) + .with(ErrorLayer::default()) + .with(tracing_subscriber::fmt::layer()); + + tracing::subscriber::set_global_default(subscriber)?; let config = Config::default().require_header("accept").require_digest(); diff --git a/http-signature-normalization-actix/examples/server.rs b/http-signature-normalization-actix/examples/server.rs index f216fd7..53e85de 100644 --- a/http-signature-normalization-actix/examples/server.rs +++ b/http-signature-normalization-actix/examples/server.rs @@ -1,11 +1,11 @@ -use actix_web::{ - http::StatusCode, middleware::Logger, web, App, HttpRequest, HttpResponse, HttpServer, - ResponseError, -}; -use futures::future::{err, ok, Ready}; +use actix_web::{http::StatusCode, web, App, HttpRequest, HttpResponse, HttpServer, ResponseError}; use http_signature_normalization_actix::prelude::*; -use log::info; use sha2::{Digest, Sha256}; +use std::future::{ready, Ready}; +use tracing::info; +use tracing_actix_web::TracingLogger; +use tracing_error::ErrorLayer; +use tracing_subscriber::{layer::SubscriberExt, EnvFilter}; #[derive(Clone, Debug)] struct MyVerify; @@ -23,21 +23,21 @@ impl SignatureVerify for MyVerify { ) -> Self::Future { match algorithm { Some(Algorithm::Hs2019) => (), - _ => return err(MyError::Algorithm), + _ => return ready(Err(MyError::Algorithm)), }; if key_id != "my-key-id" { - return err(MyError::Key); + return ready(Err(MyError::Key)); } let decoded = match base64::decode(&signature) { Ok(decoded) => decoded, - Err(_) => return err(MyError::Decode), + Err(_) => return ready(Err(MyError::Decode)), }; - println!("Signing String\n{}", signing_string); + info!("Signing String\n{}", signing_string); - ok(decoded == signing_string.as_bytes()) + ready(Ok(decoded == signing_string.as_bytes())) } } @@ -53,8 +53,14 @@ async fn index( #[actix_rt::main] async fn main() -> Result<(), Box> { - std::env::set_var("RUST_LOG", "info"); - pretty_env_logger::init(); + let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + + let subscriber = tracing_subscriber::Registry::default() + .with(env_filter) + .with(ErrorLayer::default()) + .with(tracing_subscriber::fmt::layer()); + + tracing::subscriber::set_global_default(subscriber)?; let config = Config::default().require_header("accept").require_digest(); @@ -62,7 +68,7 @@ async fn main() -> Result<(), Box> { App::new() .wrap(VerifyDigest::new(Sha256::new()).optional()) .wrap(VerifySignature::new(MyVerify, config.clone()).optional()) - .wrap(Logger::default()) + .wrap(TracingLogger::::new()) .route("/", web::post().to(index)) }) .bind("127.0.0.1:8010")? @@ -96,3 +102,52 @@ impl ResponseError for MyError { HttpResponse::BadRequest().finish() } } + +// tracing-actix-web + tracing-error WORKAROUND + +use actix_web::{ + dev::{ServiceRequest, ServiceResponse}, + Error, +}; +use tracing::Span; +use tracing_actix_web::root_span; + +pub struct RootSpanBuilder; + +impl tracing_actix_web::RootSpanBuilder for RootSpanBuilder { + fn on_request_start(request: &ServiceRequest) -> Span { + root_span!(request) + } + + fn on_request_end(span: Span, outcome: &Result, Error>) { + match &outcome { + Ok(response) => { + if let Some(error) = response.response().error() { + handle_error(span, error) + } else { + span.record("http.status_code", &response.response().status().as_u16()); + span.record("otel.status_code", &"OK"); + } + } + Err(error) => handle_error(span, error), + } + } +} + +fn handle_error(span: Span, error: &Error) { + let response_error = error.as_response_error(); + + let display = format!("{}", response_error); + let debug = format!("{:?}", response_error); + span.record("exception.message", &tracing::field::display(display)); + span.record("exception.details", &tracing::field::display(debug)); + + let status_code = response_error.status_code(); + span.record("http.status_code", &status_code.as_u16()); + + if status_code.is_client_error() { + span.record("otel.status_code", &"OK"); + } else { + span.record("otel.status_code", &"ERROR"); + } +}