This patch introduces a new options for tracing spans: a sterile span
does not admit child spans. Trying to create a child of a sterile span
results in a root span. In other words, in:
parent := t.StartSpan(WithSterile())
child1 := t.StartSpan(WithParentAndAutoCollection(parent))
child2 := t.StartSpan(WithParentAndManualCollection(parent.Meta()))
both child1 and child2 are root spans.
This is useful for modelling long-running operations that don't want a
relationship with all the sub-operations they spawn (think long-running
stopper tasks or pgwire connections). In particular, these long
operations don't want to accumulate the recordings of their children,
and they more generally don't want to be associated with their children
in a trace collector because that leads to infinitely long traces which
don't display well. For example, Zipkin doesn't make a distinction
between our ChildOf and FollowsFrom relationships, displaying both types
of relationships the same way. This makes long-running tasks with
children quite awkward. Given the tools at our disposal, maintaining
the relationship between random operations and their long-running
parents is more trouble than it's worth. The modelling of different
kinds of relationships between spans is an active topic of debate in the
OpenTelemetry project, so in the future I expect that we'll take note of
what has been decided there and apply it to our tracing.
Without this new option, it is difficult to decouple a span from what
would otherwise be its parent. I've explored different options that push
the responsibility of detaching to the point where the would-be child is
created, but the practicality sucks. Sometimes the code creating a span
doesn't know what context it's running in, and so it can't really make a
decision about whether it wants its span to be a child or not (i.e.
sometimes it wants a child, sometimes it doesn't). Instead, this patch
let's the parent brutally say "I never want any children", and then the
sub-operations can use functions like EnsureChildSpan() to get a child
span or a root span depending on the decision the parent made for them.
The next commits start using this new option for long-running stopper
tasks and such.
Release note: None