Skip to content

Commit

Permalink
attributes: add #[instrument(parent = ...)] for specifying parent span.
Browse files Browse the repository at this point in the history
## Motivation

Resolves part of tokio-rs#879.
  • Loading branch information
pandaman64 committed Feb 16, 2021
1 parent f81426b commit 37873f5
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
32 changes: 32 additions & 0 deletions tracing-attributes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ fn gen_body(

let level = args.level();
let target = args.target();
let parent = args.parent();

// filter out skipped fields
let mut quoted_fields: Vec<_> = param_names
Expand Down Expand Up @@ -427,6 +428,7 @@ fn gen_body(

quote!(tracing::span!(
target: #target,
parent: #parent,
#level,
#span_name,
#(#quoted_fields,)*
Expand Down Expand Up @@ -506,6 +508,7 @@ struct InstrumentArgs {
skips: HashSet<Ident>,
fields: Option<Fields>,
err: bool,
parent: Option<Parent>,
/// Errors describing any unrecognized parse inputs that we skipped.
parse_warnings: Vec<syn::Error>,
}
Expand Down Expand Up @@ -559,6 +562,15 @@ impl InstrumentArgs {
}
}

fn parent(&self) -> impl ToTokens {
if let Some(ref parent) = self.parent {
let value = &parent.value;
quote!(#value)
} else {
quote!(&tracing::Span::current())
}
}

/// Generate "deprecation" warnings for any unrecognized attribute inputs
/// that we skipped.
///
Expand Down Expand Up @@ -632,6 +644,11 @@ impl Parse for InstrumentArgs {
} else if lookahead.peek(kw::err) {
let _ = input.parse::<kw::err>()?;
args.err = true;
} else if lookahead.peek(kw::parent) {
if args.parent.is_some() {
return Err(input.error("expected only a single `parent` argument"));
}
args.parent = Some(input.parse()?);
} else if lookahead.peek(Token![,]) {
let _ = input.parse::<Token![,]>()?;
} else {
Expand Down Expand Up @@ -807,6 +824,20 @@ impl Parse for Level {
}
}

#[derive(Debug)]
struct Parent {
value: Expr,
}

impl Parse for Parent {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let _ = input.parse::<kw::parent>()?;
let _ = input.parse::<Token![=]>()?;
let value = input.parse::<Expr>()?;
Ok(Self { value })
}
}

fn param_names(pat: Pat) -> Box<dyn Iterator<Item = Ident>> {
match pat {
Pat::Ident(PatIdent { ident, .. }) => Box::new(iter::once(ident)),
Expand Down Expand Up @@ -837,6 +868,7 @@ mod kw {
syn::custom_keyword!(target);
syn::custom_keyword!(name);
syn::custom_keyword!(err);
syn::custom_keyword!(parent);
}

// Get the AST of the inner function we need to hook, if it was generated
Expand Down
23 changes: 23 additions & 0 deletions tracing-attributes/tests/parent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use tracing::Span;
use tracing_attributes::instrument;

#[derive(Debug)]
struct WithSpan {
span: Span,
}

impl WithSpan {
fn new(span: Span) -> Self {
Self { span }
}

#[instrument(parent = &self.span)]
fn foo(&self) {}
}

#[test]
fn test() {
let span = Span::current();
let with_span = WithSpan::new(span);
with_span.foo();
}

0 comments on commit 37873f5

Please sign in to comment.