offer function-level control over tracing (#5194)
* wiggle: fix compilation with async functions when tracing is off Fixes #5202 * switch tracing config from a boolean to a struct This will enable more complex tracing rules in the future * rename AsyncConfField to FunctionField It is going to be reused for cases other than just async functions * add support for disabling tracing per-function This adds a `disable_for` syntax after the `tracing` boolean. For example: ``` wiggle::from_witx!( tracing: true disable_for { module1::foo, module2::{bar, baz}, } ) ```
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use crate::config::{AsyncConf, ErrorConf};
|
use crate::config::{AsyncConf, ErrorConf, TracingConf};
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error};
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
@@ -15,7 +15,7 @@ pub struct CodegenSettings {
|
|||||||
// Disabling this feature makes it possible to remove all of the tracing
|
// Disabling this feature makes it possible to remove all of the tracing
|
||||||
// code emitted in the Wiggle-generated code; this can be helpful while
|
// code emitted in the Wiggle-generated code; this can be helpful while
|
||||||
// inspecting the code (e.g., with `cargo expand`).
|
// inspecting the code (e.g., with `cargo expand`).
|
||||||
pub tracing: bool,
|
pub tracing: TracingConf,
|
||||||
}
|
}
|
||||||
impl CodegenSettings {
|
impl CodegenSettings {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -23,14 +23,14 @@ impl CodegenSettings {
|
|||||||
async_: &AsyncConf,
|
async_: &AsyncConf,
|
||||||
doc: &Document,
|
doc: &Document,
|
||||||
wasmtime: bool,
|
wasmtime: bool,
|
||||||
tracing: bool,
|
tracing: &TracingConf,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let errors = ErrorTransform::new(error_conf, doc)?;
|
let errors = ErrorTransform::new(error_conf, doc)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
errors,
|
errors,
|
||||||
async_: async_.clone(),
|
async_: async_.clone(),
|
||||||
wasmtime,
|
wasmtime,
|
||||||
tracing,
|
tracing: tracing.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn get_async(&self, module: &Module, func: &InterfaceFunc) -> Asyncness {
|
pub fn get_async(&self, module: &Module, func: &InterfaceFunc) -> Asyncness {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ pub struct Config {
|
|||||||
pub errors: ErrorConf,
|
pub errors: ErrorConf,
|
||||||
pub async_: AsyncConf,
|
pub async_: AsyncConf,
|
||||||
pub wasmtime: bool,
|
pub wasmtime: bool,
|
||||||
pub tracing: bool,
|
pub tracing: TracingConf,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod kw {
|
mod kw {
|
||||||
@@ -26,6 +26,7 @@ mod kw {
|
|||||||
syn::custom_keyword!(target);
|
syn::custom_keyword!(target);
|
||||||
syn::custom_keyword!(wasmtime);
|
syn::custom_keyword!(wasmtime);
|
||||||
syn::custom_keyword!(tracing);
|
syn::custom_keyword!(tracing);
|
||||||
|
syn::custom_keyword!(disable_for);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -34,7 +35,7 @@ pub enum ConfigField {
|
|||||||
Error(ErrorConf),
|
Error(ErrorConf),
|
||||||
Async(AsyncConf),
|
Async(AsyncConf),
|
||||||
Wasmtime(bool),
|
Wasmtime(bool),
|
||||||
Tracing(bool),
|
Tracing(TracingConf),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ConfigField {
|
impl Parse for ConfigField {
|
||||||
@@ -73,7 +74,7 @@ impl Parse for ConfigField {
|
|||||||
} else if lookahead.peek(kw::tracing) {
|
} else if lookahead.peek(kw::tracing) {
|
||||||
input.parse::<kw::tracing>()?;
|
input.parse::<kw::tracing>()?;
|
||||||
input.parse::<Token![:]>()?;
|
input.parse::<Token![:]>()?;
|
||||||
Ok(ConfigField::Tracing(input.parse::<syn::LitBool>()?.value))
|
Ok(ConfigField::Tracing(input.parse()?))
|
||||||
} else {
|
} else {
|
||||||
Err(lookahead.error())
|
Err(lookahead.error())
|
||||||
}
|
}
|
||||||
@@ -128,7 +129,7 @@ impl Config {
|
|||||||
errors: errors.take().unwrap_or_default(),
|
errors: errors.take().unwrap_or_default(),
|
||||||
async_: async_.take().unwrap_or_default(),
|
async_: async_.take().unwrap_or_default(),
|
||||||
wasmtime: wasmtime.unwrap_or(true),
|
wasmtime: wasmtime.unwrap_or(true),
|
||||||
tracing: tracing.unwrap_or(true),
|
tracing: tracing.unwrap_or_default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +410,7 @@ impl Parse for AsyncFunctions {
|
|||||||
let lookahead = input.lookahead1();
|
let lookahead = input.lookahead1();
|
||||||
if lookahead.peek(syn::token::Brace) {
|
if lookahead.peek(syn::token::Brace) {
|
||||||
let _ = braced!(content in input);
|
let _ = braced!(content in input);
|
||||||
let items: Punctuated<AsyncConfField, Token![,]> =
|
let items: Punctuated<FunctionField, Token![,]> =
|
||||||
content.parse_terminated(Parse::parse)?;
|
content.parse_terminated(Parse::parse)?;
|
||||||
let mut functions: HashMap<String, Vec<String>> = HashMap::new();
|
let mut functions: HashMap<String, Vec<String>> = HashMap::new();
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
@@ -437,13 +438,13 @@ impl Parse for AsyncFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AsyncConfField {
|
pub struct FunctionField {
|
||||||
pub module_name: Ident,
|
pub module_name: Ident,
|
||||||
pub function_names: Vec<Ident>,
|
pub function_names: Vec<Ident>,
|
||||||
pub err_loc: Span,
|
pub err_loc: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for AsyncConfField {
|
impl Parse for FunctionField {
|
||||||
fn parse(input: ParseStream) -> Result<Self> {
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
let err_loc = input.span();
|
let err_loc = input.span();
|
||||||
let module_name = input.parse::<Ident>()?;
|
let module_name = input.parse::<Ident>()?;
|
||||||
@@ -454,14 +455,14 @@ impl Parse for AsyncConfField {
|
|||||||
let _ = braced!(content in input);
|
let _ = braced!(content in input);
|
||||||
let function_names: Punctuated<Ident, Token![,]> =
|
let function_names: Punctuated<Ident, Token![,]> =
|
||||||
content.parse_terminated(Parse::parse)?;
|
content.parse_terminated(Parse::parse)?;
|
||||||
Ok(AsyncConfField {
|
Ok(FunctionField {
|
||||||
module_name,
|
module_name,
|
||||||
function_names: function_names.iter().cloned().collect(),
|
function_names: function_names.iter().cloned().collect(),
|
||||||
err_loc,
|
err_loc,
|
||||||
})
|
})
|
||||||
} else if lookahead.peek(Ident) {
|
} else if lookahead.peek(Ident) {
|
||||||
let name = input.parse()?;
|
let name = input.parse()?;
|
||||||
Ok(AsyncConfField {
|
Ok(FunctionField {
|
||||||
module_name,
|
module_name,
|
||||||
function_names: vec![name],
|
function_names: vec![name],
|
||||||
err_loc,
|
err_loc,
|
||||||
@@ -565,3 +566,70 @@ impl Parse for WasmtimeConfigField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct TracingConf {
|
||||||
|
enabled: bool,
|
||||||
|
excluded_functions: HashMap<String, Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TracingConf {
|
||||||
|
pub fn enabled_for(&self, module: &str, function: &str) -> bool {
|
||||||
|
if !self.enabled {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.excluded_functions
|
||||||
|
.get(module)
|
||||||
|
.and_then(|fs| fs.iter().find(|f| *f == function))
|
||||||
|
.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TracingConf {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: true,
|
||||||
|
excluded_functions: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for TracingConf {
|
||||||
|
fn parse(input: ParseStream) -> Result<Self> {
|
||||||
|
let enabled = input.parse::<syn::LitBool>()?.value;
|
||||||
|
|
||||||
|
let lookahead = input.lookahead1();
|
||||||
|
if lookahead.peek(kw::disable_for) {
|
||||||
|
input.parse::<kw::disable_for>()?;
|
||||||
|
let content;
|
||||||
|
let _ = braced!(content in input);
|
||||||
|
let items: Punctuated<FunctionField, Token![,]> =
|
||||||
|
content.parse_terminated(Parse::parse)?;
|
||||||
|
let mut functions: HashMap<String, Vec<String>> = HashMap::new();
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
|
for i in items {
|
||||||
|
let function_names = i
|
||||||
|
.function_names
|
||||||
|
.iter()
|
||||||
|
.map(|i| i.to_string())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
match functions.entry(i.module_name.to_string()) {
|
||||||
|
Entry::Occupied(o) => o.into_mut().extend(function_names),
|
||||||
|
Entry::Vacant(v) => {
|
||||||
|
v.insert(function_names);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(TracingConf {
|
||||||
|
enabled,
|
||||||
|
excluded_functions: functions,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(TracingConf {
|
||||||
|
enabled,
|
||||||
|
excluded_functions: HashMap::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ fn _define_func(
|
|||||||
);
|
);
|
||||||
);
|
);
|
||||||
if settings.get_async(&module, &func).is_sync() {
|
if settings.get_async(&module, &func).is_sync() {
|
||||||
let traced_body = if settings.tracing {
|
let traced_body = if settings.tracing.enabled_for(&mod_name, &func_name) {
|
||||||
quote!(
|
quote!(
|
||||||
#mk_span
|
#mk_span
|
||||||
_span.in_scope(|| {
|
_span.in_scope(|| {
|
||||||
@@ -109,7 +109,7 @@ fn _define_func(
|
|||||||
bounds,
|
bounds,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let traced_body = if settings.tracing {
|
let traced_body = if settings.tracing.enabled_for(&mod_name, &func_name) {
|
||||||
quote!(
|
quote!(
|
||||||
use #rt::tracing::Instrument as _;
|
use #rt::tracing::Instrument as _;
|
||||||
#mk_span
|
#mk_span
|
||||||
@@ -261,7 +261,12 @@ impl witx::Bindgen for Rust<'_> {
|
|||||||
args.push(quote!(#name));
|
args.push(quote!(#name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.settings.tracing && func.params.len() > 0 {
|
if self
|
||||||
|
.settings
|
||||||
|
.tracing
|
||||||
|
.enabled_for(self.module.name.as_str(), self.funcname)
|
||||||
|
&& func.params.len() > 0
|
||||||
|
{
|
||||||
let args = func
|
let args = func
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
@@ -290,7 +295,11 @@ impl witx::Bindgen for Rust<'_> {
|
|||||||
let ret = #trait_name::#ident(ctx, #(#args),*).await;
|
let ret = #trait_name::#ident(ctx, #(#args),*).await;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
if self.settings.tracing {
|
if self
|
||||||
|
.settings
|
||||||
|
.tracing
|
||||||
|
.enabled_for(self.module.name.as_str(), self.funcname)
|
||||||
|
{
|
||||||
self.src.extend(quote! {
|
self.src.extend(quote! {
|
||||||
#rt::tracing::event!(
|
#rt::tracing::event!(
|
||||||
#rt::tracing::Level::TRACE,
|
#rt::tracing::Level::TRACE,
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ pub fn from_witx(args: TokenStream) -> TokenStream {
|
|||||||
&config.async_,
|
&config.async_,
|
||||||
&doc,
|
&doc,
|
||||||
config.wasmtime,
|
config.wasmtime,
|
||||||
config.tracing,
|
&config.tracing,
|
||||||
)
|
)
|
||||||
.expect("validating codegen settings");
|
.expect("validating codegen settings");
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ pub fn wasmtime_integration(args: TokenStream) -> TokenStream {
|
|||||||
&config.c.async_,
|
&config.c.async_,
|
||||||
&doc,
|
&doc,
|
||||||
true,
|
true,
|
||||||
config.c.tracing,
|
&config.c.tracing,
|
||||||
)
|
)
|
||||||
.expect("validating codegen settings");
|
.expect("validating codegen settings");
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ pub enum RichError {
|
|||||||
// Define an errno with variants corresponding to RichError. Use it in a
|
// Define an errno with variants corresponding to RichError. Use it in a
|
||||||
// trivial function.
|
// trivial function.
|
||||||
wiggle::from_witx!({
|
wiggle::from_witx!({
|
||||||
|
tracing: true disable_for {
|
||||||
|
one_error_conversion::foo,
|
||||||
|
},
|
||||||
witx_literal: "
|
witx_literal: "
|
||||||
(typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line))
|
(typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line))
|
||||||
(typename $s (record (field $f1 (@witx usize)) (field $f2 (@witx pointer u8))))
|
(typename $s (record (field $f1 (@witx usize)) (field $f2 (@witx pointer u8))))
|
||||||
|
|||||||
Reference in New Issue
Block a user