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,6 +136,7 @@ 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; let debug_logging = &mut *ctx.debug_logging.write().await;
match debug_logging { match debug_logging {
// Switch logging xdc // Switch logging xdc
@@ -121,9 +146,9 @@ pub(crate) async fn set_debug_logging_xdc(ctx: &Context, id: Option<MsgId>) -> a
let (sender, debug_logging_recv) = channel::bounded(1000); let (sender, debug_logging_recv) = channel::bounded(1000);
let loop_handle = { let loop_handle = {
let ctx = ctx.clone(); let ctx = ctx.clone();
task::spawn( task::spawn(async move {
async move { debug_logging_loop(&ctx, debug_logging_recv).await }, debug_logging_loop(&ctx, debug_logging_recv).await
) })
}; };
*debug_logging = Some(DebugLogging { *debug_logging = Some(DebugLogging {
msg_id, msg_id,
@@ -132,6 +157,7 @@ pub(crate) async fn set_debug_logging_xdc(ctx: &Context, id: Option<MsgId>) -> a
}); });
} }
} }
}
info!(ctx, "replacing logging webxdc"); info!(ctx, "replacing logging webxdc");
} }
// Delete current debug logging // Delete current debug logging