class LHC::Zipkin

def after_response

def after_response
  # only sample the current call if we're instructed to do so
  return unless dependencies? && trace_id.sampled?
  end_trace!
end

def before_request

def before_request
  return if !dependencies? || !tracing?
  ZipkinTracer::TraceContainer.with_trace_id(trace_id) do
    # add headers even if the current trace_id should not be sampled
    B3_HEADERS.each { |method, header| request.headers[header] = trace_id.send(method).to_s }
    # only sample the current call if we're instructed to do so
    start_trace! if ::Trace.tracer && trace_id.sampled?
  end
end

def dependencies?

def dependencies?
  (
    defined?(ZipkinTracer::TraceContainer) &&
    defined?(::Trace) &&
    defined?(::Trace::Annotation) &&
    defined?(::Trace::BinaryAnnotation) &&
    defined?(::Trace::Endpoint)
  ) || warn('[WARNING] Zipkin interceptor is enabled but dependencies are not found. See: https://github.com/local-ch/lhc#zipkin')
end

def end_trace!

def end_trace!
  record_status
  record_error if !response.success?
  record_end
end

def local_endpoint

def local_endpoint
  @local_endpoint ||= ::Trace.default_endpoint
end

def record_end

def record_end
  span.record(::Trace::Annotation::CLIENT_RECV, local_endpoint)
  ::Trace.tracer.end_span(span)
end

def record_error

def record_error
  span.record_tag(::Trace::BinaryAnnotation::ERROR, status, ::Trace::BinaryAnnotation::Type::STRING, local_endpoint)
end

def record_local_endpoint

def record_local_endpoint
  span.record(::Trace::Annotation::CLIENT_SEND, local_endpoint)
end

def record_path

def record_path
  span.record_tag(::Trace::BinaryAnnotation::PATH, url.path, ::Trace::BinaryAnnotation::Type::STRING, local_endpoint)
end

def record_remote_endpoint

def record_remote_endpoint
  span.record_tag(::Trace::BinaryAnnotation::SERVER_ADDRESS, TRUE, ::Trace::BinaryAnnotation::Type::BOOL, remote_endpoint)
end

def record_status

def record_status
  span.record_tag(::Trace::BinaryAnnotation::STATUS, status, ::Trace::BinaryAnnotation::Type::STRING, local_endpoint)
end

def remote_endpoint

def remote_endpoint
  @remote_endpoint ||= ::Trace::Endpoint.remote_endpoint(url, service_name, local_endpoint.ip_format)
end

def service_name

def service_name
  @service_name ||= url.host
end

def span

register a new span with zipkin tracer
def span
  @span ||= ::Trace.tracer.start_span(trace_id, url.path)
end

def start_trace!

def start_trace!
  record_path
  record_remote_endpoint
  record_local_endpoint
end

def status

def status
  @status ||= response.code.to_s
end

def trace_id

def trace_id
  @trace_id ||= ZipkinTracer::TraceGenerator.new.next_trace_id
end

def tracing?

def tracing?
  ZipkinTracer::TraceContainer.current
end

def url

def url
  @url ||= URI(request.raw.url)
end