span constructor and attributes according to spec
This commit is contained in:
Родитель
196ce7f58d
Коммит
bf6324aabe
|
@ -20,7 +20,7 @@ end
|
|||
thread2 = Thread.new do
|
||||
current = 1
|
||||
for i in 1..16
|
||||
child = LightStep.start_span('my_child', parent: span)
|
||||
child = LightStep.start_span('my_child', child_of: span)
|
||||
sleep(0.1)
|
||||
current *= 2
|
||||
child.log_event("2^#{i}", result: current)
|
||||
|
|
|
@ -2,23 +2,41 @@
|
|||
# to the spec. Baggage moves to span context.
|
||||
module LightStep
|
||||
class Span
|
||||
# ----------------------------------------------------------------------------
|
||||
# OpenTracing API
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
class UnsupportedValueTypeError < LightStep::Error; end
|
||||
|
||||
attr_reader :tracer
|
||||
attr_reader :guid, :tags, :baggage, :tracer
|
||||
attr_accessor :trace_guid, :operation_name, :start_micros, :end_micros
|
||||
|
||||
# TODO(ngauthier@gmail.com) validate value is string, bool, or number and
|
||||
# remove value.to_s from all calling code
|
||||
def initialize(
|
||||
tracer:,
|
||||
operation_name:,
|
||||
child_of_guid: nil,
|
||||
trace_guid:,
|
||||
start_micros:,
|
||||
end_micros: nil,
|
||||
tags: nil
|
||||
)
|
||||
@tags = Hash(tags)
|
||||
@baggage = {}
|
||||
|
||||
@tracer = tracer
|
||||
@guid = tracer.generate_guid
|
||||
self.operation_name = operation_name
|
||||
self.start_micros = start_micros
|
||||
self.end_micros = end_micros
|
||||
self.trace_guid = trace_guid
|
||||
set_tag(:parent_span_guid, child_of_guid) if !child_of_guid.nil?
|
||||
end
|
||||
|
||||
# TODO(ngauthier@gmail.com) []=
|
||||
def set_tag(key, value)
|
||||
case value
|
||||
when String, Fixnum, TrueClass, FalseClass
|
||||
@tags[key] = value
|
||||
else
|
||||
raise UnsupportedValueTypeError,
|
||||
"Value must be a string, number, or boolean: #{value.inspect} is a #{value.class.name}"
|
||||
"Value must be a string, number, or boolean: "+
|
||||
"#{value.inspect} is a #{value.class.name}"
|
||||
end
|
||||
self
|
||||
end
|
||||
|
@ -47,72 +65,20 @@ module LightStep
|
|||
@tracer.raw_log_record(record, fields[:payload])
|
||||
end
|
||||
|
||||
def finish(fields = nil)
|
||||
unless fields.nil?
|
||||
self.end_micros = fields[:endTime] * 1000 unless fields[:endTime].nil?
|
||||
end
|
||||
@tracer._finish_span(self)
|
||||
self
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Implemenation specific
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def initialize(tracer)
|
||||
@tags = {}
|
||||
@baggage = {}
|
||||
|
||||
@tracer = tracer
|
||||
@guid = tracer.generate_guid
|
||||
end
|
||||
|
||||
attr_reader :guid, :tags, :baggage
|
||||
attr_accessor :trace_guid
|
||||
|
||||
def finalize
|
||||
if @end_micros == 0
|
||||
# TODO: Notify about that finish() was never called for this span
|
||||
finish
|
||||
end
|
||||
end
|
||||
|
||||
attr_writer :start_micros
|
||||
def start_micros
|
||||
@start_micros ||= 0
|
||||
end
|
||||
|
||||
attr_writer :end_micros
|
||||
def end_micros
|
||||
@end_micros ||= 0
|
||||
end
|
||||
|
||||
attr_writer :operation_name
|
||||
def operation_name
|
||||
@operation_name ||= ''
|
||||
end
|
||||
|
||||
def parent_guid
|
||||
@tags[:parent_span_guid]
|
||||
end
|
||||
|
||||
def set_parent(span)
|
||||
set_tag(:parent_span_guid, span.guid)
|
||||
@trace_guid = span.trace_guid
|
||||
def finish(end_time: Time.now)
|
||||
@tracer._finish_span(self, end_time: end_time)
|
||||
self
|
||||
end
|
||||
|
||||
def to_h
|
||||
attributes = @tags.map do |key, value|
|
||||
{"Key" => key.to_s, "Value" => value}
|
||||
end
|
||||
|
||||
rec = {
|
||||
{
|
||||
"runtime_guid" => tracer.guid,
|
||||
"span_guid" => guid,
|
||||
"trace_guid" => trace_guid,
|
||||
"span_name" => operation_name,
|
||||
"attributes" => attributes,
|
||||
"attributes" => @tags.map {|key, value|
|
||||
{"Key" => key.to_s, "Value" => value}
|
||||
},
|
||||
"oldest_micros" => start_micros,
|
||||
"youngest_micros" => end_micros,
|
||||
"error_flag" => false
|
||||
|
|
|
@ -77,34 +77,26 @@ module LightStep
|
|||
# ----------------------------------------------------------------------------
|
||||
|
||||
# Starts a new span.
|
||||
#
|
||||
# The fields argument is optional. The accepted fields are:
|
||||
#
|
||||
# :parent - parent span object
|
||||
# :tags - map of key-value pairs
|
||||
# :startTime - manually specified start time of the span in milliseconds
|
||||
# :endTime - manually specified end time of the span in milliseconds
|
||||
#
|
||||
# TODO(ngauthier@gmail.com) parent should be child_of according to spec
|
||||
# TODO(ngauthier@gmail.com) support follows_from?
|
||||
# TODO(ngauthier@gmail.com) follows_from and child_of should be `references`
|
||||
# TODO(ngauthier@gmail.com) inherit SpanContext from references
|
||||
# TODO(ngauthier@gmail.com) fields should be tags
|
||||
# TODO(ngauthier@gmail.com) ability to provide a timestamp to be used other than now
|
||||
def start_span(operation_name, fields = nil)
|
||||
span = Span.new(self)
|
||||
span.operation_name = operation_name
|
||||
span.start_micros = now_micros
|
||||
|
||||
unless fields.nil?
|
||||
span.set_parent(fields[:parent]) unless fields[:parent].nil?
|
||||
span.set_tags(fields[:tags]) unless fields[:tags].nil?
|
||||
span.start_micros = fields[:startTime] * 1000 unless fields[:startTime].nil?
|
||||
span.end_micros = fields[:endTime] * 1000 unless fields[:endTime].nil?
|
||||
def start_span(operation_name, child_of: nil, start_time: nil, end_time: nil, tags: nil)
|
||||
child_of_guid = nil
|
||||
trace_guid = nil
|
||||
if Span === child_of
|
||||
child_of_guid = child_of.guid
|
||||
trace_guid = child_of.trace_guid
|
||||
else
|
||||
trace_guid = generate_guid
|
||||
end
|
||||
|
||||
span.trace_guid = generate_guid if span.trace_guid.nil?
|
||||
span
|
||||
Span.new(
|
||||
tracer: self,
|
||||
operation_name: operation_name,
|
||||
child_of_guid: child_of_guid,
|
||||
trace_guid: trace_guid,
|
||||
start_micros: start_time.nil? ? now_micros : micros(start_time),
|
||||
end_micros: end_time.nil? ? nil : micros(end_time),
|
||||
tags: tags
|
||||
)
|
||||
end
|
||||
|
||||
def inject(span, format, carrier)
|
||||
|
@ -148,7 +140,7 @@ module LightStep
|
|||
|
||||
# Disables the tracer
|
||||
# @param discard [Boolean] whether to discard queued data
|
||||
def disable(discard: false)
|
||||
def disable(discard: true)
|
||||
@enabled = false
|
||||
@tracer_transport.clear if discard
|
||||
@tracer_transport.flush
|
||||
|
@ -159,10 +151,10 @@ module LightStep
|
|||
end
|
||||
|
||||
# Internal use only.
|
||||
def _finish_span(span)
|
||||
def _finish_span(span, end_time: Time.now)
|
||||
return unless enabled?
|
||||
|
||||
span.end_micros = now_micros if span.end_micros === 0
|
||||
span.end_micros ||= micros(end_time)
|
||||
full = push_with_max(@tracer_span_records, span.to_h, max_span_records)
|
||||
@tracer_counters[:dropped_spans] += 1 if full
|
||||
flush_if_needed
|
||||
|
@ -296,11 +288,15 @@ module LightStep
|
|||
end
|
||||
|
||||
def now_micros
|
||||
(Time.now.to_f * 1e6).floor
|
||||
micros(Time.now)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def micros(time)
|
||||
(time.to_f * 1E6).floor
|
||||
end
|
||||
|
||||
def inject_to_text_map(span, carrier)
|
||||
carrier[CARRIER_TRACER_STATE_PREFIX + 'spanid'] = span.guid
|
||||
carrier[CARRIER_TRACER_STATE_PREFIX + 'traceid'] = span.trace_guid unless span.trace_guid.nil?
|
||||
|
@ -312,14 +308,13 @@ module LightStep
|
|||
end
|
||||
|
||||
def join_from_text_map(operation_name, carrier)
|
||||
span = Span.new(self)
|
||||
span.operation_name = operation_name
|
||||
span.start_micros = now_micros
|
||||
|
||||
parent_guid = carrier[CARRIER_TRACER_STATE_PREFIX + 'spanid']
|
||||
trace_guid = carrier[CARRIER_TRACER_STATE_PREFIX + 'traceid']
|
||||
span.trace_guid = trace_guid
|
||||
span.set_tag(:parent_span_guid, parent_guid)
|
||||
span = Span.new(
|
||||
tracer: self,
|
||||
operation_name: operation_name,
|
||||
start_micros: now_micros,
|
||||
child_of_guid: carrier[CARRIER_TRACER_STATE_PREFIX + 'spanid'],
|
||||
trace_guid: carrier[CARRIER_TRACER_STATE_PREFIX + 'traceid'],
|
||||
)
|
||||
|
||||
carrier.each do |key, value|
|
||||
next unless key.start_with?(CARRIER_BAGGAGE_PREFIX)
|
||||
|
|
|
@ -71,26 +71,33 @@ describe LightStep do
|
|||
it 'should allow start and end times to be specified explicitly' do
|
||||
tracer = init_test_tracer
|
||||
|
||||
span1 = tracer.start_span('test1', startTime: 1000)
|
||||
t1 = Time.now
|
||||
t1_micros = (t1.to_f * 1E6).floor
|
||||
t2 = t1 + 60
|
||||
t2_micros = (t2.to_f * 1E6).floor
|
||||
|
||||
span1 = tracer.start_span('test1', start_time: t1)
|
||||
span1.finish
|
||||
expect(span1.start_micros).to eq(1000 * 1000)
|
||||
expect(span1.start_micros).to eq(t1_micros)
|
||||
|
||||
span2 = tracer.start_span('test2', endTime: 54_321)
|
||||
span2 = tracer.start_span('test2', end_time: t1)
|
||||
span2.finish
|
||||
expect(span2.end_micros).to eq(54_321 * 1000)
|
||||
expect(span2.end_micros).to eq(t1_micros)
|
||||
|
||||
span3 = tracer.start_span('test3', startTime: 1234, endTime: 5678)
|
||||
span3 = tracer.start_span('test3', start_time: t1, end_time: t2)
|
||||
span3.finish
|
||||
expect(span3.start_micros).to eq(1234 * 1000)
|
||||
expect(span3.end_micros).to eq(5678 * 1000)
|
||||
expect(span3.start_micros).to eq(t1_micros)
|
||||
expect(span3.end_micros).to eq(t2_micros)
|
||||
end
|
||||
|
||||
it 'should allow end time to be specified at finish time' do
|
||||
tracer = init_test_tracer
|
||||
|
||||
t1 = Time.now
|
||||
t1_micros = (t1.to_f * 1E6).floor
|
||||
span = tracer.start_span('test')
|
||||
span.finish(endTime: 54_321)
|
||||
expect(span.end_micros).to eq(54_321 * 1000)
|
||||
span.finish(end_time: t1)
|
||||
expect(span.end_micros).to eq(t1_micros)
|
||||
end
|
||||
|
||||
it 'should assign the same trace_guid to child spans as the parent' do
|
||||
|
@ -98,8 +105,8 @@ describe LightStep do
|
|||
parent1 = tracer.start_span('parent1')
|
||||
parent2 = tracer.start_span('parent2')
|
||||
|
||||
children1 = (1..4).to_a.map { tracer.start_span('child', parent: parent1) }
|
||||
children2 = (1..4).to_a.map { tracer.start_span('child', parent: parent2) }
|
||||
children1 = (1..4).to_a.map { tracer.start_span('child', child_of: parent1) }
|
||||
children2 = (1..4).to_a.map { tracer.start_span('child', child_of: parent2) }
|
||||
|
||||
children1.each do |child|
|
||||
expect(child.trace_guid).to be_an_instance_of String
|
||||
|
@ -170,10 +177,10 @@ describe LightStep do
|
|||
it 'should handle nested spans' do
|
||||
tracer = init_test_tracer
|
||||
s0 = tracer.start_span('s0')
|
||||
s1 = tracer.start_span('s1', parent: s0)
|
||||
s2 = tracer.start_span('s2', parent: s1)
|
||||
s3 = tracer.start_span('s3', parent: s2)
|
||||
s4 = tracer.start_span('s4', parent: s3)
|
||||
s1 = tracer.start_span('s1', child_of: s0)
|
||||
s2 = tracer.start_span('s2', child_of: s1)
|
||||
s3 = tracer.start_span('s3', child_of: s2)
|
||||
s4 = tracer.start_span('s4', child_of: s3)
|
||||
s4.finish
|
||||
s3.finish
|
||||
s2.finish
|
||||
|
@ -250,7 +257,7 @@ describe LightStep do
|
|||
|
||||
span2 = tracer.join('test_span_2', LightStep.FORMAT_TEXT_MAP, carrier)
|
||||
expect(span2.trace_guid).to eq(span1.trace_guid)
|
||||
expect(span2.parent_guid).to eq(span1.guid)
|
||||
expect(span2.tags[:parent_span_guid]).to eq(span1.guid)
|
||||
expect(span2.get_baggage_item('footwear')).to eq('cleats')
|
||||
expect(span2.get_baggage_item('umbrella')).to eq('golf')
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче