class Buildkite::TestCollector::Tracer

in #as_json which recursively calls #as_json on all of it’s children.
is the root of the tree (see #finalize). The tree is converted into a hash
When the trace is complete the stack MUST contain a single node @top, which
is stored at @stack.
span is also stored in the stack. The root of the tree is called @top and
- A tree made up of many Span nodes. Each Span is a node in the tree. Each
- A stack (called @stack) that traces the entering & leaving of each part of the application.
This class contains two data structures:
Traces the execution of an application by creating and storing spans of information.

def backfill(section, duration, **detail)

def backfill(section, duration, **detail)
  now = MonotonicTime.call
  new_entry = Span.new(section, now - duration, now, detail)
  current_span.children << new_entry if retain_span?(new_entry)
end

def current_span

def current_span
  @stack.last
end

def enter(section, **detail)

def enter(section, **detail)
  new_entry = Span.new(section, MonotonicTime.call, nil, detail)
  current_span.children << new_entry
  @stack << new_entry
end

def finalize

def finalize
  raise "Stack not empty" unless @stack.size == 1
  @top.end_at = MonotonicTime.call
  self
end

def history

def history
  @top.as_hash
end

def initialize(min_duration: nil)

def initialize(min_duration: nil)
  @top = Span.new(:top, MonotonicTime.call, nil, {})
  @stack = [@top]
end

def leave

def leave
  current_span.end_at = MonotonicTime.call
  @stack.pop
  current_span.children.pop unless retain_span?(current_span.children.last)
  nil # avoid ambiguous return type/value
end

def retain_span?(span)

def retain_span?(span)
  return true unless Buildkite::TestCollector.span_filters
  Buildkite::TestCollector.span_filters.all? do |filter|
    filter.call(span)
  end
end