mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-10-02 15:24:47 +00:00

## Motivation Fields on spans generated by `#[instrument]` consist of the parameters to the `instrument`ed function, and a list of optional fields with literal values passed in the `fields` argument of the attribute. The current API for additional user-defined fields is pretty limited, since it only accepts literals (and doesn't accept dotted field names). It would be nice to have an API for including additional fields with values set by calling methods on `self` or on parameters, or by accessing values from parameters. ## Solution This branch extends the currently supported `fields` argument to allow providing arbitrary expressions which are invoked within the function's scope. This is a superset of the previous support for literal values only. In addition, field names passed to `fields` may now contain dotted Rust identifiers. Implementing this required rewriting how arguments to the `#[instrument]` attribute are parsed. Previously, we used `syn`'s `AttributeArgs` type, which parses a comma-separated of "nested meta" items, consisting of `$ident($nested meta)`, `$ident = $nested_meta`, paths, and literals. By replacing the use of `AttributeArgs` with our own types implementing `syn::parse::Parse`, we can accept more expressions in the attribute arguments position. This also lets us reject more invalid inputs at parse-time, which improves syntax error reporting a bit. One thing that's worth noting is that the current implementation will generate an _empty_ field when a field name is provided without an `=` and a value. This makes sense when only simple fields with literal values are permitted. However, if we accept arbitrary expressions in the macro, this is not the ideal behavior --- we would prefer to use the same local variable shorthand as the function-like `tracing` macros. However, changing this now is a breaking change. Any code which uses a name that doesn't exist in the current scope to declare an empty field would fail to compile, because it attempts to reference a name that doesn't exist. Instead, I left a comment noting that this is not the ideal behavior and it should be changed next time we're ready to break the proc macros. Fixes: #650 Signed-off-by: Eliza Weisman <eliza@buoyant.io> Signed-off-by: Eliza Weisman <eliza@buoyant.io>