确保 actix 按时间顺序记录 // 预处理

ensure actix logging in chronological order // pre-process

我有 actix-web 并且很难调试,因为记录器只在最后写入,如果出现故障,它根本不会写入。

RUST_LOG=actix_web=debug,actix_server=debug

let server = HttpServer::new(move || {
        App::new()
            .wrap(Logger::default())
            .wrap(Logger::new(
                "Request Pre",
                )
            )
            .wrap(add_service())
            .configure(add_routes)        
[2021-02-05T14:29:02Z INFO  my_lib::middleware::foo] Foo Middleware Finished
[2021-02-05T14:29:02Z INFO  my_lib::middleware::bar] Bar Middleware Finished
[2021-02-05T14:29:01Z INFO  actix_web::middleware::logger] Request Pre
[2021-02-05T14:29:01Z INFO  actix_web::middleware::logger] 127.0.0.1:54321 "POST /call/me HTTP/1.1"

我如何控制预处理(并在其中添加日志),以确保在请求到达时首先写入日志?

您可以使用跟踪记录器,它会为请求记录两次:到达时和发出响应时。通常在发送响应时记录请求,这样我们就可以将响应的状态代码等上下文添加到日志事件中。但是,如果我们收到有问题的传入请求,我们的服务可能会在记录发生之前崩溃。

在这些情况下,每个请求的 2 个日志事件可用于识别有害的传入工作负载:

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
}

在输出中我们看到中间件在 REQUEST - STARTREQUEST - 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]