class ElasticAPM::Transaction

@api private

def build_and_start_span(name, type, context, backtrace)

def build_and_start_span(name, type, context, backtrace)
  span = next_span(name, type, context)
  spans << span
  span.stacktrace =
    backtrace && Stacktrace.build(@instrumenter.config, backtrace, :span)
  span.start
end

def current_span

def current_span
  spans.reverse.lazy.find(&:running?)
end

def done(result = nil)

def done(result = nil)
  @duration = Util.micros - @timestamp
  @result = result
  self
end

def done?

def done?
  !!(@result && @duration)
end

def initialize(

rubocop:disable Metrics/MethodLength
def initialize(
  instrumenter,
  name = nil,
  type = nil,
  context: nil,
  sampled: true
)
  @id = SecureRandom.uuid
  @instrumenter = instrumenter
  @name = name
  @type = type || DEFAULT_TYPE
  @timestamp = Util.micros
  @spans = []
  @span_id_ticker = -1
  @dropped_spans = 0
  @notifications = [] # for AS::Notifications
  @context = context || Context.new
  @sampled = sampled
  yield self if block_given?
end

def inspect

def inspect
  "<ElasticAPM::Transaction id:#{id}" \
    " name:#{name.inspect}" \
    " type:#{type.inspect}" \
    '>'
end

def next_span(name, type, context)

def next_span(name, type, context)
  Span.new(
    self,
    next_span_id,
    name,
    type,
    parent: current_span,
    context: context
  )
end

def next_span_id

def next_span_id
  @span_id_ticker += 1
end

def release

def release
  @instrumenter.current_transaction = nil
end

def running_spans

def running_spans
  spans.select(&:running?)
end

def sampled?

def sampled?
  !!sampled
end

def span(name, type = nil, backtrace: nil, context: nil)

rubocop:disable Metrics/MethodLength
def span(name, type = nil, backtrace: nil, context: nil)
  unless sampled?
    return yield if block_given?
    return
  end
  if spans.length >= instrumenter.config.transaction_max_spans
    @dropped_spans += 1
    return yield if block_given?
    return
  end
  span = build_and_start_span(name, type, context, backtrace)
  return span unless block_given?
  begin
    result = yield span
  ensure
    span.done
  end
  result
end

def submit(result = nil, status: nil, headers: {})

def submit(result = nil, status: nil, headers: {})
  done result
  if status
    context.response = Context::Response.new(status, headers: headers)
  end
  release
  @instrumenter.submit_transaction self
  self
end