为什么自定义过滤器在 log4rs(1.0) 中不起作用?

Why custom filter not working in log4rs(1.0)?

我正在尝试使用 Log4rs 基于 actix-web 而不是 working.The 代码创建自定义过滤器,主要来自这个类似问题的 answer

初始化记录器配置:

    pub fn init_config() {
        let mut custom_filter_deserializer = log4rs::config::Deserializers::new();
        custom_filter_deserializer.insert(
            "request_filter",
            CustomFilterDeserializer
        );
        log4rs::init_file("config/log4rs.yaml", custom_filter_deserializer).unwrap_or_else(|e| {
            panic!("init logger file failed: {:?}", e);
        });
    }

自定义过滤器:

#[derive(Deserialize)]
pub struct RequestFilterConfig {
    request_field: String
}

#[derive(Debug)]
pub struct RequestFilter {
    request_field: String
}

impl  RequestFilter {
    /// Creates a new `CustomFilter` with the specified interesting field.
    pub fn new(request_field: String) -> Self {
        Self { request_field }
    }
}


impl Filter for RequestFilter {
    fn filter(&self, record: &Record) -> Response {
        println!("RequestFilter {:?}", record);
        let path = record.module_path().unwrap();
        println!("RequestFilter {} - {}", path, &self.request_field);
        if path.contains(&self.request_field)  {
            Response::Accept
        } else {
            Response::Reject
        }
    }
}

pub struct CustomFilterDeserializer;

impl config::Deserialize for CustomFilterDeserializer {
    type Trait = dyn Filter;
    type Config = RequestFilterConfig;

    fn deserialize(&self, config: RequestFilterConfig, _: &config::Deserializers) ->  anyhow::Result<Box<dyn Filter>> {
        let filter = RequestFilter::new(config.request_field);
        println!("CustomFilterDeserializer {:?}", &filter);
        Ok(Box::new(filter))
    }
}

我使用的地方:

#[get("/posts")]
async fn posts(pool: web::Data<DbPool>) -> Result<HttpResponse, ApiError> {
    info!("get posts");
    let conn = pool.get().expect("couldn't get db connection from pool");
    let posts_result = web::block(move || db::get_posts(&conn)).await.map_err(|e| {
        eprintln!("{:?}", e);
        HttpResponse::InternalServerError().finish()
    });
    match posts_result {
        Ok(posts) => Ok(HttpResponse::Ok().json(posts)),
        Err(error) => Ok(error),
    }
}

配置yaml文件:

refresh_rate: 30 seconds
appenders:
  stdout:
    kind: console
  requests:
    kind: file
    path: "log/requests.log"
    filters:
      - kind: request_filter
        request_field: api
    encoder:
      pattern: "{d} {l} {t} - {m}{n}"
root:
  level: info
  appenders:
    - stdout
loggers:
  requests_logger:
    level: info
    appenders:
      - requests
    additive: false

从控制台输出来看,似乎程序甚至没有运行进入RequestFilter::filter方法:

CustomFilterDeserializer RequestFilter { request_field: "api" }
logger init success!
env init success!
db pool init success!
ssl pool init success!
2021-04-18T19:41:51.590650400+08:00 INFO actix_server::builder - Starting 12 workers
2021-04-18T19:41:51.592819400+08:00 INFO actix_server::builder - Starting "actix-web-service-0.0.0.0:8080" service on 0.0.0.0:8080
2021-04-18T19:41:51.592876400+08:00 INFO actix_server::builder - Starting "actix-web-service-0.0.0.0:8083" service on 0.0.0.0:8083
2021-04-18T19:42:02.698122400+08:00 INFO actix_angular_web::api - get posts
2021-04-18T19:42:02.705875900+08:00 INFO actix_web::middleware::logger - 127.0.0.1:33200 Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0

哪里错了?

完整代码可以在这里找到:https://github.com/lazystitan/actix-angular-web

是时候自己回答这个问题了。

目标是让发出的记录写入不同的文件,因为它们是在程序的不同功能部分发出的。

不需要使用自定义过滤器,我们可以很容易地通过记录者的名字来过滤记录:

crate_name::module_name(::module_name...)::function_name 中发出的记录被发送到具有相应名称 crate_name::module_name(::module_name...)::function_name 或其祖先 crate_name::module_name(::module_name...).

的记录器

但要注意包含-的crate在程序运行时会自动转换为只有_的名称。

例如。在我的例子中 actix-angular-web => actix_angular_web.

所以,我应该使用 actix_angular_web::apis::get_posts,而不是 actix-angular-web::apis::get_posts