From 9b6e14173ddee6a5a08f2ba077282743f47eb453 Mon Sep 17 00:00:00 2001 From: Thomas BESSOU Date: Sun, 2 Jun 2024 02:10:14 +0200 Subject: [PATCH 1/3] add tracing integration to librados --- src/ceph.rs | 1 + src/lib.rs | 1 + src/tracing_integration.rs | 106 +++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 src/tracing_integration.rs diff --git a/src/ceph.rs b/src/ceph.rs index 4001947..59ea7dc 100644 --- a/src/ceph.rs +++ b/src/ceph.rs @@ -393,6 +393,7 @@ pub fn connect_to_ceph(user_id: &str, config_file: &str) -> RadosResult { if ret_code < 0 { return Err(ret_code.into()); } + crate::tracing_integration::enable_tracing_integration(cluster_handle)?; let ret_code = rados_conf_read_file(cluster_handle, conf_file.as_ptr()); if ret_code < 0 { return Err(ret_code.into()); diff --git a/src/lib.rs b/src/lib.rs index caccece..58c69b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,7 @@ pub mod utils; mod ceph_client; mod ceph_version; mod mon_command; +mod tracing_integration; pub use crate::ceph_client::CephClient; pub use crate::ceph_version::CephVersion; diff --git a/src/tracing_integration.rs b/src/tracing_integration.rs new file mode 100644 index 0000000..2133d2a --- /dev/null +++ b/src/tracing_integration.rs @@ -0,0 +1,106 @@ +use crate::{error::RadosResult, rados::*}; + +use {libc::*, std::ffi::CStr, tracing::Level}; + +/// For tracing integration to function properly, logging (tracing handler) must be enabled before +/// the `Rados` struct is created. +pub(crate) fn enable_tracing_integration(rados: rados_t) -> RadosResult<()> { + let (level_str, opt_log_callback): (&[u8], rados_log_callback_t) = { + if event_enabled!(target: "librados", Level::ERROR) { + if event_enabled!(target: "librados", Level::WARN) { + if event_enabled!(target: "librados", Level::INFO) { + if event_enabled!(target: "librados", Level::DEBUG) { + (b"debug\0", Some(log_callback)) + } else { + (b"info\0", Some(log_callback)) + } + } else { + (b"warn\0", Some(log_callback)) + } + } else { + (b"error\0", Some(log_callback)) + } + } else { + (b"\0", None) + } + }; + + let level_cstr = + CStr::from_bytes_with_nul(level_str).expect("Constructed with trailing nul byte above"); + unsafe { + let ret_code = rados_monitor_log( + rados, + level_cstr.as_ptr(), + opt_log_callback, + 0 as *mut c_void, + ); + if ret_code < 0 { + return Err(ret_code.into()); + } + } + + Ok(()) +} + +extern "C" fn log_callback( + _arg: *mut ::std::os::raw::c_void, + line: *const ::libc::c_char, + who: *const ::libc::c_char, + _sec: u64, + _nsec: u64, + _seq: u64, + level: *const ::libc::c_char, + msg: *const ::libc::c_char, +) { + macro_rules! level { + ($($l: expr => $n: ident,)*) => { + match unsafe { *(level as *const u8) } { + $( + $l => { + if event_enabled!(target: "librados", Level::$n) { + Level::$n + } else { + return; + } + } + )* + _ => return, + } + }; + } + let level = level!( + b'e' => ERROR, + b'w' => WARN, + b'i' => INFO, + b'd' => DEBUG, + ); + + // We need to log, build the things + let who = unsafe { CStr::from_ptr(who) }; + let who = who.to_string_lossy(); + let line = unsafe { CStr::from_ptr(line) }; + let line: Option = line.to_str().ok().and_then(|l| l.parse().ok()); + let msg = unsafe { CStr::from_ptr(msg) }; + let msg = msg.to_string_lossy(); + + // Macro is necessary because tracing::event! requires level to be const + // https://github.com/tokio-rs/tracing/issues/2730 + macro_rules! build_and_capture_event { + ($($lvl: ident),*) => { + match level { + $( + Level::$lvl => { + if let Some(line) = line { + event!(target: "librados", Level::$lvl, %who, %line, "{msg}"); + } else { + event!(target: "librados", Level::$lvl, %who, "{msg}"); + } + }, + )* + _ => unreachable!(), + } + + }; + } + build_and_capture_event!(DEBUG, INFO, WARN, ERROR); +} From 208a248d65bbfa247cf2c3a0974a65ce47b61c11 Mon Sep 17 00:00:00 2001 From: Thomas BESSOU Date: Sat, 9 Nov 2024 16:54:14 +0100 Subject: [PATCH 2/3] For some reason this needs to be enabled after connecting --- src/ceph.rs | 3 ++- src/tracing_integration.rs | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ceph.rs b/src/ceph.rs index 59ea7dc..54bea8f 100644 --- a/src/ceph.rs +++ b/src/ceph.rs @@ -393,7 +393,6 @@ pub fn connect_to_ceph(user_id: &str, config_file: &str) -> RadosResult { if ret_code < 0 { return Err(ret_code.into()); } - crate::tracing_integration::enable_tracing_integration(cluster_handle)?; let ret_code = rados_conf_read_file(cluster_handle, conf_file.as_ptr()); if ret_code < 0 { return Err(ret_code.into()); @@ -402,6 +401,8 @@ pub fn connect_to_ceph(user_id: &str, config_file: &str) -> RadosResult { if ret_code < 0 { return Err(ret_code.into()); } + // Tracing integration needs to be enabled after we connected for some reason + crate::tracing_integration::enable_tracing_integration(cluster_handle)?; Ok(Rados { rados: cluster_handle, phantom: PhantomData, diff --git a/src/tracing_integration.rs b/src/tracing_integration.rs index 2133d2a..367ade7 100644 --- a/src/tracing_integration.rs +++ b/src/tracing_integration.rs @@ -1,9 +1,13 @@ -use crate::{error::RadosResult, rados::*}; +use crate::error::RadosResult; +use crate::rados::*; -use {libc::*, std::ffi::CStr, tracing::Level}; +use libc::*; +use std::ffi::CStr; +use tracing::Level; /// For tracing integration to function properly, logging (tracing handler) must be enabled before -/// the `Rados` struct is created. +/// connecting to ceph: if tracing is not enabled, we don't set a callback, which avoids the +/// corresponding overhead. pub(crate) fn enable_tracing_integration(rados: rados_t) -> RadosResult<()> { let (level_str, opt_log_callback): (&[u8], rados_log_callback_t) = { if event_enabled!(target: "librados", Level::ERROR) { From 60415586cdf98abb5a04805f230dd95d6590bf1c Mon Sep 17 00:00:00 2001 From: Thomas BESSOU Date: Sun, 15 Jun 2025 21:08:57 +0200 Subject: [PATCH 3/3] Fix log level detection in tracing integration --- src/tracing_integration.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/tracing_integration.rs b/src/tracing_integration.rs index 367ade7..a0a0281 100644 --- a/src/tracing_integration.rs +++ b/src/tracing_integration.rs @@ -58,7 +58,7 @@ extern "C" fn log_callback( ) { macro_rules! level { ($($l: expr => $n: ident,)*) => { - match unsafe { *(level as *const u8) } { + match unsafe { *((level as *const u8).add(1)) } { $( $l => { if event_enabled!(target: "librados", Level::$n) { @@ -68,15 +68,20 @@ extern "C" fn log_callback( } } )* - _ => return, + _ => { + let s = unsafe { CStr::from_ptr(level) }; + let level = s.to_string_lossy(); + event!(target: "librados", Level::WARN, "Unknown log level: {level} - please report issue at github.com/ceph/ceph-rust"); + Level::DEBUG + }, } }; } let level = level!( - b'e' => ERROR, - b'w' => WARN, - b'i' => INFO, - b'd' => DEBUG, + b'E' => ERROR, + b'W' => WARN, + b'I' => INFO, + b'D' => DEBUG, ); // We need to log, build the things