use super::base::{Middleware, Next};
use crate::{
errors::EventErrorKind,
event::{telegram::HandlerResponse, EventReturn},
Request,
};
use std::{
fmt::{self, Display, Formatter},
time::Instant,
};
use tracing::{event, instrument, Level};
#[derive(Debug, Default, Clone, Copy)]
pub struct Logging;
impl Logging {
#[inline]
#[must_use]
pub const fn new() -> Self {
Self {}
}
}
impl Display for Logging {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Logging")
}
}
impl<Client> Middleware<Client> for Logging
where
Client: Send + Sync + 'static,
{
#[instrument(skip(self, request, next))]
async fn call(
&mut self,
request: Request<Client>,
next: Next<Client>,
) -> Result<HandlerResponse<Client>, EventErrorKind> {
let now = Instant::now();
let result = next(request).await;
let elapsed = now.elapsed();
match result {
Ok(ref response) => match response.result.as_ref().unwrap() {
EventReturn::Finish => {
event!(
Level::DEBUG,
"Handler finished. Execution time: {elapsed:.2?}",
);
}
EventReturn::Skip => {
event!(
Level::DEBUG,
"Handler skipped. Execution time: {elapsed:.2?}",
);
}
EventReturn::Cancel => {
event!(
Level::DEBUG,
"Handler canceled. Execution time: {elapsed:.2?}",
);
}
},
Err(ref err_kind) => match err_kind {
EventErrorKind::Extraction(err) => {
event!(
Level::ERROR,
error = %err,
"Extraction returns error. Execution time: {elapsed:.2?}",
);
}
EventErrorKind::Handler(err) => {
event!(
Level::ERROR,
error = %err,
"Handler returns error. Execution time: {elapsed:.2?}",
);
}
EventErrorKind::Middleware(err) => {
event!(
Level::ERROR,
error = %err,
"Middleware returns error. Execution time: {elapsed:.2?}",
);
}
EventErrorKind::Filter(_) => unreachable!(
"Inner middleware processes after filters, so it can't return filter error"
),
},
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
client::Reqwest,
event::telegram::handler::boxed_handler_factory,
middlewares::inner::wrap_to_next,
types::{ChatPrivate, MessageText, Update, UpdateMessage},
Bot, Extensions,
};
use std::{convert::Infallible, sync::Arc};
#[tokio::test]
async fn test_logging() {
let handler_service =
boxed_handler_factory(|| async { Ok::<_, Infallible>(EventReturn::Finish) });
let request = Request::<Reqwest> {
update: Arc::new(Update::Message(UpdateMessage::new(
0,
MessageText::new(0, 0, ChatPrivate::new(0), ""),
))),
bot: Bot::default(),
context: crate::Context::default(),
extensions: Extensions::default(),
};
let response = Logging
.call(request, wrap_to_next(handler_service, [].into()))
.await;
assert!(response.is_ok());
}
}