为什么自定义过滤器在 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
。
我正在尝试使用 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
。