Skip to content

Custom instrumentation macroΒ #1552

@drahnr

Description

@drahnr

Issue Scope

Currently we do use #[tracing::instrument(..)] but we always use the same 4 common patterns:

#[instrument(parent = None, target: COMPONENT, name = "foo.bar.baz", skip_all, err)]
#[instrument(target: COMPONENT, name = "foo.bar.baz", skip_all, err)]
#[instrument(parent = None, target: COMPONENT, name = "foo.bar.baz", skip_all, ret(level = "debug"), err)]
#[instrument(parent = None, target: COMPONENT, name = "foo.bar.baz", skip_all, fields(path=%some_path_ident.display())), err]

Let's go through the meaning of each of the used attributes one by one:

  1. name - a human readable name you'll find in honeycomb
  2. level=debug - only the given level will this span appear in the output
  3. err - add a log message if this path is taken, as if it was done with error!. Can be modified with err(debug)
  4. skip_all - skip all parameters to be recorded, bad for debugging, good for speed and avoiding accidental secrets being leaked in logs
  5. ret(level = "debug") - log the return value at this level or above
  6. parent - defines the parent span, or None for a new root level span

This is the maximum scope we use. There is little correlation (consistency?) in when we do which (bar parent usage).

Proposal

Simplify the API

#[instrument("foo.bar.baz", ret(level="debug"))]
// desugars to
// #[tracing::instrument(name="foo.bar.baz", target=COMPONENT, err(level="warn"), skip_all]
fn bar() -> u32  {..}
#[instrument(root, "foo.bar.foo", %a=a.display(),b=b.printer())]
// desugars to 
// #[tracing::instrument(parent = None, target=COMPONENT, name="foo.bar.foo", err(level="warn"), skip_all, fields(%a=a.display(),b=b.printer()))), err]
fn foo() -> Result<_> {..}

Simplification serves two purposes:

  • less boiler plate
  • consistency using sane defaults
  • make COMPONENT explicitly provided or implicitly assumed
  • allow customization for Result<_,_> types, to utilize our own Report trait

Further considerations:

Since we are hardwiring some special cases, we might go one step further, i.e. allow to print fields of which we know their relevance, i.e. BlockNumber is always safe to print, adding a "safe-list" and always add them as fields might be a good usability trade-off, while providing a off-switch with i.e. -. This ofc smells a lot like skip_all again, just more restricted, however the scope we operate in, this might be a good balance.

Metadata

Metadata

Assignees

Labels

telemetryRelates to tracing and open-telemetry

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions