Skip to content

Commit

Permalink
tracing: Add support for span fields
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Aug 11, 2020
1 parent 31ba572 commit d1e0087
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 5 deletions.
31 changes: 28 additions & 3 deletions src/rust/include/tracing.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,10 @@ typedef struct TracingSpanGuard TracingSpanGuard;
/// Creates a span for a callsite.
///
/// The span must be freed when it goes out of scope.
TracingSpanHandle* tracing_span_create(const TracingCallsite* callsite);
TracingSpanHandle* tracing_span_create(
const TracingCallsite* callsite,
const char* const* field_values,
size_t fields_len);

/// Clones the given span.
///
Expand Down Expand Up @@ -216,7 +219,7 @@ class Span
Span() : inner(nullptr, tracing_span_free) {}

/// Use the `TracingSpan` macro instead of calling this constructor directly.
Span(const TracingCallsite* callsite) : inner(tracing_span_create(callsite), tracing_span_free) {}
Span(const TracingCallsite* callsite, const char* const* field_values, size_t fields_len) : inner(tracing_span_create(callsite, field_values, fields_len), tracing_span_free) {}

Span(Span& span) : inner(std::move(span.inner)) {}
Span(const Span& span) : inner(tracing_span_clone(span.inner.get()), tracing_span_free) {}
Expand Down Expand Up @@ -257,9 +260,31 @@ class Span
/// strings.
#define TracingSpan(level, target, name) ([&] { \
static constexpr const char* const FIELDS[] = {}; \
const char* T_VALUES[] = {}; \
static TracingCallsite* CALLSITE = \
T_CALLSITE(name, target, level, FIELDS, true); \
return tracing::Span(CALLSITE); \
return tracing::Span( \
CALLSITE, T_VALUES, T_ARRLEN(T_VALUES)); \
}())

/// Expands to a `tracing::Span` object which is used to record a span.
/// The `Span::Enter` method on that object records that the span has been
/// entered, and returns a RAII guard object, which will exit the span when
/// dropped.
///
/// Arguments: (level, target, name, key, value[, key2, value2, ...])
///
/// level, target, name, and all keys MUST be static constants, and MUST be
/// valid UTF-8 strings.
#define TracingSpanFields(level, target, name, ...) ([&] { \
static constexpr const char* const FIELDS[] = \
{T_FIELD_NAMES(__VA_ARGS__)}; \
const char* T_VALUES[] = \
{T_FIELD_VALUES(__VA_ARGS__)}; \
static TracingCallsite* CALLSITE = \
T_CALLSITE(name, target, level, FIELDS, true); \
return tracing::Span( \
CALLSITE, T_VALUES, T_ARRLEN(T_VALUES)); \
}())
#endif

Expand Down
69 changes: 67 additions & 2 deletions src/rust/src/tracing_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ pub extern "C" fn tracing_callsite(
}

macro_rules! repeat {
(0, $val:expr) => {
[]
};
(1, $val:expr) => {
[$val]
};
Expand Down Expand Up @@ -435,14 +438,76 @@ macro_rules! repeat {
}

#[no_mangle]
pub extern "C" fn tracing_span_create(callsite: *const FfiCallsite) -> *mut Span {
pub extern "C" fn tracing_span_create(
callsite: *const FfiCallsite,
field_values: *const *const c_char,
fields_len: usize,
) -> *mut Span {
let callsite = unsafe { &*callsite };
let field_values = unsafe { slice::from_raw_parts(field_values, fields_len) };

let meta = callsite.metadata();
assert!(meta.is_span());

let span = if level_enabled!(*meta.level()) && callsite.is_enabled() {
Span::new(meta, &meta.fields().value_set(&[]))
let mut fi = meta.fields().iter();
let mut vi = field_values
.iter()
.map(|&p| unsafe { CStr::from_ptr(p) })
.map(|cs| cs.to_string_lossy());

macro_rules! new_span {
($n:tt) => {
Span::new(
meta,
&meta.fields().value_set(&repeat!(
$n,
(
&fi.next().unwrap(),
Some(&vi.next().unwrap().as_ref() as &dyn Value)
)
)),
)
};
}

// https://github.com/tokio-rs/tracing/issues/782 might help improve things here.
match field_values.len() {
0 => new_span!(0),
1 => new_span!(1),
2 => new_span!(2),
3 => new_span!(3),
4 => new_span!(4),
5 => new_span!(5),
6 => new_span!(6),
7 => new_span!(7),
8 => new_span!(8),
9 => new_span!(9),
10 => new_span!(10),
11 => new_span!(11),
12 => new_span!(12),
13 => new_span!(13),
14 => new_span!(14),
15 => new_span!(15),
16 => new_span!(16),
17 => new_span!(17),
18 => new_span!(18),
19 => new_span!(19),
20 => new_span!(20),
21 => new_span!(21),
22 => new_span!(22),
23 => new_span!(23),
24 => new_span!(24),
25 => new_span!(25),
26 => new_span!(26),
27 => new_span!(27),
28 => new_span!(28),
29 => new_span!(29),
30 => new_span!(30),
31 => new_span!(31),
32 => new_span!(32),
_ => unimplemented!(),
}
} else {
Span::none()
};
Expand Down

0 comments on commit d1e0087

Please sign in to comment.