mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2025-09-01 17:33:50 +00:00
gstreamer: Add safe Rust bindings for the new LogContext API
Implements LogContext and LogContextBuilder bindings for GStreamer 1.28's new log context API, providing "log once" functionality and throttling support. The LogContext can be used anywhere DebugCategory is used, enabling message deduplication and periodic logging with configurable intervals. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/555 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1747>
This commit is contained in:
parent
b96e0438ae
commit
aacf979652
6 changed files with 1187 additions and 239 deletions
|
@ -58,6 +58,8 @@ manual = [
|
|||
"Gst.DeviceProviderClass", # for docs only
|
||||
"Gst.ElementClass", # for docs only
|
||||
"Gst.IdStr",
|
||||
"Gst.LogContext",
|
||||
"Gst.LogContextBuilder",
|
||||
"Gst.Rank",
|
||||
"Gst.Segment",
|
||||
"Gst.StaticCaps",
|
||||
|
@ -191,6 +193,10 @@ status = "generate"
|
|||
pattern = "debug_log.*"
|
||||
ignore = true
|
||||
|
||||
[[object.function]]
|
||||
pattern = "log_context.*"
|
||||
ignore = true
|
||||
|
||||
[[object.function]]
|
||||
name = "debug_set_color_mode"
|
||||
ignore = true
|
||||
|
@ -1504,6 +1510,20 @@ status = "generate"
|
|||
name = "num_errors"
|
||||
ignore = true
|
||||
|
||||
[[object]]
|
||||
name = "Gst.LogContextFlags"
|
||||
status = "generate"
|
||||
[[object.member]]
|
||||
name = "none"
|
||||
ignore = true
|
||||
|
||||
[[object]]
|
||||
name = "Gst.LogContextHashFlags"
|
||||
status = "generate"
|
||||
[[object.member]]
|
||||
name = "default"
|
||||
ignore = true
|
||||
|
||||
[[object]]
|
||||
name = "Gst.Memory"
|
||||
status = "manual"
|
||||
|
@ -2547,6 +2567,7 @@ status = "generate"
|
|||
[[object.derive]]
|
||||
name = "Debug"
|
||||
|
||||
|
||||
[[object]]
|
||||
name = "Gst.URIType"
|
||||
status = "generate"
|
||||
|
|
|
@ -980,6 +980,218 @@ impl From<GapFlags> for glib::Value {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
bitflags! {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[doc(alias = "GstLogContextFlags")]
|
||||
pub struct LogContextFlags: u32 {
|
||||
#[doc(alias = "GST_LOG_CONTEXT_FLAG_THROTTLE")]
|
||||
const THROTTLE = ffi::GST_LOG_CONTEXT_FLAG_THROTTLE as _;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(hidden)]
|
||||
impl IntoGlib for LogContextFlags {
|
||||
type GlibType = ffi::GstLogContextFlags;
|
||||
|
||||
#[inline]
|
||||
fn into_glib(self) -> ffi::GstLogContextFlags {
|
||||
self.bits()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(hidden)]
|
||||
impl FromGlib<ffi::GstLogContextFlags> for LogContextFlags {
|
||||
#[inline]
|
||||
unsafe fn from_glib(value: ffi::GstLogContextFlags) -> Self {
|
||||
skip_assert_initialized!();
|
||||
Self::from_bits_truncate(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl StaticType for LogContextFlags {
|
||||
#[inline]
|
||||
#[doc(alias = "gst_log_context_flags_get_type")]
|
||||
fn static_type() -> glib::Type {
|
||||
unsafe { from_glib(ffi::gst_log_context_flags_get_type()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl glib::HasParamSpec for LogContextFlags {
|
||||
type ParamSpec = glib::ParamSpecFlags;
|
||||
type SetValue = Self;
|
||||
type BuilderFn = fn(&str) -> glib::ParamSpecFlagsBuilder<Self>;
|
||||
|
||||
fn param_spec_builder() -> Self::BuilderFn {
|
||||
Self::ParamSpec::builder
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl glib::value::ValueType for LogContextFlags {
|
||||
type Type = Self;
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
unsafe impl<'a> glib::value::FromValue<'a> for LogContextFlags {
|
||||
type Checker = glib::value::GenericValueTypeChecker<Self>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_value(value: &'a glib::Value) -> Self {
|
||||
skip_assert_initialized!();
|
||||
from_glib(glib::gobject_ffi::g_value_get_flags(value.to_glib_none().0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl ToValue for LogContextFlags {
|
||||
#[inline]
|
||||
fn to_value(&self) -> glib::Value {
|
||||
let mut value = glib::Value::for_value_type::<Self>();
|
||||
unsafe {
|
||||
glib::gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, self.into_glib());
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_type(&self) -> glib::Type {
|
||||
Self::static_type()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl From<LogContextFlags> for glib::Value {
|
||||
#[inline]
|
||||
fn from(v: LogContextFlags) -> Self {
|
||||
skip_assert_initialized!();
|
||||
ToValue::to_value(&v)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
bitflags! {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[doc(alias = "GstLogContextHashFlags")]
|
||||
pub struct LogContextHashFlags: u32 {
|
||||
#[doc(alias = "GST_LOG_CONTEXT_IGNORE_OBJECT")]
|
||||
const IGNORE_OBJECT = ffi::GST_LOG_CONTEXT_IGNORE_OBJECT as _;
|
||||
#[doc(alias = "GST_LOG_CONTEXT_IGNORE_FORMAT")]
|
||||
const IGNORE_FORMAT = ffi::GST_LOG_CONTEXT_IGNORE_FORMAT as _;
|
||||
#[doc(alias = "GST_LOG_CONTEXT_IGNORE_FILE")]
|
||||
const IGNORE_FILE = ffi::GST_LOG_CONTEXT_IGNORE_FILE as _;
|
||||
#[doc(alias = "GST_LOG_CONTEXT_USE_LINE_NUMBER")]
|
||||
const USE_LINE_NUMBER = ffi::GST_LOG_CONTEXT_USE_LINE_NUMBER as _;
|
||||
#[doc(alias = "GST_LOG_CONTEXT_USE_STRING_ARGS")]
|
||||
const USE_STRING_ARGS = ffi::GST_LOG_CONTEXT_USE_STRING_ARGS as _;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(hidden)]
|
||||
impl IntoGlib for LogContextHashFlags {
|
||||
type GlibType = ffi::GstLogContextHashFlags;
|
||||
|
||||
#[inline]
|
||||
fn into_glib(self) -> ffi::GstLogContextHashFlags {
|
||||
self.bits()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(hidden)]
|
||||
impl FromGlib<ffi::GstLogContextHashFlags> for LogContextHashFlags {
|
||||
#[inline]
|
||||
unsafe fn from_glib(value: ffi::GstLogContextHashFlags) -> Self {
|
||||
skip_assert_initialized!();
|
||||
Self::from_bits_truncate(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl StaticType for LogContextHashFlags {
|
||||
#[inline]
|
||||
#[doc(alias = "gst_log_context_hash_flags_get_type")]
|
||||
fn static_type() -> glib::Type {
|
||||
unsafe { from_glib(ffi::gst_log_context_hash_flags_get_type()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl glib::HasParamSpec for LogContextHashFlags {
|
||||
type ParamSpec = glib::ParamSpecFlags;
|
||||
type SetValue = Self;
|
||||
type BuilderFn = fn(&str) -> glib::ParamSpecFlagsBuilder<Self>;
|
||||
|
||||
fn param_spec_builder() -> Self::BuilderFn {
|
||||
Self::ParamSpec::builder
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl glib::value::ValueType for LogContextHashFlags {
|
||||
type Type = Self;
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
unsafe impl<'a> glib::value::FromValue<'a> for LogContextHashFlags {
|
||||
type Checker = glib::value::GenericValueTypeChecker<Self>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_value(value: &'a glib::Value) -> Self {
|
||||
skip_assert_initialized!();
|
||||
from_glib(glib::gobject_ffi::g_value_get_flags(value.to_glib_none().0))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl ToValue for LogContextHashFlags {
|
||||
#[inline]
|
||||
fn to_value(&self) -> glib::Value {
|
||||
let mut value = glib::Value::for_value_type::<Self>();
|
||||
unsafe {
|
||||
glib::gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, self.into_glib());
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn value_type(&self) -> glib::Type {
|
||||
Self::static_type()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
impl From<LogContextHashFlags> for glib::Value {
|
||||
#[inline]
|
||||
fn from(v: LogContextHashFlags) -> Self {
|
||||
skip_assert_initialized!();
|
||||
ToValue::to_value(&v)
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[doc(alias = "GstMemoryFlags")]
|
||||
|
|
|
@ -165,6 +165,12 @@ pub use self::flags::EventTypeFlags;
|
|||
#[cfg(feature = "v1_20")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_20")))]
|
||||
pub use self::flags::GapFlags;
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
pub use self::flags::LogContextFlags;
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
pub use self::flags::LogContextHashFlags;
|
||||
pub use self::flags::MemoryFlags;
|
||||
pub use self::flags::MetaFlags;
|
||||
pub use self::flags::ObjectFlags;
|
||||
|
|
|
@ -50,17 +50,24 @@ mod serde_macros;
|
|||
|
||||
#[macro_use]
|
||||
pub mod log;
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
pub mod log_context;
|
||||
#[cfg(feature = "log")]
|
||||
pub use crate::log::DebugCategoryLogger;
|
||||
pub use crate::log::{
|
||||
DebugCategory, DebugLogFunction, DebugMessage, LoggedObject, CAT_BUFFER, CAT_BUFFER_LIST,
|
||||
CAT_BUS, CAT_CALL_TRACE, CAT_CAPS, CAT_CLOCK, CAT_CONTEXT, CAT_DEFAULT, CAT_ELEMENT_PADS,
|
||||
CAT_ERROR_SYSTEM, CAT_EVENT, CAT_GST_INIT, CAT_LOCKING, CAT_MEMORY, CAT_MESSAGE, CAT_META,
|
||||
CAT_NEGOTIATION, CAT_PADS, CAT_PARAMS, CAT_PARENTAGE, CAT_PERFORMANCE, CAT_PIPELINE,
|
||||
CAT_PLUGIN_INFO, CAT_PLUGIN_LOADING, CAT_PROBE, CAT_PROPERTIES, CAT_QOS, CAT_REFCOUNTING,
|
||||
CAT_REGISTRY, CAT_RUST, CAT_SCHEDULING, CAT_SIGNAL, CAT_STATES,
|
||||
DebugCategory, DebugLogFunction, DebugLogger, DebugMessage, LoggedObject, CAT_BUFFER,
|
||||
CAT_BUFFER_LIST, CAT_BUS, CAT_CALL_TRACE, CAT_CAPS, CAT_CLOCK, CAT_CONTEXT, CAT_DEFAULT,
|
||||
CAT_ELEMENT_PADS, CAT_ERROR_SYSTEM, CAT_EVENT, CAT_GST_INIT, CAT_LOCKING, CAT_MEMORY,
|
||||
CAT_MESSAGE, CAT_META, CAT_NEGOTIATION, CAT_PADS, CAT_PARAMS, CAT_PARENTAGE, CAT_PERFORMANCE,
|
||||
CAT_PIPELINE, CAT_PLUGIN_INFO, CAT_PLUGIN_LOADING, CAT_PROBE, CAT_PROPERTIES, CAT_QOS,
|
||||
CAT_REFCOUNTING, CAT_REGISTRY, CAT_RUST, CAT_SCHEDULING, CAT_SIGNAL, CAT_STATES,
|
||||
};
|
||||
|
||||
#[cfg(feature = "v1_28")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
pub use crate::log_context::{LogContext, LogContextBuilder};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -352,6 +359,7 @@ pub mod prelude {
|
|||
element::{ElementClassExt, ElementExtManual},
|
||||
format::prelude::*,
|
||||
gobject::GObjectExtManualGst,
|
||||
log::DebugLogger,
|
||||
memory::MemoryType,
|
||||
message::MessageErrorDomain,
|
||||
meta::{MetaAPI, MetaAPIExt, MetaTag},
|
||||
|
|
|
@ -158,14 +158,6 @@ impl DebugCategory {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn above_threshold(self, level: crate::DebugLevel) -> bool {
|
||||
match self.0 {
|
||||
Some(cat) => unsafe { cat.as_ref().threshold >= level.into_glib() },
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(alias = "get_color")]
|
||||
#[doc(alias = "gst_debug_category_get_color")]
|
||||
#[inline]
|
||||
|
@ -256,50 +248,6 @@ impl DebugCategory {
|
|||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
#[doc(alias = "gst_debug_log")]
|
||||
pub fn log_unfiltered(
|
||||
self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
self.log_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
args,
|
||||
)
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
#[doc(alias = "gst_debug_log_literal")]
|
||||
pub fn log_literal_unfiltered(
|
||||
self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
self.log_literal_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
msg,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn log_unfiltered_internal(
|
||||
self,
|
||||
|
@ -412,42 +360,6 @@ impl DebugCategory {
|
|||
self.log_id_literal_unfiltered_internal(id.as_ref(), level, file, function, line, msg);
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
#[doc(alias = "gst_debug_log_id")]
|
||||
pub fn log_id_unfiltered(
|
||||
self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
self.log_id_unfiltered_internal(id.as_ref(), level, file, function, line, args)
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
#[doc(alias = "gst_debug_log_id_literal")]
|
||||
pub fn log_id_literal_unfiltered(
|
||||
self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
self.log_id_literal_unfiltered_internal(id.as_ref(), level, file, function, line, msg)
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
#[inline(never)]
|
||||
fn log_id_unfiltered_internal(
|
||||
|
@ -542,6 +454,95 @@ impl DebugCategory {
|
|||
}
|
||||
}
|
||||
|
||||
impl DebugLogger for DebugCategory {
|
||||
#[inline]
|
||||
fn above_threshold(&self, level: crate::DebugLevel) -> bool {
|
||||
match self.0 {
|
||||
Some(cat) => unsafe { cat.as_ref().threshold >= level.into_glib() },
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
#[doc(alias = "gst_debug_log")]
|
||||
fn log_unfiltered(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
self.log_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
args,
|
||||
)
|
||||
}
|
||||
|
||||
#[doc(alias = "gst_debug_log_literal")]
|
||||
fn log_literal_unfiltered(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
self.log_literal_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
msg,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
#[doc(alias = "gst_debug_log_id_literal")]
|
||||
fn log_id_literal_unfiltered(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
self.log_id_literal_unfiltered_internal(id.as_ref(), level, file, function, line, msg)
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
#[doc(alias = "gst_debug_log_id")]
|
||||
fn log_id_unfiltered(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
self.log_id_unfiltered_internal(id.as_ref(), level, file, function, line, args)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for DebugCategory {}
|
||||
unsafe impl Send for DebugCategory {}
|
||||
|
||||
|
@ -621,144 +622,192 @@ declare_debug_category_from_name!(CAT_META, "GST_META");
|
|||
declare_debug_category_from_name!(CAT_LOCKING, "GST_LOCKING");
|
||||
declare_debug_category_from_name!(CAT_CONTEXT, "GST_CONTEXT");
|
||||
|
||||
pub trait DebugLogger {
|
||||
fn above_threshold(&self, level: DebugLevel) -> bool;
|
||||
|
||||
fn log_unfiltered(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
);
|
||||
|
||||
fn log_literal_unfiltered(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
);
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
fn log_id_unfiltered(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
);
|
||||
|
||||
#[cfg(feature = "v1_22")]
|
||||
fn log_id_literal_unfiltered(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! error(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Error, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Error, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Error, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Error, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Error, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Error, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Error, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Error, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! warning(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Warning, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Warning, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Warning, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Warning, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Warning, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Warning, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Warning, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Warning, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fixme(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Fixme, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Fixme, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Fixme, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Fixme, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Fixme, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Fixme, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Fixme, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Fixme, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! info(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Info, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Info, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Info, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Info, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Info, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Info, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Info, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Info, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! debug(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Debug, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Debug, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Debug, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Debug, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Debug, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Debug, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Debug, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Debug, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Log, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Log, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Log, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Log, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Log, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Log, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Log, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Log, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! trace(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Trace, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Trace, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Trace, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Trace, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Trace, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Trace, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Trace, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Trace, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! memdump(
|
||||
($cat:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Memdump, obj = $obj, $($args)*)
|
||||
($logger:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Memdump, obj = $obj, $($args)*)
|
||||
}};
|
||||
($cat:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Memdump, imp = $imp, $($args)*)
|
||||
($logger:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Memdump, imp = $imp, $($args)*)
|
||||
}};
|
||||
($cat:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Memdump, id = $id, $($args)*)
|
||||
($logger:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Memdump, id = $id, $($args)*)
|
||||
}};
|
||||
($cat:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($cat, $crate::DebugLevel::Memdump, $($args)*)
|
||||
($logger:expr, $($args:tt)*) => { {
|
||||
$crate::log_with_level!($logger, $crate::DebugLevel::Memdump, $($args)*)
|
||||
}};
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! log_with_level(
|
||||
($cat:expr, $level:expr, obj = $obj:expr, $msg:literal) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, obj = $obj:expr, $msg:literal) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
use $crate::glib::prelude::Cast;
|
||||
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
|
@ -773,8 +822,7 @@ macro_rules! log_with_level(
|
|||
// be assigned to a variable
|
||||
(|args: std::fmt::Arguments| {
|
||||
if args.as_str().is_some() {
|
||||
$crate::DebugCategory::log_literal_unfiltered(
|
||||
cat,
|
||||
logger.log_literal_unfiltered(
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -783,8 +831,7 @@ macro_rules! log_with_level(
|
|||
$crate::glib::gstr!($msg),
|
||||
)
|
||||
} else {
|
||||
$crate::DebugCategory::log_unfiltered(
|
||||
cat,
|
||||
logger.log_unfiltered(
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -796,13 +843,15 @@ macro_rules! log_with_level(
|
|||
})(format_args!($msg))
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, obj = $obj:expr, $($args:tt)*) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
use $crate::glib::prelude::Cast;
|
||||
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
|
@ -810,25 +859,26 @@ macro_rules! log_with_level(
|
|||
|
||||
let obj = &$obj;
|
||||
let obj = unsafe { obj.unsafe_cast_ref::<$crate::glib::Object>() };
|
||||
$crate::DebugCategory::log_unfiltered(
|
||||
cat,
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
$crate::glib::function_name!(),
|
||||
line!(),
|
||||
format_args!($($args)*),
|
||||
)
|
||||
logger.log_unfiltered(
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
$crate::glib::function_name!(),
|
||||
line!(),
|
||||
format_args!($($args)*),
|
||||
)
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, imp = $imp:expr, $msg:literal) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, imp = $imp:expr, $msg:literal) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
use $crate::glib::prelude::Cast;
|
||||
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
|
@ -843,8 +893,7 @@ macro_rules! log_with_level(
|
|||
// be assigned to a variable
|
||||
(|args: std::fmt::Arguments| {
|
||||
if args.as_str().is_some() {
|
||||
$crate::DebugCategory::log_literal_unfiltered(
|
||||
cat,
|
||||
logger.log_literal_unfiltered(
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -853,8 +902,7 @@ macro_rules! log_with_level(
|
|||
$crate::glib::gstr!($msg),
|
||||
)
|
||||
} else {
|
||||
$crate::DebugCategory::log_unfiltered(
|
||||
cat,
|
||||
logger.log_unfiltered(
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -866,13 +914,15 @@ macro_rules! log_with_level(
|
|||
})(format_args!($msg))
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, imp = $imp:expr, $($args:tt)*) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
use $crate::glib::prelude::Cast;
|
||||
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
|
@ -880,25 +930,26 @@ macro_rules! log_with_level(
|
|||
|
||||
let obj = $imp.obj();
|
||||
let obj = unsafe { obj.unsafe_cast_ref::<$crate::glib::Object>() };
|
||||
$crate::DebugCategory::log_unfiltered(
|
||||
cat,
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
$crate::glib::function_name!(),
|
||||
line!(),
|
||||
format_args!($($args)*),
|
||||
)
|
||||
logger.log_unfiltered(
|
||||
Some(obj),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
$crate::glib::function_name!(),
|
||||
line!(),
|
||||
format_args!($($args)*),
|
||||
)
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, id = $id:literal, $msg:literal) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, id = $id:literal, $msg:literal) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
// directly pass it as `&GStr` forward
|
||||
|
||||
|
@ -909,8 +960,7 @@ macro_rules! log_with_level(
|
|||
// be assigned to a variable
|
||||
(|args: std::fmt::Arguments| {
|
||||
if args.as_str().is_some() {
|
||||
$crate::DebugCategory::log_id_literal_unfiltered(
|
||||
cat,
|
||||
logger.log_id_literal_unfiltered(
|
||||
$crate::glib::gstr!($id),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -919,8 +969,7 @@ macro_rules! log_with_level(
|
|||
$crate::glib::gstr!($msg),
|
||||
)
|
||||
} else {
|
||||
$crate::DebugCategory::log_id_unfiltered(
|
||||
cat,
|
||||
logger.log_id_unfiltered(
|
||||
$crate::glib::gstr!($id),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -932,35 +981,38 @@ macro_rules! log_with_level(
|
|||
})(format_args!($msg))
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, id = $id:literal, $($args:tt)*) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, id = $id:literal, $($args:tt)*) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
// directly pass it as `&GStr` forward
|
||||
|
||||
$crate::DebugCategory::log_id_unfiltered(
|
||||
cat,
|
||||
$crate::glib::gstr!($id),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
$crate::glib::function_name!(),
|
||||
line!(),
|
||||
format_args!($($args)*),
|
||||
)
|
||||
logger.log_id_unfiltered(
|
||||
$crate::glib::gstr!($id),
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
$crate::glib::function_name!(),
|
||||
line!(),
|
||||
format_args!($($args)*),
|
||||
)
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, id = $id:expr, $msg:literal) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, id = $id:expr, $msg:literal) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
// directly pass it as `&GStr` forward
|
||||
|
||||
|
@ -971,8 +1023,7 @@ macro_rules! log_with_level(
|
|||
// be assigned to a variable
|
||||
(|args: std::fmt::Arguments| {
|
||||
if args.as_str().is_some() {
|
||||
$crate::DebugCategory::log_id_literal_unfiltered(
|
||||
cat,
|
||||
logger.log_id_literal_unfiltered(
|
||||
$id,
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -981,8 +1032,7 @@ macro_rules! log_with_level(
|
|||
$crate::glib::gstr!($msg),
|
||||
)
|
||||
} else {
|
||||
$crate::DebugCategory::log_id_unfiltered(
|
||||
cat,
|
||||
logger.log_id_unfiltered(
|
||||
$id,
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -994,18 +1044,19 @@ macro_rules! log_with_level(
|
|||
})(format_args!($msg))
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, id = $id:expr, $($args:tt)*) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
// directly pass it as `&GStr` forward
|
||||
|
||||
$crate::DebugCategory::log_id_unfiltered(
|
||||
cat,
|
||||
logger.log_id_unfiltered(
|
||||
$id,
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -1015,14 +1066,16 @@ macro_rules! log_with_level(
|
|||
)
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, $msg:literal) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, $msg:literal) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
#[allow(clippy::redundant_closure_call)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
// directly pass it as `&GStr` forward
|
||||
|
||||
|
@ -1033,8 +1086,7 @@ macro_rules! log_with_level(
|
|||
// be assigned to a variable
|
||||
(|args: std::fmt::Arguments| {
|
||||
if args.as_str().is_some() {
|
||||
$crate::DebugCategory::log_literal_unfiltered(
|
||||
cat,
|
||||
logger.log_literal_unfiltered(
|
||||
None as Option<&$crate::glib::Object>,
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -1043,8 +1095,7 @@ macro_rules! log_with_level(
|
|||
$crate::glib::gstr!($msg),
|
||||
)
|
||||
} else {
|
||||
$crate::DebugCategory::log_unfiltered(
|
||||
cat,
|
||||
logger.log_unfiltered(
|
||||
None as Option<&$crate::glib::Object>,
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
@ -1056,18 +1107,19 @@ macro_rules! log_with_level(
|
|||
})(format_args!($msg))
|
||||
}
|
||||
}};
|
||||
($cat:expr, $level:expr, $($args:tt)*) => { {
|
||||
let cat = $cat.clone();
|
||||
($logger:expr, $level:expr, $($args:tt)*) => { {
|
||||
#[allow(unused_imports)]
|
||||
use $crate::log::DebugLogger;
|
||||
let logger = &$logger;
|
||||
|
||||
// Check the log level before using `format_args!` otherwise
|
||||
// formatted arguments are evaluated even if we end up not logging.
|
||||
#[allow(unused_unsafe)]
|
||||
if cat.above_threshold($level) {
|
||||
if logger.above_threshold($level) {
|
||||
// FIXME: Once there's a function_name! macro that returns a string literal we can
|
||||
// directly pass it as `&GStr` forward
|
||||
|
||||
$crate::DebugCategory::log_unfiltered(
|
||||
cat,
|
||||
logger.log_unfiltered(
|
||||
None as Option<&$crate::glib::Object>,
|
||||
$level,
|
||||
unsafe { $crate::glib::GStr::from_utf8_with_nul_unchecked(concat!(file!(), "\0").as_bytes()) },
|
||||
|
|
649
gstreamer/src/log_context.rs
Normal file
649
gstreamer/src/log_context.rs
Normal file
|
@ -0,0 +1,649 @@
|
|||
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||
|
||||
use std::{fmt, io::Write, ptr};
|
||||
|
||||
use glib::{prelude::*, translate::*};
|
||||
|
||||
use crate::log::DebugLogger;
|
||||
use crate::{ffi, ClockTime, DebugCategory, DebugLevel, LogContextFlags, LogContextHashFlags};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[doc(alias = "GstLogContext")]
|
||||
#[repr(transparent)]
|
||||
pub struct LogContext(ptr::NonNull<ffi::GstLogContext>);
|
||||
|
||||
impl LogContext {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_log_context_get_category")]
|
||||
#[doc(alias = "get_category")]
|
||||
#[inline]
|
||||
pub fn category(&self) -> DebugCategory {
|
||||
unsafe { from_glib_none(ffi::gst_log_context_get_category(self.0.as_ptr())) }
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_log_context_reset")]
|
||||
#[inline]
|
||||
pub fn reset(&self) {
|
||||
unsafe {
|
||||
ffi::gst_log_context_reset(self.0.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *mut ffi::GstLogContext {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline(never)]
|
||||
fn log_unfiltered_internal(
|
||||
&self,
|
||||
obj: Option<&glib::Object>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
let mut w = smallvec::SmallVec::<[u8; 256]>::new();
|
||||
|
||||
// Can't really happen but better safe than sorry
|
||||
if Write::write_fmt(&mut w, args).is_err() {
|
||||
return;
|
||||
}
|
||||
w.push(0);
|
||||
|
||||
self.log_literal_unfiltered_internal(obj, level, file, function, line, unsafe {
|
||||
glib::GStr::from_utf8_with_nul_unchecked(&w)
|
||||
});
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn log_literal_unfiltered_internal(
|
||||
&self,
|
||||
obj: Option<&glib::Object>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
let obj_ptr = match obj {
|
||||
Some(obj) => obj.as_ptr(),
|
||||
None => ptr::null_mut(),
|
||||
};
|
||||
|
||||
function.run_with_gstr(|function| unsafe {
|
||||
ffi::gst_debug_log_literal_with_context(
|
||||
self.0.as_ptr(),
|
||||
level.into_glib(),
|
||||
file.as_ptr(),
|
||||
function.as_ptr(),
|
||||
line as i32,
|
||||
obj_ptr,
|
||||
msg.as_ptr(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn log_id_unfiltered_internal(
|
||||
&self,
|
||||
id: &glib::GStr,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
let mut w = smallvec::SmallVec::<[u8; 256]>::new();
|
||||
|
||||
// Can't really happen but better safe than sorry
|
||||
if Write::write_fmt(&mut w, args).is_err() {
|
||||
return;
|
||||
}
|
||||
w.push(0);
|
||||
|
||||
self.log_id_literal_unfiltered_internal(id, level, file, function, line, unsafe {
|
||||
glib::GStr::from_utf8_with_nul_unchecked(&w)
|
||||
});
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn log_id_literal_unfiltered_internal(
|
||||
&self,
|
||||
id: &glib::GStr,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
function.run_with_gstr(|function| unsafe {
|
||||
ffi::gst_debug_log_id_literal_with_context(
|
||||
self.0.as_ptr(),
|
||||
level.into_glib(),
|
||||
file.as_ptr(),
|
||||
function.as_ptr(),
|
||||
line as i32,
|
||||
id.as_ptr(),
|
||||
msg.as_ptr(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_debug_log_with_context")]
|
||||
pub fn log(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
if !self.above_threshold(level) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.log_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
args,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_debug_log_literal_with_context")]
|
||||
pub fn log_literal(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
if !self.above_threshold(level) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.log_literal_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
msg,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_debug_log_id_with_context")]
|
||||
pub fn log_id(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: fmt::Arguments,
|
||||
) {
|
||||
if !self.above_threshold(level) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.log_id_unfiltered_internal(id.as_ref(), level, file, function, line, args);
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_debug_log_id_literal_with_context")]
|
||||
pub fn log_id_literal(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
if !self.above_threshold(level) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.log_id_literal_unfiltered_internal(id.as_ref(), level, file, function, line, msg);
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LogContext {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::gst_log_context_free(self.0.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for LogContext {}
|
||||
unsafe impl Sync for LogContext {}
|
||||
|
||||
impl crate::log::DebugLogger for LogContext {
|
||||
#[inline]
|
||||
fn above_threshold(&self, level: crate::DebugLevel) -> bool {
|
||||
self.category().above_threshold(level)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn log_unfiltered(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: std::fmt::Arguments,
|
||||
) {
|
||||
self.log_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
args,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn log_literal_unfiltered(
|
||||
&self,
|
||||
obj: Option<&impl IsA<glib::Object>>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
self.log_literal_unfiltered_internal(
|
||||
obj.map(|obj| obj.as_ref()),
|
||||
level,
|
||||
file,
|
||||
function,
|
||||
line,
|
||||
msg,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn log_id_unfiltered(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
args: std::fmt::Arguments,
|
||||
) {
|
||||
self.log_id_unfiltered_internal(id.as_ref(), level, file, function, line, args)
|
||||
}
|
||||
|
||||
// rustdoc-stripper-ignore-next
|
||||
/// Logs without checking the log level.
|
||||
#[inline]
|
||||
fn log_id_literal_unfiltered(
|
||||
&self,
|
||||
id: impl AsRef<glib::GStr>,
|
||||
level: crate::DebugLevel,
|
||||
file: &glib::GStr,
|
||||
function: &str,
|
||||
line: u32,
|
||||
msg: &glib::GStr,
|
||||
) {
|
||||
self.log_id_literal_unfiltered_internal(id.as_ref(), level, file, function, line, msg)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[doc(alias = "GstLogContextBuilder")]
|
||||
#[repr(transparent)]
|
||||
pub struct LogContextBuilder(ptr::NonNull<ffi::GstLogContextBuilder>);
|
||||
|
||||
impl LogContextBuilder {
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_log_context_builder_new")]
|
||||
pub fn new(category: DebugCategory, flags: LogContextFlags) -> Self {
|
||||
skip_assert_initialized!();
|
||||
unsafe {
|
||||
let ptr = ffi::gst_log_context_builder_new(category.as_ptr(), flags.into_glib());
|
||||
LogContextBuilder(ptr::NonNull::new_unchecked(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_log_context_builder_set_hash_flags")]
|
||||
pub fn hash_flags(self, flags: LogContextHashFlags) -> Self {
|
||||
unsafe {
|
||||
ffi::gst_log_context_builder_set_hash_flags(self.0.as_ptr(), flags.into_glib());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_log_context_builder_set_category")]
|
||||
pub fn category(self, category: DebugCategory) -> Self {
|
||||
unsafe {
|
||||
ffi::gst_log_context_builder_set_category(self.0.as_ptr(), category.as_ptr());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_log_context_builder_set_interval")]
|
||||
pub fn interval(self, interval: impl Into<Option<ClockTime>>) -> Self {
|
||||
unsafe {
|
||||
ffi::gst_log_context_builder_set_interval(self.0.as_ptr(), interval.into().into_glib());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "v1_28")))]
|
||||
#[doc(alias = "gst_log_context_builder_build")]
|
||||
pub fn build(self) -> LogContext {
|
||||
unsafe {
|
||||
let ptr = ffi::gst_log_context_builder_build(self.0.as_ptr());
|
||||
LogContext(ptr::NonNull::new_unchecked(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{log::DebugLogger, DebugLevel, LogContextFlags, LogContextHashFlags};
|
||||
|
||||
#[test]
|
||||
fn log_context_builder_basic() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-log-context",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test log context category"),
|
||||
);
|
||||
|
||||
// Test basic builder pattern
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::empty()).build();
|
||||
|
||||
assert_eq!(context.category(), cat);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_builder_with_flags() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-log-context-flags",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test log context with flags"),
|
||||
);
|
||||
|
||||
// Test builder with various configuration options
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::THROTTLE)
|
||||
.hash_flags(LogContextHashFlags::USE_LINE_NUMBER)
|
||||
.interval(Some(crate::ClockTime::from_seconds(1)))
|
||||
.build();
|
||||
|
||||
assert_eq!(context.category(), cat);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_trait_implementation() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-trait-impl",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test trait implementation"),
|
||||
);
|
||||
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::empty()).build();
|
||||
|
||||
// Test that LogContext implements DebugLogger trait
|
||||
assert_eq!(
|
||||
context.above_threshold(DebugLevel::Error),
|
||||
cat.above_threshold(DebugLevel::Error)
|
||||
);
|
||||
assert_eq!(
|
||||
context.above_threshold(DebugLevel::Debug),
|
||||
cat.above_threshold(DebugLevel::Debug)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_with_macros() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-macro-usage",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test macro usage"),
|
||||
);
|
||||
cat.set_threshold(DebugLevel::Trace);
|
||||
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::empty()).build();
|
||||
|
||||
// Test that LogContext works with all the logging macros
|
||||
crate::error!(context, "error message");
|
||||
crate::error!(&context, "error message");
|
||||
crate::warning!(context, "warning message");
|
||||
crate::warning!(&context, "warning message");
|
||||
crate::info!(context, "info message");
|
||||
crate::info!(&context, "info message");
|
||||
crate::debug!(context, "debug message");
|
||||
crate::debug!(&context, "debug message");
|
||||
crate::trace!(context, "trace message");
|
||||
crate::trace!(&context, "trace message");
|
||||
|
||||
// Test with object
|
||||
let obj = crate::Bin::with_name("test-bin");
|
||||
crate::error!(context, obj = &obj, "error with object");
|
||||
crate::warning!(context, obj = &obj, "warning with object");
|
||||
|
||||
// Test with formatting
|
||||
let value = 42;
|
||||
crate::info!(context, "formatted message: {}", value);
|
||||
crate::debug!(context, obj = &obj, "formatted with obj: {}", value);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_interchangeable_with_category() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-interchangeable",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test interchangeable usage"),
|
||||
);
|
||||
cat.set_threshold(DebugLevel::Info);
|
||||
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::empty()).build();
|
||||
|
||||
// Test that we can use both category and context in the same way
|
||||
let test_message = "test message";
|
||||
|
||||
// These should both work identically
|
||||
crate::info!(cat, "{}", test_message);
|
||||
crate::info!(&cat, "{}", test_message);
|
||||
crate::info!(context, "{}", test_message);
|
||||
crate::info!(&context, "{}", test_message);
|
||||
|
||||
// With objects too
|
||||
let obj = crate::Bin::with_name("test-bin-2");
|
||||
crate::info!(cat, obj = &obj, "{}", test_message);
|
||||
crate::info!(context, obj = &obj, "{}", test_message);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn static_log_context() {
|
||||
crate::init().unwrap();
|
||||
|
||||
// Create a static category first
|
||||
static TEST_CATEGORY: std::sync::LazyLock<crate::DebugCategory> =
|
||||
std::sync::LazyLock::new(|| {
|
||||
crate::DebugCategory::new(
|
||||
"test-static-context",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test static context"),
|
||||
)
|
||||
});
|
||||
|
||||
// Create static context directly with LazyLock
|
||||
static TEST_CONTEXT: std::sync::LazyLock<LogContext> = std::sync::LazyLock::new(|| {
|
||||
LogContextBuilder::new(*TEST_CATEGORY, LogContextFlags::empty()).build()
|
||||
});
|
||||
|
||||
// Use the static context
|
||||
crate::info!(TEST_CONTEXT, "message from static context");
|
||||
|
||||
assert_eq!(TEST_CONTEXT.category(), *TEST_CATEGORY);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn static_log_context_with_advanced_options() {
|
||||
crate::init().unwrap();
|
||||
|
||||
// Create a static category first
|
||||
static ADVANCED_CATEGORY: std::sync::LazyLock<crate::DebugCategory> =
|
||||
std::sync::LazyLock::new(|| {
|
||||
crate::DebugCategory::new(
|
||||
"test-static-advanced",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test static context advanced"),
|
||||
)
|
||||
});
|
||||
|
||||
// Create static context with advanced options using LazyLock
|
||||
static ADVANCED_CONTEXT: std::sync::LazyLock<LogContext> = std::sync::LazyLock::new(|| {
|
||||
LogContextBuilder::new(*ADVANCED_CATEGORY, LogContextFlags::THROTTLE)
|
||||
.hash_flags(LogContextHashFlags::USE_LINE_NUMBER)
|
||||
.interval(Some(crate::ClockTime::from_seconds(2)))
|
||||
.build()
|
||||
});
|
||||
|
||||
crate::debug!(ADVANCED_CONTEXT, "advanced static context message");
|
||||
assert_eq!(ADVANCED_CONTEXT.category(), *ADVANCED_CATEGORY);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_with_id_logging() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-id-logging",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test ID logging"),
|
||||
);
|
||||
cat.set_threshold(DebugLevel::Trace);
|
||||
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::empty()).build();
|
||||
|
||||
// Test ID-based logging with LogContext
|
||||
crate::trace!(context, id = "test-id-123", "message with ID");
|
||||
crate::debug!(
|
||||
context,
|
||||
id = "test-id-456",
|
||||
"another message with ID: {}",
|
||||
42
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_memory_safety() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-memory-safety",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test memory safety"),
|
||||
);
|
||||
|
||||
// Test that LogContext can be safely dropped
|
||||
{
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::empty()).build();
|
||||
crate::info!(context, "message before drop");
|
||||
} // context is dropped here
|
||||
|
||||
// Create another context to ensure no memory issues
|
||||
let context2 = LogContextBuilder::new(cat, LogContextFlags::THROTTLE).build();
|
||||
crate::info!(context2, "message from second context");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_category_consistency() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat1 = crate::DebugCategory::new(
|
||||
"test-consistency-1",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test consistency 1"),
|
||||
);
|
||||
|
||||
let cat2 = crate::DebugCategory::new(
|
||||
"test-consistency-2",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test consistency 2"),
|
||||
);
|
||||
|
||||
let context1 = LogContextBuilder::new(cat1, LogContextFlags::empty()).build();
|
||||
let context2 = LogContextBuilder::new(cat2, LogContextFlags::empty()).build();
|
||||
|
||||
// Verify that contexts maintain their respective categories
|
||||
assert_eq!(context1.category(), cat1);
|
||||
assert_eq!(context2.category(), cat2);
|
||||
assert_ne!(context1.category(), cat2);
|
||||
assert_ne!(context2.category(), cat1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn log_context_threshold_behavior() {
|
||||
crate::init().unwrap();
|
||||
|
||||
let cat = crate::DebugCategory::new(
|
||||
"test-threshold",
|
||||
crate::DebugColorFlags::empty(),
|
||||
Some("Test threshold behavior"),
|
||||
);
|
||||
|
||||
let context = LogContextBuilder::new(cat, LogContextFlags::empty()).build();
|
||||
|
||||
// Test threshold behavior matches between category and context
|
||||
cat.set_threshold(DebugLevel::Warning);
|
||||
|
||||
assert!(context.above_threshold(DebugLevel::Error));
|
||||
assert!(context.above_threshold(DebugLevel::Warning));
|
||||
assert!(!context.above_threshold(DebugLevel::Info));
|
||||
assert!(!context.above_threshold(DebugLevel::Debug));
|
||||
|
||||
// Same as category
|
||||
assert_eq!(
|
||||
context.above_threshold(DebugLevel::Error),
|
||||
cat.above_threshold(DebugLevel::Error)
|
||||
);
|
||||
assert_eq!(
|
||||
context.above_threshold(DebugLevel::Warning),
|
||||
cat.above_threshold(DebugLevel::Warning)
|
||||
);
|
||||
assert_eq!(
|
||||
context.above_threshold(DebugLevel::Info),
|
||||
cat.above_threshold(DebugLevel::Info)
|
||||
);
|
||||
assert_eq!(
|
||||
context.above_threshold(DebugLevel::Debug),
|
||||
cat.above_threshold(DebugLevel::Debug)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue