Debug logging refactoring

Move DebugLogging into debug logging module.
Remove Context.send_log_event().
Use blocking_read() instead of try_read() to
get read lock on debug_logging() in synchronous code.
Do not try to log events while holding a lock
on DebugLogging.
This commit is contained in:
link2xt
2023-04-16 00:37:39 +00:00
parent 4dfe34eedc
commit 2b8888350b
2 changed files with 52 additions and 61 deletions

View File

@@ -12,13 +12,12 @@ use anyhow::{bail, ensure, Context as _, Result};
use async_channel::{self as channel, Receiver, Sender}; use async_channel::{self as channel, Receiver, Sender};
use ratelimit::Ratelimit; use ratelimit::Ratelimit;
use tokio::sync::{Mutex, Notify, RwLock}; use tokio::sync::{Mutex, Notify, RwLock};
use tokio::task;
use crate::chat::{get_chat_cnt, ChatId}; use crate::chat::{get_chat_cnt, ChatId};
use crate::config::Config; use crate::config::Config;
use crate::constants::DC_VERSION_STR; use crate::constants::DC_VERSION_STR;
use crate::contact::Contact; use crate::contact::Contact;
use crate::debug_logging::DebugEventLogData; use crate::debug_logging::DebugLogging;
use crate::events::{Event, EventEmitter, EventType, Events}; use crate::events::{Event, EventEmitter, EventType, Events};
use crate::key::{DcKey, SignedPublicKey}; use crate::key::{DcKey, SignedPublicKey};
use crate::login_param::LoginParam; use crate::login_param::LoginParam;
@@ -247,17 +246,6 @@ pub struct InnerContext {
pub(crate) debug_logging: RwLock<Option<DebugLogging>>, pub(crate) debug_logging: RwLock<Option<DebugLogging>>,
} }
#[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>,
}
/// The state of ongoing process. /// The state of ongoing process.
#[derive(Debug)] #[derive(Debug)]
enum RunningState { enum RunningState {
@@ -449,41 +437,18 @@ impl Context {
/// Emits a single event. /// Emits a single event.
pub fn emit_event(&self, event: EventType) { pub fn emit_event(&self, event: EventType) {
if self
.debug_logging
.try_read()
.ok()
.map(|inner| inner.is_some())
== Some(true)
{ {
self.send_log_event(event.clone()).ok(); let lock = tokio::task::block_in_place(|| self.debug_logging.blocking_read());
}; if let Some(debug_logging) = &*lock {
debug_logging.log_event(event.clone());
}
}
self.events.emit(Event { self.events.emit(Event {
id: self.id, id: self.id,
typ: event, typ: event,
}); });
} }
pub(crate) fn send_log_event(&self, event: EventType) -> anyhow::Result<()> {
if let Ok(lock) = self.debug_logging.try_read() {
if let Some(DebugLogging {
msg_id: xdc_id,
sender,
..
}) = &*lock
{
let event_data = DebugEventLogData {
time: time(),
msg_id: *xdc_id,
event,
};
sender.try_send(event_data).ok();
}
}
Ok(())
}
/// Emits a generic MsgsChanged event (without chat or message id) /// Emits a generic MsgsChanged event (without chat or message id)
pub fn emit_msgs_changed_without_ids(&self) { pub fn emit_msgs_changed_without_ids(&self) {
self.emit_event(EventType::MsgsChanged { self.emit_event(EventType::MsgsChanged {

View File

@@ -2,17 +2,41 @@
use crate::{ use crate::{
chat::ChatId, chat::ChatId,
config::Config, config::Config,
context::{Context, DebugLogging}, context::Context,
message::{Message, MsgId, Viewtype}, message::{Message, MsgId, Viewtype},
param::Param, param::Param,
tools::time,
webxdc::StatusUpdateItem, webxdc::StatusUpdateItem,
Event, EventType, Event, EventType,
}; };
use async_channel::{self as channel, Receiver}; use async_channel::{self as channel, Receiver, Sender};
use serde_json::json; use serde_json::json;
use std::path::PathBuf; use std::path::PathBuf;
use tokio::task; 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. /// Store all information needed to log an event to a webxdc.
pub struct DebugEventLogData { pub struct DebugEventLogData {
pub time: i64, pub time: i64,
@@ -112,24 +136,26 @@ pub(crate) async fn set_debug_logging_xdc(ctx: &Context, id: Option<MsgId>) -> a
Some(msg_id.to_string().as_ref()), Some(msg_id.to_string().as_ref()),
) )
.await?; .await?;
let debug_logging = &mut *ctx.debug_logging.write().await; {
match debug_logging { let debug_logging = &mut *ctx.debug_logging.write().await;
// Switch logging xdc match debug_logging {
Some(debug_logging) => debug_logging.msg_id = msg_id, // Switch logging xdc
// Bootstrap background loop for message forwarding Some(debug_logging) => debug_logging.msg_id = msg_id,
None => { // Bootstrap background loop for message forwarding
let (sender, debug_logging_recv) = channel::bounded(1000); None => {
let loop_handle = { let (sender, debug_logging_recv) = channel::bounded(1000);
let ctx = ctx.clone(); let loop_handle = {
task::spawn( let ctx = ctx.clone();
async move { debug_logging_loop(&ctx, debug_logging_recv).await }, task::spawn(async move {
) debug_logging_loop(&ctx, debug_logging_recv).await
}; })
*debug_logging = Some(DebugLogging { };
msg_id, *debug_logging = Some(DebugLogging {
loop_handle, msg_id,
sender, loop_handle,
}); sender,
});
}
} }
} }
info!(ctx, "replacing logging webxdc"); info!(ctx, "replacing logging webxdc");