You can use a tracing logger which logs twice for a request: upon arrival and when a response is sent out. Often requests are logged when sending the response, this way we can add context like the response's status code to the log event. However, if we receive a problematic incoming request our service might crash before logging occured.
In those cases 2 log events per requests are useful to identify harmful incoming workload:
use actix_service::Service;
use actix_web::{web, App, HttpServer};
use actix_web_opentelemetry::RequestTracing;
use log;
use tracing::subscriber::set_global_default;
use tracing_actix_web::TracingLogger;
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
use tracing_log::LogTracer;
use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
const PKG_NAME: &str = env!("CARGO_PKG_NAME");
async fn index() -> &'static str {
"Hello!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "info,actix_web=error");
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let formatting_layer = BunyanFormattingLayer::new(PKG_NAME.into(), std::io::stdout);
let subscriber = Registry::default()
.with(env_filter)
.with(JsonStorageLayer)
.with(formatting_layer);
LogTracer::init().expect("Failed to set logger");
set_global_default(subscriber).expect("Failed to set subscriber");
HttpServer::new(|| {
App::new()
.wrap_fn(|req, srv| {
log::info!("hello from middleware!");
srv.call(req)
})
.wrap(RequestTracing::new())
.wrap(TracingLogger)
.service(web::resource("/").to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
In the output we see the middleware is logging between REQUEST - START
and REQUEST - END
:
./target/debug/log-test | jq -cr '.msg'
Starting 4 workers
Starting "actix-web-service-127.0.0.1:8080" service on 127.0.0.1:8080
[REQUEST - START]
hello from middleware!
[REQUEST - END]