Update actix examples with tracing

This commit is contained in:
Aode (lion) 2021-09-17 20:04:04 -05:00
parent 7b9aff925a
commit 11be605f5b
3 changed files with 86 additions and 21 deletions

View file

@ -41,4 +41,5 @@ tracing-futures = "0.2"
[dev-dependencies] [dev-dependencies]
actix-rt = "2.1.0" 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"] }

View file

@ -3,6 +3,9 @@ use awc::Client;
use http_signature_normalization_actix::prelude::*; use http_signature_normalization_actix::prelude::*;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::time::SystemTime; 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<dyn std::error::Error>> { async fn request(config: Config) -> Result<(), Box<dyn std::error::Error>> {
let digest = Sha256::new(); let digest = Sha256::new();
@ -13,30 +16,36 @@ async fn request(config: Config) -> Result<(), Box<dyn std::error::Error>> {
.append_header(("Accept", "text/plain")) .append_header(("Accept", "text/plain"))
.insert_header(actix_web::http::header::Date(SystemTime::now().into())) .insert_header(actix_web::http::header::Date(SystemTime::now().into()))
.signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| { .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> Ok(base64::encode(s)) as Result<_, MyError>
}) })
.await? .await?
.send() .send()
.await .await
.map_err(|e| { .map_err(|e| {
eprintln!("Error, {}", e); error!("Error, {}", e);
MyError::SendRequest MyError::SendRequest
})?; })?;
let body = response.body().await.map_err(|e| { let body = response.body().await.map_err(|e| {
eprintln!("Error, {}", e); error!("Error, {}", e);
MyError::Body MyError::Body
})?; })?;
println!("{:?}", body); info!("{:?}", body);
Ok(()) Ok(())
} }
#[actix_rt::main] #[actix_rt::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::set_var("RUST_LOG", "info"); let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
pretty_env_logger::init();
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(); let config = Config::default().require_header("accept").require_digest();

View file

@ -1,11 +1,11 @@
use actix_web::{ use actix_web::{http::StatusCode, web, App, HttpRequest, HttpResponse, HttpServer, ResponseError};
http::StatusCode, middleware::Logger, web, App, HttpRequest, HttpResponse, HttpServer,
ResponseError,
};
use futures::future::{err, ok, Ready};
use http_signature_normalization_actix::prelude::*; use http_signature_normalization_actix::prelude::*;
use log::info;
use sha2::{Digest, Sha256}; 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)] #[derive(Clone, Debug)]
struct MyVerify; struct MyVerify;
@ -23,21 +23,21 @@ impl SignatureVerify for MyVerify {
) -> Self::Future { ) -> Self::Future {
match algorithm { match algorithm {
Some(Algorithm::Hs2019) => (), Some(Algorithm::Hs2019) => (),
_ => return err(MyError::Algorithm), _ => return ready(Err(MyError::Algorithm)),
}; };
if key_id != "my-key-id" { if key_id != "my-key-id" {
return err(MyError::Key); return ready(Err(MyError::Key));
} }
let decoded = match base64::decode(&signature) { let decoded = match base64::decode(&signature) {
Ok(decoded) => decoded, 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] #[actix_rt::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
std::env::set_var("RUST_LOG", "info"); let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
pretty_env_logger::init();
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(); let config = Config::default().require_header("accept").require_digest();
@ -62,7 +68,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
App::new() App::new()
.wrap(VerifyDigest::new(Sha256::new()).optional()) .wrap(VerifyDigest::new(Sha256::new()).optional())
.wrap(VerifySignature::new(MyVerify, config.clone()).optional()) .wrap(VerifySignature::new(MyVerify, config.clone()).optional())
.wrap(Logger::default()) .wrap(TracingLogger::<RootSpanBuilder>::new())
.route("/", web::post().to(index)) .route("/", web::post().to(index))
}) })
.bind("127.0.0.1:8010")? .bind("127.0.0.1:8010")?
@ -96,3 +102,52 @@ impl ResponseError for MyError {
HttpResponse::BadRequest().finish() 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<B>(span: Span, outcome: &Result<ServiceResponse<B>, 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");
}
}