mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-22 03:21:00 +00:00
tracers: queue-levels: Add a signal to force writing log file
This way applications can write the queue levels info whenever it wants and does not need to wait for the application to quite. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1912>
This commit is contained in:
parent
def8a29cc6
commit
153d4c7ac5
1 changed files with 71 additions and 43 deletions
|
@ -44,7 +44,7 @@
|
||||||
*
|
*
|
||||||
* By default this is not set.
|
* By default this is not set.
|
||||||
*/
|
*/
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -179,6 +179,7 @@ struct State {
|
||||||
queues: HashMap<usize, Arc<glib::GString>>,
|
queues: HashMap<usize, Arc<glib::GString>>,
|
||||||
log: Vec<LogLine>,
|
log: Vec<LogLine>,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
|
logs_written: HashSet<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LogLine {
|
struct LogLine {
|
||||||
|
@ -239,49 +240,26 @@ impl ObjectImpl for QueueLevels {
|
||||||
self.register_hook(TracerHook::PadPushEventPre);
|
self.register_hook(TracerHook::PadPushEventPre);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn signals() -> &'static [glib::subclass::Signal] {
|
||||||
|
static SIGNALS: LazyLock<Vec<glib::subclass::Signal>> = LazyLock::new(|| {
|
||||||
|
vec![glib::subclass::Signal::builder("write-log")
|
||||||
|
.action()
|
||||||
|
.param_types([Option::<String>::static_type()])
|
||||||
|
.class_handler(|_, args| {
|
||||||
|
let obj = args[0].get::<super::QueueLevels>().unwrap();
|
||||||
|
|
||||||
|
obj.imp().write_log(args[1].get::<Option<&str>>().unwrap());
|
||||||
|
|
||||||
|
None
|
||||||
|
})
|
||||||
|
.build()]
|
||||||
|
});
|
||||||
|
|
||||||
|
SIGNALS.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
fn dispose(&self) {
|
fn dispose(&self) {
|
||||||
use std::io::prelude::*;
|
self.write_log(None);
|
||||||
|
|
||||||
let state = self.state.lock().unwrap();
|
|
||||||
|
|
||||||
let mut file = match std::fs::File::create(&state.settings.file) {
|
|
||||||
Ok(file) => file,
|
|
||||||
Err(err) => {
|
|
||||||
gst::error!(CAT, imp = self, "Failed to create file: {err}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
gst::debug!(
|
|
||||||
CAT,
|
|
||||||
imp = self,
|
|
||||||
"Writing file {}",
|
|
||||||
state.settings.file.display()
|
|
||||||
);
|
|
||||||
|
|
||||||
for LogLine {
|
|
||||||
timestamp,
|
|
||||||
name,
|
|
||||||
idx,
|
|
||||||
ptr,
|
|
||||||
cur_level_bytes,
|
|
||||||
cur_level_time,
|
|
||||||
cur_level_buffers,
|
|
||||||
max_size_bytes,
|
|
||||||
max_size_time,
|
|
||||||
max_size_buffers,
|
|
||||||
} in &state.log
|
|
||||||
{
|
|
||||||
let res = if let Some(idx) = idx {
|
|
||||||
writeln!(&mut file, "{timestamp},{name}:{idx},0x{ptr:08x},{cur_level_bytes},{cur_level_time},{cur_level_buffers},{max_size_bytes},{max_size_time},{max_size_buffers}")
|
|
||||||
} else {
|
|
||||||
writeln!(&mut file, "{timestamp},{name},0x{ptr:08x},{cur_level_bytes},{cur_level_time},{cur_level_buffers},{max_size_bytes},{max_size_time},{max_size_buffers}")
|
|
||||||
};
|
|
||||||
if let Err(err) = res {
|
|
||||||
gst::error!(CAT, imp = self, "Failed to write to file: {err}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,4 +523,54 @@ impl QueueLevels {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_log(&self, file_path: Option<&str>) {
|
||||||
|
use std::io::prelude::*;
|
||||||
|
|
||||||
|
let mut state = self.state.lock().unwrap();
|
||||||
|
let path = file_path.map_or_else(|| state.settings.file.clone(), PathBuf::from);
|
||||||
|
let first_write = state.logs_written.contains(&path);
|
||||||
|
|
||||||
|
let mut file = match std::fs::OpenOptions::new()
|
||||||
|
.append(!first_write)
|
||||||
|
.create(true)
|
||||||
|
.open(path.clone())
|
||||||
|
{
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(err) => {
|
||||||
|
gst::error!(CAT, imp = self, "Failed to create file: {err}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let log = std::mem::take(&mut state.log);
|
||||||
|
state.logs_written.insert(path);
|
||||||
|
drop(state);
|
||||||
|
|
||||||
|
gst::debug!(CAT, imp = self, "Writing file {:?}", file);
|
||||||
|
|
||||||
|
for LogLine {
|
||||||
|
timestamp,
|
||||||
|
name,
|
||||||
|
idx,
|
||||||
|
ptr,
|
||||||
|
cur_level_bytes,
|
||||||
|
cur_level_time,
|
||||||
|
cur_level_buffers,
|
||||||
|
max_size_bytes,
|
||||||
|
max_size_time,
|
||||||
|
max_size_buffers,
|
||||||
|
} in &log
|
||||||
|
{
|
||||||
|
let res = if let Some(idx) = idx {
|
||||||
|
writeln!(&mut file, "{timestamp},{name}:{idx},0x{ptr:08x},{cur_level_bytes},{cur_level_time},{cur_level_buffers},{max_size_bytes},{max_size_time},{max_size_buffers}")
|
||||||
|
} else {
|
||||||
|
writeln!(&mut file, "{timestamp},{name},0x{ptr:08x},{cur_level_bytes},{cur_level_time},{cur_level_buffers},{max_size_bytes},{max_size_time},{max_size_buffers}")
|
||||||
|
};
|
||||||
|
if let Err(err) = res {
|
||||||
|
gst::error!(CAT, imp = self, "Failed to write to file: {err}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue