Add configurable debug logging for all events and/or requests

This commit is contained in:
Peter Cai 2025-03-09 13:32:26 -04:00
parent 8ea8261f38
commit 86bb5b6a52
4 changed files with 57 additions and 19 deletions

View file

@ -30,6 +30,17 @@ ask_cmd = "contrib/ask-bemenu.sh"
# will not be filtered whatever this command does.
notify_cmd = "contrib/notify-libnotify.sh"
[logging]
# If true, log all known requests (client -> server) at the DEBUG level
# log_all_requests = false
# If true, log all known events (server -> client) at the DEBUG level
# log_all_events = false
# Set the maximum log level output to stdout
# Overrides the RUST_LOG environmet variable if set
# log_level = "info"
[filter]
# A list of Wayland global singleton objects that's allowed
# Each of them generally correspond to an implemented protocol

View file

@ -9,7 +9,10 @@ use serde_derive::Deserialize;
#[derive(Deserialize)]
pub struct Config {
pub socket: WlSockets,
#[serde(default)]
pub exec: WlExec,
#[serde(default)]
pub logging: WlLogging,
pub filter: WlFilter,
}
@ -52,7 +55,16 @@ impl WlSockets {
}
}
#[derive(Deserialize)]
#[derive(Default, Deserialize)]
pub struct WlLogging {
#[serde(default)]
pub log_all_requests: bool,
#[serde(default)]
pub log_all_events: bool,
pub log_level: Option<String>,
}
#[derive(Default, Deserialize)]
pub struct WlExec {
pub ask_cmd: Option<String>,
pub notify_cmd: Option<String>,

View file

@ -6,7 +6,7 @@ mod proto;
mod config;
mod state;
use std::{io, ops::ControlFlow, path::Path, sync::Arc};
use std::{io, ops::ControlFlow, path::Path, str::FromStr, sync::Arc};
use codec::DecoderOutcome;
use config::Config;
@ -14,12 +14,10 @@ use io_util::{WlMsgReader, WlMsgWriter};
use proto::{WL_DISPLAY_OBJECT_ID, WlConstructableMessage, WlDisplayErrorEvent};
use state::{WlMitmOutcome, WlMitmState, WlMitmVerdict};
use tokio::net::{UnixListener, UnixStream};
use tracing::{Instrument, Level, debug, error, info, span, warn};
use tracing::{Instrument, Level, error, info, level_filters::LevelFilter, span, warn};
#[tokio::main]
async fn main() {
tracing_subscriber::fmt::init();
let mut conf_file = "config.toml";
let args: Vec<_> = std::env::args().collect();
@ -33,6 +31,15 @@ async fn main() {
let config: Arc<Config> =
Arc::new(toml::from_str(&conf_str).expect("Can't decode config file"));
let mut tracing_builder = tracing_subscriber::fmt();
if let Some(ref level) = config.logging.log_level {
tracing_builder = tracing_builder
.with_max_level(LevelFilter::from_str(level).expect("Invalid log level"));
}
tracing_builder.init();
let src = config.socket.upstream_socket_path();
let proxied = config.socket.listen_socket_path();
@ -119,13 +126,6 @@ impl<'a> ConnDuplex<'a> {
) -> io::Result<ControlFlow<()>> {
match decoded_raw {
codec::DecoderOutcome::Decoded(mut wl_raw_msg) => {
debug!(
obj_id = wl_raw_msg.obj_id,
opcode = wl_raw_msg.opcode,
num_fds = wl_raw_msg.fds.len(),
"s2c event"
);
let WlMitmOutcome(num_consumed_fds, mut verdict) =
self.state.on_s2c_event(&wl_raw_msg).await;
self.upstream_read
@ -165,13 +165,6 @@ impl<'a> ConnDuplex<'a> {
) -> io::Result<ControlFlow<()>> {
match decoded_raw {
codec::DecoderOutcome::Decoded(mut wl_raw_msg) => {
debug!(
obj_id = wl_raw_msg.obj_id,
opcode = wl_raw_msg.opcode,
num_fds = wl_raw_msg.fds.len(),
"c2s request"
);
let WlMitmOutcome(num_consumed_fds, mut verdict) =
self.state.on_c2s_request(&wl_raw_msg).await;
self.downstream_read

View file

@ -243,6 +243,17 @@ impl WlMitmState {
outcome.set_consumed_fds(msg.num_consumed_fds());
if self.config.logging.log_all_requests {
debug!(
raw_payload_bytes = ?raw_msg.payload(),
num_fds = raw_msg.fds.len(),
num_consumed_fds = msg.num_consumed_fds(),
"{}::{}",
msg.self_object_type().interface(),
msg.self_msg_name(),
)
}
// To get here, the object referred to in raw_msg must exist, but it might already be destroyed by the client
// In that case, the client is broken!
if self.objects.is_half_destroyed(msg.obj_id()) {
@ -439,6 +450,17 @@ impl WlMitmState {
outcome.set_consumed_fds(msg.num_consumed_fds());
if self.config.logging.log_all_events {
debug!(
raw_payload_bytes = ?raw_msg.payload(),
num_fds = raw_msg.fds.len(),
num_consumed_fds = msg.num_consumed_fds(),
"{}::{}",
msg.self_object_type().interface(),
msg.self_msg_name(),
)
}
if !self.handle_created_or_destroyed_objects(&*msg, false) {
return outcome.terminate();
}