1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
use crate::{config::AccessLogConfig, error::ServiceError, FilterRequest, State};
use futures::executor::block_on;
use log::error;
use std::{net::SocketAddr, ops::ControlFlow, time::SystemTime};
use tokio::{
fs::OpenOptions,
io::{AsyncWriteExt, BufWriter},
};
pub async fn access_log(
state: &State,
host: &str,
addr: SocketAddr,
config: &AccessLogConfig,
req: &FilterRequest,
) -> Result<ControlFlow<()>, ServiceError> {
let mut g = state.access_logs.write().await;
let log = g.entry(host.to_owned()).or_insert_with(|| {
BufWriter::new(
// TODO aaahh dont block the runtime and dont panic in any case....
block_on(
OpenOptions::new()
.append(true)
.create(true)
.open(&config.file),
)
.unwrap(),
)
});
let method = req.method().as_str();
let time = SystemTime::UNIX_EPOCH.elapsed().unwrap().as_micros();
let mut res = log
.write_all(format!("{time}\t{addr}\t{method}\t{:?}\n", req.uri()).as_bytes())
.await;
if config.flush && res.is_ok() {
res = log.flush().await;
}
if config.reject_on_fail {
res?
} else if let Err(e) = res {
error!("failed to write log: {e:?}")
}
Ok(ControlFlow::Continue(()))
}
|