class ElasticAPM::OpenTracing::Tracer

A custom tracer to use the OpenTracing API with ElasticAPM

def active_span

def active_span
  scope_manager.active&.span
end

def context_from_active_scope(ignore_active_scope)

def context_from_active_scope(ignore_active_scope)
  if ignore_active_scope
    ElasticAPM.agent&.config&.logger&.warn(
      'ignore_active_scope might lead to unexpected results'
    )
    return
  end
  @scope_manager.active&.span&.context
end

def context_from_child_of(child_of)

def context_from_child_of(child_of)
  return unless child_of
  child_of.respond_to?(:context) ? child_of.context : child_of
end

def context_from_references(references)

def context_from_references(references)
  return if !references || references.none?
  child_of = references.find do |reference|
    reference.type == ::OpenTracing::Reference::CHILD_OF
  end
  (child_of || references.first).context
end

def extract(format, carrier)

def extract(format, carrier)
  case format
  when ::OpenTracing::FORMAT_RACK
    SpanContext.from_header(
      carrier['HTTP_ELASTIC_APM_TRACEPARENT']
    )
  when ::OpenTracing::FORMAT_TEXT_MAP
    SpanContext.from_header(
      carrier['elastic-apm-traceparent']
    )
  else
    warn 'Only extraction from HTTP headers via Rack or in ' \
      'text map format are available'
    nil
  end
rescue ElasticAPM::TraceContext::InvalidTraceparentHeader
  nil
end

def initialize

def initialize
  @scope_manager = ScopeManager.new
end

def inject(span_context, format, carrier)

def inject(span_context, format, carrier)
  case format
  when ::OpenTracing::FORMAT_RACK, ::OpenTracing::FORMAT_TEXT_MAP
    carrier['elastic-apm-traceparent'] =
      span_context.traceparent.to_header
  else
    warn 'Only injection via HTTP headers and Rack is available'
  end
end

def prepare_span_context(

def prepare_span_context(
  child_of:,
  references:,
  ignore_active_scope:
)
  context = context_from_child_of(child_of) ||
            context_from_references(references) ||
            context_from_active_scope(ignore_active_scope)
  return context.child if context.respond_to?(:child)
  context
end

def start_active_span(

rubocop:disable Metrics/ParameterLists
def start_active_span(
  operation_name,
  child_of: nil,
  references: nil,
  start_time: Time.now,
  tags: {},
  ignore_active_scope: false,
  finish_on_close: true,
  **
)
  span = start_span(
    operation_name,
    child_of: child_of,
    references: references,
    start_time: start_time,
    tags: tags,
    ignore_active_scope: ignore_active_scope
  )
  scope = scope_manager.activate(span, finish_on_close: finish_on_close)
  if block_given?
    begin
      return yield scope
    ensure
      scope.close
    end
  end
  scope
end

def start_span(

rubocop:disable Metrics/ParameterLists
def start_span(
  operation_name,
  child_of: nil,
  references: nil,
  start_time: Time.now,
  tags: {},
  ignore_active_scope: false,
  **
)
  span_context = prepare_span_context(
    child_of: child_of,
    references: references,
    ignore_active_scope: ignore_active_scope
  )
  if span_context
    trace_context =
      span_context.respond_to?(:trace_context) &&
      span_context.trace_context
  end
  elastic_span =
    if ElasticAPM.current_transaction
      ElasticAPM.start_span(
        operation_name,
        trace_context: trace_context
      )
    else
      ElasticAPM.start_transaction(
        operation_name,
        trace_context: trace_context
      )
    end
  # if no Elastic APM agent is running or transaction not sampled
  unless elastic_span
    return ::OpenTracing::Span::NOOP_INSTANCE
  end
  span_context ||=
    SpanContext.from_trace_context(elastic_span.trace_context)
  tags.each do |key, value|
    elastic_span.context.labels[key] = value
  end
  elastic_span.start Util.micros(start_time)
  Span.new(elastic_span, span_context)
end