109 lines
3.2 KiB
Ruby
109 lines
3.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Jaeger
|
|
module Extractors
|
|
class SerializedJaegerTrace
|
|
def self.parse(trace)
|
|
return nil if !trace || trace == ''
|
|
|
|
trace_arguments = trace.split(':').map(&TraceId.method(:base16_hex_id_to_uint64))
|
|
return nil if trace_arguments.size != 4
|
|
|
|
trace_id, span_id, parent_id, flags = trace_arguments
|
|
return nil if trace_id.zero? || span_id.zero?
|
|
|
|
SpanContext.new(
|
|
trace_id: trace_id,
|
|
parent_id: parent_id,
|
|
span_id: span_id,
|
|
flags: flags
|
|
)
|
|
end
|
|
end
|
|
|
|
class JaegerTextMapCodec
|
|
def self.extract(carrier)
|
|
context = SerializedJaegerTrace.parse(carrier['uber-trace-id'])
|
|
return nil unless context
|
|
|
|
carrier.each do |key, value|
|
|
baggage_match = key.match(/\Auberctx-([\w-]+)\Z/)
|
|
if baggage_match
|
|
context.set_baggage_item(baggage_match[1], value)
|
|
end
|
|
end
|
|
|
|
context
|
|
end
|
|
end
|
|
|
|
class JaegerRackCodec
|
|
def self.extract(carrier)
|
|
serialized_trace = carrier['HTTP_UBER_TRACE_ID']
|
|
serialized_trace = CGI.unescape(serialized_trace) if serialized_trace
|
|
context = SerializedJaegerTrace.parse(serialized_trace)
|
|
return nil unless context
|
|
|
|
carrier.each do |key, value|
|
|
baggage_match = key.match(/\AHTTP_UBERCTX_(\w+)\Z/)
|
|
if baggage_match
|
|
key = baggage_match[1].downcase.tr('_', '-')
|
|
context.set_baggage_item(key, CGI.unescape(value))
|
|
end
|
|
end
|
|
|
|
context
|
|
end
|
|
end
|
|
|
|
class JaegerBinaryCodec
|
|
def self.extract(_carrier)
|
|
warn 'Jaeger::Client with binary format is not supported yet'
|
|
end
|
|
end
|
|
|
|
class B3RackCodec
|
|
def self.extract(carrier)
|
|
trace_id = TraceId.base16_hex_id_to_uint64(carrier['HTTP_X_B3_TRACEID'])
|
|
span_id = TraceId.base16_hex_id_to_uint64(carrier['HTTP_X_B3_SPANID'])
|
|
parent_id = TraceId.base16_hex_id_to_uint64(carrier['HTTP_X_B3_PARENTSPANID'])
|
|
flags = parse_flags(carrier['HTTP_X_B3_FLAGS'], carrier['HTTP_X_B3_SAMPLED'])
|
|
|
|
return nil if span_id.nil? || trace_id.nil?
|
|
return nil if span_id.zero? || trace_id.zero?
|
|
|
|
SpanContext.new(
|
|
trace_id: trace_id,
|
|
parent_id: parent_id,
|
|
span_id: span_id,
|
|
flags: flags
|
|
)
|
|
end
|
|
|
|
# if the flags header is '1' then the sampled header should not be present
|
|
def self.parse_flags(flags_header, sampled_header)
|
|
if flags_header == '1'
|
|
Jaeger::SpanContext::Flags::DEBUG
|
|
else
|
|
TraceId.base16_hex_id_to_uint64(sampled_header)
|
|
end
|
|
end
|
|
private_class_method :parse_flags
|
|
end
|
|
|
|
DEFAULT_EXTRACTORS = {
|
|
OpenTracing::FORMAT_TEXT_MAP => JaegerTextMapCodec,
|
|
OpenTracing::FORMAT_BINARY => JaegerBinaryCodec,
|
|
OpenTracing::FORMAT_RACK => JaegerRackCodec
|
|
}.freeze
|
|
|
|
def self.prepare(extractors)
|
|
DEFAULT_EXTRACTORS.reduce(extractors) do |acc, (format, default)|
|
|
provided_extractors = Array(extractors[format])
|
|
provided_extractors += [default] if provided_extractors.empty?
|
|
|
|
acc.merge(format => provided_extractors)
|
|
end
|
|
end
|
|
end
|
|
end
|