mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-06 15:04:11 -04:00
ffi: Add basic tracing bindings
This commit is contained in:
committed by
Jonas Platte
parent
0da8e56a68
commit
bb05ac7dac
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -2791,6 +2791,7 @@ dependencies = [
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
"tracing-android",
|
||||
"tracing-core",
|
||||
"tracing-opentelemetry",
|
||||
"tracing-subscriber",
|
||||
"uniffi",
|
||||
|
||||
@@ -41,6 +41,7 @@ serde_json = "1.0.91"
|
||||
thiserror = "1.0.38"
|
||||
tokio = { version = "1.24", default-features = false, features = ["sync"] }
|
||||
tracing = { version = "0.1.36", default-features = false, features = ["std"] }
|
||||
tracing-core = "0.1.30"
|
||||
uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "41e94c0a4834137d8d359b829e2d4b334f5ab5b5" }
|
||||
uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "41e94c0a4834137d8d359b829e2d4b334f5ab5b5" }
|
||||
vodozemac = { git = "https://github.com/matrix-org/vodozemac", rev = "fb609ca1e4df5a7a818490ae86ac694119e41e71" }
|
||||
|
||||
@@ -40,6 +40,7 @@ sanitize-filename-reader-friendly = "2.2.1"
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-core = { workspace = true }
|
||||
tracing-opentelemetry = { version = "0.18.0" }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
|
||||
|
||||
@@ -32,6 +32,7 @@ pub mod room_member;
|
||||
pub mod session_verification;
|
||||
pub mod sliding_sync;
|
||||
pub mod timeline;
|
||||
pub mod tracing;
|
||||
|
||||
use client::Client;
|
||||
use client_builder::ClientBuilder;
|
||||
@@ -128,6 +129,7 @@ mod uniffi_types {
|
||||
TimelineItemContent, TimelineItemContentKind, VideoInfo, VideoMessageContent,
|
||||
VirtualTimelineItem,
|
||||
},
|
||||
tracing::{LogLevel, Span},
|
||||
ClientError,
|
||||
};
|
||||
}
|
||||
|
||||
147
bindings/matrix-sdk-ffi/src/tracing.rs
Normal file
147
bindings/matrix-sdk-ffi/src/tracing.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
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,
|
||||
line: u32,
|
||||
column: u32,
|
||||
level: LogLevel,
|
||||
target: String,
|
||||
message: String,
|
||||
) {
|
||||
static METADATA: Mutex<BTreeMap<Location, StaticMetadata>> = Mutex::new(BTreeMap::new());
|
||||
let loc = Location::new(file, line, column);
|
||||
let metadata = get_or_init_metadata(&METADATA, loc, level, target, |loc| {
|
||||
(format!("event {}:{}", loc.file, loc.line), &["message"], MetadataKind::EVENT)
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
fn make_span(
|
||||
file: String,
|
||||
line: u32,
|
||||
column: u32,
|
||||
level: LogLevel,
|
||||
target: String,
|
||||
name: String,
|
||||
) -> Arc<Span> {
|
||||
static METADATA: Mutex<BTreeMap<Location, StaticMetadata>> = 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));
|
||||
|
||||
// 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)))
|
||||
}
|
||||
|
||||
type FieldNames = &'static [&'static str];
|
||||
|
||||
fn get_or_init_metadata(
|
||||
mutex: &Mutex<BTreeMap<Location, StaticMetadata>>,
|
||||
loc: Location,
|
||||
level: LogLevel,
|
||||
target: String,
|
||||
get_details: impl FnOnce(&Location) -> (String, FieldNames, MetadataKind),
|
||||
) -> StaticMetadata {
|
||||
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())));
|
||||
let metadata = Box::leak(Box::new(tracing::Metadata::new(
|
||||
Box::leak(name.into_boxed_str()),
|
||||
Box::leak(target.into_boxed_str()),
|
||||
level.to_tracing_level(),
|
||||
Some(Box::leak(Box::from(loc.file.as_str()))),
|
||||
Some(loc.line),
|
||||
None, // module path
|
||||
FieldSet::new(field_names, identify_callsite!(callsite)),
|
||||
span_kind,
|
||||
)));
|
||||
callsite.0.set(DefaultCallsite::new(metadata)).expect("callsite was not set before");
|
||||
metadata
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct Span(tracing::Span);
|
||||
|
||||
#[uniffi::export]
|
||||
impl Span {
|
||||
fn enter(&self) {
|
||||
self.0.with_subscriber(|(id, dispatch)| dispatch.enter(id));
|
||||
}
|
||||
|
||||
fn exit(&self) {
|
||||
self.0.with_subscriber(|(id, dispatch)| dispatch.exit(id));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(uniffi::Enum)]
|
||||
pub enum LogLevel {
|
||||
Error,
|
||||
Warn,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
||||
impl LogLevel {
|
||||
fn to_tracing_level(&self) -> tracing::Level {
|
||||
match self {
|
||||
LogLevel::Error => tracing::Level::ERROR,
|
||||
LogLevel::Warn => tracing::Level::WARN,
|
||||
LogLevel::Info => tracing::Level::INFO,
|
||||
LogLevel::Debug => tracing::Level::DEBUG,
|
||||
LogLevel::Trace => tracing::Level::TRACE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct Location {
|
||||
file: String,
|
||||
line: u32,
|
||||
column: u32,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
fn new(file: String, line: u32, column: u32) -> Self {
|
||||
Self { file, line, column }
|
||||
}
|
||||
}
|
||||
|
||||
struct LateInitCallsite(OnceCell<DefaultCallsite>);
|
||||
|
||||
impl Callsite for LateInitCallsite {
|
||||
fn set_interest(&self, interest: tracing_core::Interest) {
|
||||
self.0
|
||||
.get()
|
||||
.expect("Callsite impl must not be used before initialization")
|
||||
.set_interest(interest)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> &tracing::Metadata<'_> {
|
||||
self.0.get().expect("Callsite impl must not be used before initialization").metadata()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user