span constructor and attributes according to spec

This commit is contained in:
Nick Gauthier 2016-10-28 14:22:43 -04:00
Родитель 196ce7f58d
Коммит bf6324aabe
4 изменённых файлов: 88 добавлений и 120 удалений

Просмотреть файл

@ -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')