mirror of
https://github.com/chatmail/core.git
synced 2026-04-06 15:42:10 +03:00
It is required by rPGP 0.18.0. All the changes in `.rs` files are made automatically with `clippy --fix`.
175 lines
5.5 KiB
Rust
175 lines
5.5 KiB
Rust
//! Forward log messages to logging webxdc
|
|
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 {
|
|
/// The message containing the logging xdc
|
|
pub(crate) msg_id: MsgId,
|
|
/// Handle to the background task responsible for sending
|
|
pub(crate) loop_handle: task::JoinHandle<()>,
|
|
/// Channel that log events should be sent to.
|
|
/// A background loop will receive and handle them.
|
|
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();
|
|
}
|
|
}
|
|
|
|
/// Store all information needed to log an event to a webxdc.
|
|
pub struct DebugEventLogData {
|
|
pub time: i64,
|
|
pub msg_id: MsgId,
|
|
pub event: EventType,
|
|
}
|
|
|
|
/// Creates a loop which forwards all log messages send into the channel to the associated
|
|
/// logging xdc.
|
|
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 {
|
|
// This should not happen as the update has no `uid`.
|
|
error!(context, "Debug logging update is not created.");
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Set message as new logging webxdc if filename and chat_id fit
|
|
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(())
|
|
}
|
|
|
|
/// Set message as new logging webxdc if filename and chat_id fit
|
|
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(())
|
|
}
|
|
|
|
/// Set the webxdc contained in the msg as the current logging xdc on the context and save it to db
|
|
/// If id is a `None` value, disable debug logging
|
|
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 {
|
|
// Switch logging xdc
|
|
Some(debug_logging) => debug_logging.msg_id = msg_id,
|
|
// Bootstrap background loop for message forwarding
|
|
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");
|
|
}
|
|
// Delete current debug logging
|
|
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(())
|
|
}
|