From 29068265dbb6fe52e794c66da9fabe9985fc6f33 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Thu, 23 Mar 2023 16:43:04 +0100 Subject: [PATCH] ffi: Add filtering of tracing events and spans --- bindings/matrix-sdk-ffi/src/tracing.rs | 76 ++++++++++++++++++-------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/bindings/matrix-sdk-ffi/src/tracing.rs b/bindings/matrix-sdk-ffi/src/tracing.rs index 7c0d108d0..1e8f1585a 100644 --- a/bindings/matrix-sdk-ffi/src/tracing.rs +++ b/bindings/matrix-sdk-ffi/src/tracing.rs @@ -7,8 +7,6 @@ use once_cell::sync::OnceCell; use tracing::{callsite::DefaultCallsite, field::FieldSet, Callsite}; use tracing_core::{identify_callsite, metadata::Kind as MetadataKind}; -type StaticMetadata = &'static tracing::Metadata<'static>; - #[uniffi::export] fn log_event( file: String, @@ -18,23 +16,27 @@ fn log_event( target: String, message: String, ) { - static METADATA: Mutex> = Mutex::new(BTreeMap::new()); + static CALLSITES: Mutex> = + Mutex::new(BTreeMap::new()); let loc = Location::new(file, line, column); - let metadata = get_or_init_metadata(&METADATA, loc, level, target, |loc| { + let callsite = get_or_init_metadata(&CALLSITES, loc, level, target, |loc| { (format!("event {}:{}", loc.file, loc.line), &["message"], MetadataKind::EVENT) }); + let metadata = callsite.metadata(); - let fields = metadata.fields(); - let message_field = fields.field("message").unwrap(); - #[allow(trivial_casts)] // The compiler is lying, it can't infer this cast - let values = [(&message_field, Some(&message as &dyn tracing::Value))]; + if span_or_event_enabled(callsite) { + let fields = metadata.fields(); + let message_field = fields.field("message").unwrap(); + #[allow(trivial_casts)] // The compiler is lying, it can't infer this cast + let values = [(&message_field, Some(&message as &dyn tracing::Value))]; - // This function is hidden from docs, but we have to use it - // because there is no other way of obtaining a `ValueSet`. - // It's not entirely clear why it is private. See this issue: - // https://github.com/tokio-rs/tracing/issues/2363 - let values = fields.value_set(&values); - tracing::Event::dispatch(metadata, &values); + // This function is hidden from docs, but we have to use it + // because there is no other way of obtaining a `ValueSet`. + // It's not entirely clear why it is private. See this issue: + // https://github.com/tokio-rs/tracing/issues/2363 + let values = fields.value_set(&values); + tracing::Event::dispatch(metadata, &values); + } } #[uniffi::export] @@ -46,25 +48,34 @@ fn make_span( target: String, name: String, ) -> Arc { - static METADATA: Mutex> = Mutex::new(BTreeMap::new()); + static CALLSITES: Mutex> = + Mutex::new(BTreeMap::new()); let loc = Location::new(file, line, column); - let metadata = - get_or_init_metadata(&METADATA, loc, level, target, |_loc| (name, &[], MetadataKind::SPAN)); + let callsite = get_or_init_metadata(&CALLSITES, loc, level, target, |_loc| { + (name, &[], MetadataKind::SPAN) + }); + let metadata = callsite.metadata(); - // This function is hidden from docs, but we have to use it (see above). - let values = metadata.fields().value_set(&[]); - Arc::new(Span(tracing::Span::new(metadata, &values))) + let span = if span_or_event_enabled(callsite) { + // This function is hidden from docs, but we have to use it (see above). + let values = metadata.fields().value_set(&[]); + tracing::Span::new(metadata, &values) + } else { + tracing::Span::none() + }; + + Arc::new(Span(span)) } type FieldNames = &'static [&'static str]; fn get_or_init_metadata( - mutex: &Mutex>, + mutex: &Mutex>, loc: Location, level: LogLevel, target: String, get_details: impl FnOnce(&Location) -> (String, FieldNames, MetadataKind), -) -> StaticMetadata { +) -> &'static DefaultCallsite { mutex.lock().unwrap().entry(loc).or_insert_with_key(|loc| { let (name, field_names, span_kind) = get_details(loc); let callsite = Box::leak(Box::new(LateInitCallsite(OnceCell::new()))); @@ -78,11 +89,28 @@ fn get_or_init_metadata( FieldSet::new(field_names, identify_callsite!(callsite)), span_kind, ))); - callsite.0.set(DefaultCallsite::new(metadata)).expect("callsite was not set before"); - metadata + callsite.0.try_insert(DefaultCallsite::new(metadata)).expect("callsite was not set before") }) } +fn span_or_event_enabled(callsite: &'static DefaultCallsite) -> bool { + use tracing::{ + dispatcher, + level_filters::{LevelFilter, STATIC_MAX_LEVEL}, + }; + + let meta = callsite.metadata(); + let level = *meta.level(); + + if level > STATIC_MAX_LEVEL || level > LevelFilter::current() { + false + } else { + let interest = callsite.interest(); + interest.is_always() + || !interest.is_never() && dispatcher::get_default(|default| default.enabled(meta)) + } +} + pub struct Span(tracing::Span); impl Span {