Skip to content

Commit b50bc5e

Browse files
Backport 9262 to release-25.0.0 (#9270)
* wit-bindgen: Don't trace values containing lists by default. (#9262) * wit-bindgen: Don't trace values containing lists by default. `list` values in Wit interfaces can represent things like HTTP bodies which can be very large. To enable tracing without spamming logfiles with all this data, put printing of values containing `list`s behind a separate `verbose_tracing` option. This is a coarse-grained approach; but it seems like a pretty good default for tracing, and enabling full tracing when one needs it is straightforward. In the future, we may want to refine the option by implementing the `Valuable` trait and using `tracing::field::valuable`, which could allow us to do things like print non-`list` fields of records that otherwise contain `list`s. * Use `option_type_contains_lists` more. * Hook up `verbose_tracing` to the macro. * Update expected outputs for tests. * Add release notes --------- Co-authored-by: Dan Gohman <[email protected]>
1 parent c3dd8ad commit b50bc5e

File tree

9 files changed

+186
-76
lines changed

9 files changed

+186
-76
lines changed

RELEASES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ Unreleased.
2929

3030
### Changed
3131

32+
* The host bindgen macro now accepts a new `verbose_tracing` option, which will
33+
trace the value of `list` arguments. The new behavior of the `tracing` option
34+
is that it does not print `list` values without `verbose_tracing` also being
35+
present.
36+
[#9262](https://github.com/bytecodealliance/wasmtime/pull/9262)
37+
3238
* Wasmtime's support for WASI is now listed with the 0.2.1 version instead of
3339
0.2.0. This is expected to not cause fallout or breakage, but please open an
3440
issue if you see any problems.

crates/component-macro/src/bindgen.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ impl Parse for Config {
110110
inline = Some(s.value());
111111
}
112112
Opt::Tracing(val) => opts.tracing = val,
113+
Opt::VerboseTracing(val) => opts.verbose_tracing = val,
113114
Opt::Async(val, span) => {
114115
if async_configured {
115116
return Err(Error::new(span, "cannot specify second async config"));
@@ -232,6 +233,7 @@ mod kw {
232233
syn::custom_keyword!(inline);
233234
syn::custom_keyword!(path);
234235
syn::custom_keyword!(tracing);
236+
syn::custom_keyword!(verbose_tracing);
235237
syn::custom_keyword!(trappable_error_type);
236238
syn::custom_keyword!(world);
237239
syn::custom_keyword!(ownership);
@@ -254,6 +256,7 @@ enum Opt {
254256
Path(syn::LitStr),
255257
Inline(syn::LitStr),
256258
Tracing(bool),
259+
VerboseTracing(bool),
257260
Async(AsyncConfig, Span),
258261
TrappableErrorType(Vec<TrappableError>),
259262
Ownership(Ownership),
@@ -288,6 +291,10 @@ impl Parse for Opt {
288291
input.parse::<kw::tracing>()?;
289292
input.parse::<Token![:]>()?;
290293
Ok(Opt::Tracing(input.parse::<syn::LitBool>()?.value))
294+
} else if l.peek(kw::verbose_tracing) {
295+
input.parse::<kw::verbose_tracing>()?;
296+
input.parse::<Token![:]>()?;
297+
Ok(Opt::VerboseTracing(input.parse::<syn::LitBool>()?.value))
291298
} else if l.peek(Token![async]) {
292299
let span = input.parse::<Token![async]>()?.span;
293300
input.parse::<Token![:]>()?;

crates/component-macro/tests/codegen.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ macro_rules! gentest {
1616
wasmtime::component::bindgen!({
1717
path: $path,
1818
tracing: true,
19+
verbose_tracing: true,
1920
ownership: Borrowing {
2021
duplicate_if_necessary: true
2122
}

crates/component-macro/tests/expanded/lists_tracing_async.rs

Lines changed: 54 additions & 54 deletions
Large diffs are not rendered by default.

crates/component-macro/tests/expanded/resources-import_tracing_async.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,7 @@ pub mod foo {
10451045
wasmtime::component::__internal::Box::new(
10461046
async move {
10471047
tracing::event!(
1048-
tracing::Level::TRACE, x = tracing::field::debug(& arg0),
1048+
tracing::Level::TRACE, x = tracing::field::debug("..."),
10491049
"call"
10501050
);
10511051
let host = &mut host_getter(caller.data_mut());
@@ -1080,7 +1080,7 @@ pub mod foo {
10801080
wasmtime::component::__internal::Box::new(
10811081
async move {
10821082
tracing::event!(
1083-
tracing::Level::TRACE, x = tracing::field::debug(& arg0),
1083+
tracing::Level::TRACE, x = tracing::field::debug("..."),
10841084
"call"
10851085
);
10861086
let host = &mut host_getter(caller.data_mut());
@@ -1109,8 +1109,8 @@ pub mod foo {
11091109
let host = &mut host_getter(caller.data_mut());
11101110
let r = Host::list_result(host).await;
11111111
tracing::event!(
1112-
tracing::Level::TRACE, result = tracing::field::debug(& r),
1113-
"return"
1112+
tracing::Level::TRACE, result =
1113+
tracing::field::debug("..."), "return"
11141114
);
11151115
Ok((r,))
11161116
}

crates/component-macro/tests/expanded/simple-lists_tracing_async.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ pub mod foo {
255255
wasmtime::component::__internal::Box::new(
256256
async move {
257257
tracing::event!(
258-
tracing::Level::TRACE, l = tracing::field::debug(& arg0),
258+
tracing::Level::TRACE, l = tracing::field::debug("..."),
259259
"call"
260260
);
261261
let host = &mut host_getter(caller.data_mut());
@@ -284,8 +284,8 @@ pub mod foo {
284284
let host = &mut host_getter(caller.data_mut());
285285
let r = Host::simple_list2(host).await;
286286
tracing::event!(
287-
tracing::Level::TRACE, result = tracing::field::debug(& r),
288-
"return"
287+
tracing::Level::TRACE, result =
288+
tracing::field::debug("..."), "return"
289289
);
290290
Ok((r,))
291291
}
@@ -313,14 +313,14 @@ pub mod foo {
313313
wasmtime::component::__internal::Box::new(
314314
async move {
315315
tracing::event!(
316-
tracing::Level::TRACE, a = tracing::field::debug(& arg0), b
317-
= tracing::field::debug(& arg1), "call"
316+
tracing::Level::TRACE, a = tracing::field::debug("..."), b =
317+
tracing::field::debug("..."), "call"
318318
);
319319
let host = &mut host_getter(caller.data_mut());
320320
let r = Host::simple_list3(host, arg0, arg1).await;
321321
tracing::event!(
322-
tracing::Level::TRACE, result = tracing::field::debug(& r),
323-
"return"
322+
tracing::Level::TRACE, result =
323+
tracing::field::debug("..."), "return"
324324
);
325325
Ok((r,))
326326
}
@@ -348,14 +348,14 @@ pub mod foo {
348348
wasmtime::component::__internal::Box::new(
349349
async move {
350350
tracing::event!(
351-
tracing::Level::TRACE, l = tracing::field::debug(& arg0),
351+
tracing::Level::TRACE, l = tracing::field::debug("..."),
352352
"call"
353353
);
354354
let host = &mut host_getter(caller.data_mut());
355355
let r = Host::simple_list4(host, arg0).await;
356356
tracing::event!(
357-
tracing::Level::TRACE, result = tracing::field::debug(& r),
358-
"return"
357+
tracing::Level::TRACE, result =
358+
tracing::field::debug("..."), "return"
359359
);
360360
Ok((r,))
361361
}

crates/component-macro/tests/expanded/variants_tracing_async.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -868,8 +868,8 @@ pub mod foo {
868868
tracing::Level::TRACE, a = tracing::field::debug(& arg0), b
869869
= tracing::field::debug(& arg1), c = tracing::field::debug(&
870870
arg2), d = tracing::field::debug(& arg3), e =
871-
tracing::field::debug(& arg4), f = tracing::field::debug(&
872-
arg5), "call"
871+
tracing::field::debug(& arg4), f =
872+
tracing::field::debug("..."), "call"
873873
);
874874
let host = &mut host_getter(caller.data_mut());
875875
let r = Host::result_arg(
@@ -906,8 +906,8 @@ pub mod foo {
906906
let host = &mut host_getter(caller.data_mut());
907907
let r = Host::result_result(host).await;
908908
tracing::event!(
909-
tracing::Level::TRACE, result = tracing::field::debug(& r),
910-
"return"
909+
tracing::Level::TRACE, result =
910+
tracing::field::debug("..."), "return"
911911
);
912912
Ok((r,))
913913
}

crates/wasmtime/src/runtime/component/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,19 @@ pub(crate) use self::store::ComponentStoreData;
241241
/// ",
242242
///
243243
/// // Add calls to `tracing::span!` before each import or export is called
244-
/// // to log arguments and return values.
244+
/// // to log most arguments and return values. By default values
245+
/// // containing lists are excluded; enable `verbose_tracing` to include
246+
/// // them.
245247
/// //
246248
/// // This option defaults to `false`.
247249
/// tracing: true,
248250
///
251+
/// // Include all arguments and return values in the tracing output,
252+
/// // including values containing lists, which may be very large.
253+
/// //
254+
/// // This option defaults to `false`.
255+
/// verbose_tracing: false,
256+
///
249257
/// // Imports will be async functions through #[async_trait] and exports
250258
/// // are also invoked as async functions. Requires `Config::async_support`
251259
/// // to be `true`.

crates/wit-bindgen/src/lib.rs

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ pub struct Opts {
125125
/// Whether or not to emit `tracing` macro calls on function entry/exit.
126126
pub tracing: bool,
127127

128+
/// Whether or not `tracing` macro calls should included argument and
129+
/// return values which contain dynamically-sized `list` values.
130+
pub verbose_tracing: bool,
131+
128132
/// Whether or not to use async rust functions and traits.
129133
pub async_: AsyncConfig,
130134

@@ -2582,9 +2586,9 @@ impl<'a> InterfaceGenerator<'a> {
25822586
.params
25832587
.iter()
25842588
.enumerate()
2585-
.map(|(i, (name, _ty))| {
2589+
.map(|(i, (name, ty))| {
25862590
let name = to_rust_ident(&name);
2587-
format!("{name} = tracing::field::debug(&arg{i})")
2591+
formatting_for_arg(&name, i, *ty, &self.gen.opts, &self.resolve)
25882592
})
25892593
.collect::<Vec<String>>();
25902594
event_fields.push(format!("\"call\""));
@@ -2629,7 +2633,8 @@ impl<'a> InterfaceGenerator<'a> {
26292633
if self.gen.opts.tracing {
26302634
uwrite!(
26312635
self.src,
2632-
"tracing::event!(tracing::Level::TRACE, result = tracing::field::debug(&r), \"return\");"
2636+
"tracing::event!(tracing::Level::TRACE, {}, \"return\");",
2637+
formatting_for_results(&func.results, &self.gen.opts, &self.resolve)
26332638
);
26342639
}
26352640

@@ -2955,6 +2960,89 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
29552960
}
29562961
}
29572962

2963+
/// Produce a string for tracing a function argument.
2964+
fn formatting_for_arg(
2965+
name: &str,
2966+
index: usize,
2967+
ty: Type,
2968+
opts: &Opts,
2969+
resolve: &Resolve,
2970+
) -> String {
2971+
if !opts.verbose_tracing && type_contains_lists(ty, resolve) {
2972+
return format!("{name} = tracing::field::debug(\"...\")");
2973+
}
2974+
2975+
// Normal tracing.
2976+
format!("{name} = tracing::field::debug(&arg{index})")
2977+
}
2978+
2979+
/// Produce a string for tracing function results.
2980+
fn formatting_for_results(results: &Results, opts: &Opts, resolve: &Resolve) -> String {
2981+
let contains_lists = match results {
2982+
Results::Anon(ty) => type_contains_lists(*ty, resolve),
2983+
Results::Named(params) => params
2984+
.iter()
2985+
.any(|(_, ty)| type_contains_lists(*ty, resolve)),
2986+
};
2987+
2988+
if !opts.verbose_tracing && contains_lists {
2989+
return format!("result = tracing::field::debug(\"...\")");
2990+
}
2991+
2992+
// Normal tracing.
2993+
format!("result = tracing::field::debug(&r)")
2994+
}
2995+
2996+
/// Test whether the given type contains lists.
2997+
///
2998+
/// Here, a `string` is not considered a list.
2999+
fn type_contains_lists(ty: Type, resolve: &Resolve) -> bool {
3000+
match ty {
3001+
Type::Id(id) => match &resolve.types[id].kind {
3002+
TypeDefKind::Resource
3003+
| TypeDefKind::Unknown
3004+
| TypeDefKind::Flags(_)
3005+
| TypeDefKind::Handle(_)
3006+
| TypeDefKind::Enum(_) => false,
3007+
TypeDefKind::Option(ty) => type_contains_lists(*ty, resolve),
3008+
TypeDefKind::Result(Result_ { ok, err }) => {
3009+
option_type_contains_lists(*ok, resolve)
3010+
|| option_type_contains_lists(*err, resolve)
3011+
}
3012+
TypeDefKind::Record(record) => record
3013+
.fields
3014+
.iter()
3015+
.any(|field| type_contains_lists(field.ty, resolve)),
3016+
TypeDefKind::Tuple(tuple) => tuple
3017+
.types
3018+
.iter()
3019+
.any(|ty| type_contains_lists(*ty, resolve)),
3020+
TypeDefKind::Variant(variant) => variant
3021+
.cases
3022+
.iter()
3023+
.any(|case| option_type_contains_lists(case.ty, resolve)),
3024+
TypeDefKind::Type(ty) => type_contains_lists(*ty, resolve),
3025+
TypeDefKind::Future(ty) => option_type_contains_lists(*ty, resolve),
3026+
TypeDefKind::Stream(Stream { element, end }) => {
3027+
option_type_contains_lists(*element, resolve)
3028+
|| option_type_contains_lists(*end, resolve)
3029+
}
3030+
TypeDefKind::List(_) => true,
3031+
},
3032+
3033+
// Technically strings are lists too, but we ignore that here because
3034+
// they're usually short.
3035+
_ => false,
3036+
}
3037+
}
3038+
3039+
fn option_type_contains_lists(ty: Option<Type>, resolve: &Resolve) -> bool {
3040+
match ty {
3041+
Some(ty) => type_contains_lists(ty, resolve),
3042+
None => false,
3043+
}
3044+
}
3045+
29583046
/// When an interface `use`s a type from another interface, it creates a new TypeId
29593047
/// referring to the definition TypeId. Chase this chain of references down to
29603048
/// a TypeId for type's definition.

0 commit comments

Comments
 (0)