diff --git a/Cargo.lock b/Cargo.lock index 940ee82c0..9545c934e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3041,6 +3041,7 @@ dependencies = [ "livekit-api", "livekit-protocol", "log", + "metrics-logger", "parking_lot", "prost 0.14.1", "prost-build 0.14.1", @@ -3181,6 +3182,25 @@ dependencies = [ "paste", ] +[[package]] +name = "metrics" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d05972e8cbac2671e85aa9d04d9160d193f8bebd1a5c1a2f4542c62e65d1d0" +dependencies = [ + "ahash", + "portable-atomic", +] + +[[package]] +name = "metrics-logger" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51842f541c2515cf93ee1a4ef97728816d5ca163d70cbc67d8605246725fec7d" +dependencies = [ + "metrics", +] + [[package]] name = "mime" version = "0.3.17" diff --git a/livekit-ffi/Cargo.toml b/livekit-ffi/Cargo.toml index 326be17b6..aad39dfe9 100644 --- a/livekit-ffi/Cargo.toml +++ b/livekit-ffi/Cargo.toml @@ -37,6 +37,7 @@ downcast-rs = "1.2" console-subscriber = { version = "0.1", features = ["parking_lot"], optional = true } bytes = "1.10.1" from_variants = "1.0.2" +metrics-logger = "0.22.1" [target.'cfg(target_os = "android")'.dependencies] jni = "0.21.1" diff --git a/livekit-ffi/src/server/colorcvt/cvtimpl.rs b/livekit-ffi/src/server/colorcvt/cvtimpl.rs index 24bb0b4f0..02e16628c 100644 --- a/livekit-ffi/src/server/colorcvt/cvtimpl.rs +++ b/livekit-ffi/src/server/colorcvt/cvtimpl.rs @@ -12,10 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::time::Instant; + use super::*; use crate::proto; use crate::{FfiError, FfiResult}; use imgproc::colorcvt; +use metrics_logger::metrics::histogram; pub unsafe fn cvt( buffer: proto::VideoBufferInfo, @@ -312,16 +315,24 @@ pub unsafe fn cvt_i420( | proto::VideoBufferType::Abgr | proto::VideoBufferType::Argb | proto::VideoBufferType::Bgra => { + + let start = Instant::now(); let mut dst = vec![0u8; (width * height * 4) as usize].into_boxed_slice(); + let delta = start.elapsed(); + histogram!("dst_alloc").record(delta.as_millis() as f64); + let stride = width * 4; macro_rules! cvt { ($rgba:expr, $fnc:ident) => { if dst_type == $rgba { + let start = Instant::now(); colorcvt::$fnc( data_y, c0.stride, data_u, c1.stride, data_v, c2.stride, &mut dst, stride, width, height, flip_y, ); + let delta = start.elapsed(); + histogram!(stringify!($fnc)).record(delta.as_millis() as f64); } }; } diff --git a/livekit-ffi/src/server/mod.rs b/livekit-ffi/src/server/mod.rs index 91939f7f7..caaf3e095 100644 --- a/livekit-ffi/src/server/mod.rs +++ b/livekit-ffi/src/server/mod.rs @@ -29,6 +29,7 @@ use livekit::webrtc::{ }; use parking_lot::{deadlock, Mutex}; use tokio::{sync::oneshot, task::JoinHandle}; +use metrics_logger::{metrics, MetricsLogger, LogMode}; use crate::{proto, proto::FfiEvent, FfiError, FfiHandleId, FfiResult, INVALID_HANDLE}; @@ -101,6 +102,13 @@ impl Default for FfiServer { #[cfg(feature = "tracing")] console_subscriber::init(); + let recorder = MetricsLogger::new( + LogMode::Periodic(10), + |logs| log::info!(target: "metrics", "{}", logs), + |err| log::error!(target: "metrics", "{}", err), + ); + metrics::set_global_recorder(recorder).unwrap(); + // Create a background thread which checks for deadlocks every 10s thread::spawn(move || loop { thread::sleep(Duration::from_secs(10)); diff --git a/livekit-ffi/src/server/requests.rs b/livekit-ffi/src/server/requests.rs index 644e25e4f..15547f1a0 100644 --- a/livekit-ffi/src/server/requests.rs +++ b/livekit-ffi/src/server/requests.rs @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{slice, sync::Arc}; +use std::{slice, sync::Arc, time::Instant}; +use metrics_logger::metrics::histogram; use colorcvt::cvtimpl; use livekit::{ @@ -480,7 +481,13 @@ unsafe fn on_video_convert( let ref buffer = video_convert.buffer; let flip_y = video_convert.flip_y; let dst_type = video_convert.dst_type(); - match cvtimpl::cvt(buffer.clone(), dst_type, flip_y.unwrap_or(false)) { + + let start = Instant::now(); + let cvt_result = cvtimpl::cvt(buffer.clone(), dst_type, flip_y.unwrap_or(false)); + let delta = start.elapsed(); + histogram!("color_cvt").record(delta.as_millis() as f64); + + match cvt_result { Ok((buffer, info)) => { let id = server.next_id(); server.store_handle(id, buffer);