| | |
| | use crate::chat::ChatId; |
| | use crate::config::Config; |
| | use crate::context::Context; |
| | use crate::events::EventType; |
| | use crate::message::{Message, MsgId, Viewtype}; |
| | use crate::param::Param; |
| | use crate::tools::time; |
| | use crate::webxdc::StatusUpdateItem; |
| | use async_channel::{self as channel, Receiver, Sender}; |
| | use serde_json::json; |
| | use tokio::task; |
| |
|
| | #[derive(Debug)] |
| | pub(crate) struct DebugLogging { |
| | |
| | pub(crate) msg_id: MsgId, |
| | |
| | pub(crate) loop_handle: task::JoinHandle<()>, |
| | |
| | |
| | pub(crate) sender: Sender<DebugEventLogData>, |
| | } |
| |
|
| | impl DebugLogging { |
| | pub(crate) fn log_event(&self, event: EventType) { |
| | let event_data = DebugEventLogData { |
| | time: time(), |
| | msg_id: self.msg_id, |
| | event, |
| | }; |
| |
|
| | self.sender.try_send(event_data).ok(); |
| | } |
| | } |
| |
|
| | |
| | pub struct DebugEventLogData { |
| | pub time: i64, |
| | pub msg_id: MsgId, |
| | pub event: EventType, |
| | } |
| |
|
| | |
| | |
| | pub async fn debug_logging_loop(context: &Context, events: Receiver<DebugEventLogData>) { |
| | while let Ok(DebugEventLogData { |
| | time, |
| | msg_id, |
| | event, |
| | }) = events.recv().await |
| | { |
| | match context |
| | .write_status_update_inner( |
| | &msg_id, |
| | &StatusUpdateItem { |
| | payload: json!({ |
| | "event": event, |
| | "time": time, |
| | }), |
| | info: None, |
| | href: None, |
| | summary: None, |
| | document: None, |
| | uid: None, |
| | notify: None, |
| | }, |
| | time, |
| | ) |
| | .await |
| | { |
| | Err(err) => { |
| | eprintln!("Can't log event to webxdc status update: {err:#}"); |
| | } |
| | Ok(serial) => { |
| | if let Some(serial) = serial { |
| | if !matches!(event, EventType::WebxdcStatusUpdate { .. }) { |
| | context.emit_event(EventType::WebxdcStatusUpdate { |
| | msg_id, |
| | status_update_serial: serial, |
| | }); |
| | } |
| | } else { |
| | |
| | error!(context, "Debug logging update is not created."); |
| | }; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | |
| | pub async fn maybe_set_logging_xdc( |
| | context: &Context, |
| | msg: &Message, |
| | chat_id: ChatId, |
| | ) -> anyhow::Result<()> { |
| | maybe_set_logging_xdc_inner( |
| | context, |
| | msg.get_viewtype(), |
| | chat_id, |
| | msg.param.get(Param::Filename), |
| | msg.get_id(), |
| | ) |
| | .await?; |
| |
|
| | Ok(()) |
| | } |
| |
|
| | |
| | pub async fn maybe_set_logging_xdc_inner( |
| | context: &Context, |
| | viewtype: Viewtype, |
| | chat_id: ChatId, |
| | filename: Option<&str>, |
| | msg_id: MsgId, |
| | ) -> anyhow::Result<()> { |
| | if viewtype == Viewtype::Webxdc |
| | && let Some(filename) = filename |
| | && filename.starts_with("debug_logging") |
| | && filename.ends_with(".xdc") |
| | && chat_id.is_self_talk(context).await? |
| | { |
| | set_debug_logging_xdc(context, Some(msg_id)).await?; |
| | } |
| | Ok(()) |
| | } |
| |
|
| | |
| | |
| | pub(crate) async fn set_debug_logging_xdc(ctx: &Context, id: Option<MsgId>) -> anyhow::Result<()> { |
| | match id { |
| | Some(msg_id) => { |
| | ctx.sql |
| | .set_raw_config( |
| | Config::DebugLogging.as_ref(), |
| | Some(msg_id.to_string().as_ref()), |
| | ) |
| | .await?; |
| | { |
| | let debug_logging = &mut *ctx.debug_logging.write().expect("RwLock is poisoned"); |
| | match debug_logging { |
| | |
| | Some(debug_logging) => debug_logging.msg_id = msg_id, |
| | |
| | None => { |
| | let (sender, debug_logging_recv) = channel::bounded(1000); |
| | let loop_handle = { |
| | let ctx = ctx.clone(); |
| | task::spawn(async move { |
| | debug_logging_loop(&ctx, debug_logging_recv).await |
| | }) |
| | }; |
| | *debug_logging = Some(DebugLogging { |
| | msg_id, |
| | loop_handle, |
| | sender, |
| | }); |
| | } |
| | } |
| | } |
| | info!(ctx, "replacing logging webxdc"); |
| | } |
| | |
| | None => { |
| | ctx.sql |
| | .set_raw_config(Config::DebugLogging.as_ref(), None) |
| | .await?; |
| | *ctx.debug_logging.write().expect("RwLock is poisoned") = None; |
| | info!(ctx, "removing logging webxdc"); |
| | } |
| | } |
| | Ok(()) |
| | } |
| |
|