lightstep 0.12.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +32 -0
- data/.gitignore +1 -2
- data/.rubocop.yml +48 -0
- data/CHANGELOG.md +45 -0
- data/CONTRIBUTING.md +58 -0
- data/Gemfile.lock +52 -0
- data/Makefile +3 -3
- data/README.md +4 -1
- data/example.rb +2 -2
- data/examples/rack/inject_extract.rb +1 -1
- data/lib/lightstep.rb +4 -0
- data/lib/lightstep/propagation.rb +25 -0
- data/lib/lightstep/propagation/b3_propagator.rb +29 -0
- data/lib/lightstep/propagation/lightstep_propagator.rb +127 -0
- data/lib/lightstep/reporter.rb +14 -9
- data/lib/lightstep/scope.rb +23 -0
- data/lib/lightstep/scope_manager.rb +54 -0
- data/lib/lightstep/span.rb +44 -19
- data/lib/lightstep/span_context.rb +36 -3
- data/lib/lightstep/tracer.rb +131 -100
- data/lib/lightstep/transport/base.rb +0 -3
- data/lib/lightstep/transport/http_json.rb +74 -23
- data/lib/lightstep/version.rb +1 -1
- data/lightstep.gemspec +8 -4
- metadata +26 -17
- data/circle.yml +0 -3
data/lib/lightstep/reporter.rb
CHANGED
@@ -57,7 +57,10 @@ module LightStep
|
|
57
57
|
|
58
58
|
span_records = @span_records.slice!(0, @span_records.length)
|
59
59
|
dropped_spans = 0
|
60
|
-
@dropped_spans.update
|
60
|
+
@dropped_spans.update do |old|
|
61
|
+
dropped_spans = old
|
62
|
+
0
|
63
|
+
end
|
61
64
|
|
62
65
|
report_request = {
|
63
66
|
runtime: @runtime,
|
@@ -65,9 +68,10 @@ module LightStep
|
|
65
68
|
youngest_micros: now,
|
66
69
|
span_records: span_records,
|
67
70
|
internal_metrics: {
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
+
counts: [{
|
72
|
+
name: 'spans.dropped',
|
73
|
+
int64_value: dropped_spans
|
74
|
+
}]
|
71
75
|
}
|
72
76
|
}
|
73
77
|
|
@@ -75,9 +79,10 @@ module LightStep
|
|
75
79
|
|
76
80
|
begin
|
77
81
|
@transport.report(report_request)
|
78
|
-
rescue
|
79
|
-
|
80
|
-
|
82
|
+
rescue StandardError => e
|
83
|
+
LightStep.logger.error "LightStep error reporting to collector: #{e.message}"
|
84
|
+
# an error occurs, add the previous dropped_spans and count of spans
|
85
|
+
# that would have been recorded
|
81
86
|
@dropped_spans.increment(dropped_spans + span_records.length)
|
82
87
|
end
|
83
88
|
end
|
@@ -103,8 +108,8 @@ module LightStep
|
|
103
108
|
sleep(@period)
|
104
109
|
flush
|
105
110
|
end
|
106
|
-
rescue =>
|
107
|
-
|
111
|
+
rescue StandardError => e
|
112
|
+
LightStep.logger.error "LightStep failed to report spans: #{e.message}"
|
108
113
|
end
|
109
114
|
end
|
110
115
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module LightStep
|
2
|
+
# Scope represents an OpenTracing Scope
|
3
|
+
#
|
4
|
+
# See http://www.opentracing.io for more information.
|
5
|
+
class Scope
|
6
|
+
attr_reader :span
|
7
|
+
|
8
|
+
def initialize(manager:, span:, finish_on_close: true)
|
9
|
+
@manager = manager
|
10
|
+
@span = span
|
11
|
+
@finish_on_close = finish_on_close
|
12
|
+
end
|
13
|
+
|
14
|
+
# Mark the end of the active period for the current thread and Scope,
|
15
|
+
# updating the ScopeManager#active in the process.
|
16
|
+
def close
|
17
|
+
raise(LightStep::Error, 'already closed') if @closed
|
18
|
+
@closed = true
|
19
|
+
@span.finish if @finish_on_close
|
20
|
+
@manager.deactivate
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module LightStep
|
2
|
+
# ScopeManager represents an OpenTracing ScopeManager
|
3
|
+
#
|
4
|
+
# See http://www.opentracing.io for more information.
|
5
|
+
#
|
6
|
+
# The ScopeManager interface abstracts both the activation of Span instances
|
7
|
+
# via ScopeManager#activate and access to an active Span/Scope via
|
8
|
+
# ScopeManager#active
|
9
|
+
#
|
10
|
+
class ScopeManager
|
11
|
+
# Make a span instance active.
|
12
|
+
#
|
13
|
+
# @param span [Span] the Span that should become active
|
14
|
+
# @param finish_on_close [Boolean] whether the Span should automatically be
|
15
|
+
# finished when Scope#close is called
|
16
|
+
# @return [Scope] instance to control the end of the active period for the
|
17
|
+
# Span. It is a programming error to neglect to call Scope#close on the
|
18
|
+
# returned instance.
|
19
|
+
def activate(span:, finish_on_close: true)
|
20
|
+
return active if active && active.span == span
|
21
|
+
LightStep::Scope.new(manager: self, span: span, finish_on_close: finish_on_close).tap do |scope|
|
22
|
+
add_scope(scope)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Scope] the currently active Scope which can be used to access the
|
27
|
+
# currently active Span.
|
28
|
+
#
|
29
|
+
# If there is a non-null Scope, its wrapped Span becomes an implicit parent
|
30
|
+
# (as Reference#CHILD_OF) of any newly-created Span at Tracer#start_active_span
|
31
|
+
# or Tracer#start_span time.
|
32
|
+
def active
|
33
|
+
scopes.last
|
34
|
+
end
|
35
|
+
|
36
|
+
def deactivate
|
37
|
+
scopes.pop
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def scopes
|
43
|
+
Thread.current[object_id.to_s] || []
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_scope(scope)
|
47
|
+
if Thread.current[object_id.to_s].nil?
|
48
|
+
Thread.current[object_id.to_s] = [scope]
|
49
|
+
else
|
50
|
+
Thread.current[object_id.to_s] << scope
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/lightstep/span.rb
CHANGED
@@ -11,7 +11,10 @@ module LightStep
|
|
11
11
|
|
12
12
|
# Internal use only
|
13
13
|
# @private
|
14
|
-
attr_reader :start_micros, :end_micros, :tags, :operation_name, :
|
14
|
+
attr_reader :start_micros, :end_micros, :tags, :operation_name, :context
|
15
|
+
|
16
|
+
# To keep backwards compatibility
|
17
|
+
alias_method :span_context, :context
|
15
18
|
|
16
19
|
# Creates a new {Span}
|
17
20
|
#
|
@@ -37,8 +40,9 @@ module LightStep
|
|
37
40
|
tags: nil,
|
38
41
|
max_log_records:
|
39
42
|
)
|
43
|
+
|
40
44
|
@tags = Concurrent::Hash.new
|
41
|
-
@tags.update(tags) unless tags.nil?
|
45
|
+
@tags.update(tags.each { |k, v| tags[k] = v.to_s }) unless tags.nil?
|
42
46
|
@log_records = Concurrent::Array.new
|
43
47
|
@dropped_logs = Concurrent::AtomicFixnum.new
|
44
48
|
@max_log_records = max_log_records
|
@@ -49,14 +53,18 @@ module LightStep
|
|
49
53
|
|
50
54
|
ref = child_of ? child_of : references
|
51
55
|
ref = ref[0] if (Array === ref)
|
52
|
-
ref = ref.
|
56
|
+
ref = ref.context if (Span === ref)
|
53
57
|
|
54
58
|
if SpanContext === ref
|
55
|
-
@
|
59
|
+
@context = SpanContext.new(
|
60
|
+
id: LightStep.guid,
|
61
|
+
trace_id: ref.trace_id,
|
62
|
+
trace_id_upper64: ref.trace_id_upper64,
|
63
|
+
sampled: ref.sampled?)
|
56
64
|
set_baggage(ref.baggage)
|
57
65
|
set_tag(:parent_span_guid, ref.id)
|
58
66
|
else
|
59
|
-
@
|
67
|
+
@context = SpanContext.new(id: LightStep.guid, trace_id: LightStep.guid)
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
@@ -76,10 +84,12 @@ module LightStep
|
|
76
84
|
# @param key [String] the key of the baggage item
|
77
85
|
# @param value [String] the value of the baggage item
|
78
86
|
def set_baggage_item(key, value)
|
79
|
-
@
|
80
|
-
id:
|
81
|
-
trace_id:
|
82
|
-
|
87
|
+
@context = SpanContext.new(
|
88
|
+
id: context.id,
|
89
|
+
trace_id: context.trace_id,
|
90
|
+
trace_id_upper64: context.trace_id_upper64,
|
91
|
+
sampled: context.sampled?,
|
92
|
+
baggage: context.baggage.merge({key => value})
|
83
93
|
)
|
84
94
|
self
|
85
95
|
end
|
@@ -87,9 +97,11 @@ module LightStep
|
|
87
97
|
# Set all baggage at once. This will reset the baggage to the given param.
|
88
98
|
# @param baggage [Hash] new baggage for the span
|
89
99
|
def set_baggage(baggage = {})
|
90
|
-
@
|
91
|
-
id:
|
92
|
-
trace_id:
|
100
|
+
@context = SpanContext.new(
|
101
|
+
id: context.id,
|
102
|
+
trace_id: context.trace_id,
|
103
|
+
trace_id_upper64: context.trace_id_upper64,
|
104
|
+
sampled: context.sampled?,
|
93
105
|
baggage: baggage
|
94
106
|
)
|
95
107
|
end
|
@@ -98,25 +110,38 @@ module LightStep
|
|
98
110
|
# @param key [String] the key of the baggage item
|
99
111
|
# @return Value of the baggage item
|
100
112
|
def get_baggage_item(key)
|
101
|
-
|
113
|
+
context.baggage[key]
|
102
114
|
end
|
103
115
|
|
116
|
+
# @deprecated Use {#log_kv} instead.
|
104
117
|
# Add a log entry to this span
|
105
118
|
# @param event [String] event name for the log
|
106
119
|
# @param timestamp [Time] time of the log
|
107
|
-
# @param fields [Hash] Additional information to log
|
120
|
+
# @param fields [Hash{Symbol=>Object}] Additional information to log
|
108
121
|
def log(event: nil, timestamp: Time.now, **fields)
|
122
|
+
warn 'Span#log is deprecated. Please use Span#log_kv instead.'
|
109
123
|
return unless tracer.enabled?
|
110
124
|
|
111
125
|
fields = {} if fields.nil?
|
112
126
|
unless event.nil?
|
113
127
|
fields[:event] = event.to_s
|
114
128
|
end
|
129
|
+
|
130
|
+
log_kv(timestamp: timestamp, **fields)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Add a log entry to this span
|
134
|
+
# @param timestamp [Time] time of the log
|
135
|
+
# @param fields [Hash{Symbol=>Object}] Additional information to log
|
136
|
+
def log_kv(timestamp: Time.now, **fields)
|
137
|
+
return unless tracer.enabled?
|
138
|
+
|
139
|
+
fields = {} if fields.nil?
|
115
140
|
record = {
|
116
141
|
timestamp_micros: LightStep.micros(timestamp),
|
117
|
-
fields: fields.to_a.map
|
118
|
-
{Key: key.to_s, Value: value.to_s}
|
119
|
-
|
142
|
+
fields: fields.to_a.map do |key, value|
|
143
|
+
{ Key: key.to_s, Value: value.to_s }
|
144
|
+
end
|
120
145
|
}
|
121
146
|
|
122
147
|
log_records.push(record)
|
@@ -140,8 +165,8 @@ module LightStep
|
|
140
165
|
def to_h
|
141
166
|
{
|
142
167
|
runtime_guid: tracer.guid,
|
143
|
-
span_guid:
|
144
|
-
trace_guid:
|
168
|
+
span_guid: context.id,
|
169
|
+
trace_guid: context.trace_id,
|
145
170
|
span_name: operation_name,
|
146
171
|
attributes: tags.map {|key, value|
|
147
172
|
{Key: key.to_s, Value: value}
|
@@ -1,12 +1,45 @@
|
|
1
|
+
#frozen_string_literal: true
|
2
|
+
|
1
3
|
module LightStep
|
2
4
|
# SpanContext holds the data for a span that gets inherited to child spans
|
3
5
|
class SpanContext
|
4
|
-
attr_reader :id, :trace_id, :baggage
|
6
|
+
attr_reader :id, :trace_id, :trace_id_upper64, :sampled, :baggage
|
7
|
+
alias_method :trace_id64, :trace_id
|
8
|
+
alias_method :sampled?, :sampled
|
9
|
+
|
10
|
+
ZERO_PADDING = '0' * 16
|
5
11
|
|
6
|
-
def initialize(id:, trace_id:, baggage: {})
|
12
|
+
def initialize(id:, trace_id:, trace_id_upper64: nil, sampled: true, baggage: {})
|
7
13
|
@id = id.freeze
|
8
|
-
@trace_id = trace_id.freeze
|
14
|
+
@trace_id = truncate_id(trace_id).freeze
|
15
|
+
@trace_id_upper64 = trace_id_upper64 || extended_bits(trace_id).freeze
|
16
|
+
@sampled = sampled
|
9
17
|
@baggage = baggage.freeze
|
10
18
|
end
|
19
|
+
|
20
|
+
# Lazily initializes and returns a 128-bit representation of a 64-bit trace id
|
21
|
+
def trace_id128
|
22
|
+
@trace_id128 ||= "#{trace_id_upper64 || ZERO_PADDING}#{trace_id}"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns true if the original trace_id was 128 bits
|
26
|
+
def id_truncated?
|
27
|
+
!@trace_id_upper64.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Truncates an id to 64 bits
|
33
|
+
def truncate_id(id)
|
34
|
+
return id unless id && id.size == 32
|
35
|
+
id[16..-1]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the most significant 64 bits of a 128 bit id or nil if the id
|
39
|
+
# is 64 bits
|
40
|
+
def extended_bits(id)
|
41
|
+
return unless id && id.size == 32
|
42
|
+
id[0...16]
|
43
|
+
end
|
11
44
|
end
|
12
45
|
end
|
data/lib/lightstep/tracer.rb
CHANGED
@@ -5,6 +5,7 @@ require 'opentracing'
|
|
5
5
|
|
6
6
|
require 'lightstep/span'
|
7
7
|
require 'lightstep/reporter'
|
8
|
+
require 'lightstep/propagation'
|
8
9
|
require 'lightstep/transport/http_json'
|
9
10
|
require 'lightstep/transport/nil'
|
10
11
|
require 'lightstep/transport/callback'
|
@@ -14,6 +15,11 @@ module LightStep
|
|
14
15
|
class Error < LightStep::Error; end
|
15
16
|
class ConfigurationError < LightStep::Tracer::Error; end
|
16
17
|
|
18
|
+
DEFAULT_MAX_LOG_RECORDS = 1000
|
19
|
+
MIN_MAX_LOG_RECORDS = 1
|
20
|
+
DEFAULT_MAX_SPAN_RECORDS = 1000
|
21
|
+
MIN_MAX_SPAN_RECORDS = 1
|
22
|
+
|
17
23
|
attr_reader :access_token, :guid
|
18
24
|
|
19
25
|
# Initialize a new tracer. Either an access_token or a transport must be
|
@@ -22,10 +28,20 @@ module LightStep
|
|
22
28
|
# @param access_token [String] The project access token when pushing to LightStep
|
23
29
|
# @param transport [LightStep::Transport] How the data should be transported
|
24
30
|
# @param tags [Hash] Tracer-level tags
|
31
|
+
# @param propagator [Propagator] Symbol one of :lightstep, :b3 indicating the propagator
|
32
|
+
# to use
|
25
33
|
# @return LightStep::Tracer
|
26
34
|
# @raise LightStep::ConfigurationError if the group name or access token is not a valid string.
|
27
|
-
def initialize(component_name:,
|
28
|
-
|
35
|
+
def initialize(component_name:,
|
36
|
+
access_token: nil,
|
37
|
+
transport: nil,
|
38
|
+
tags: {},
|
39
|
+
propagator: :lightstep)
|
40
|
+
configure(component_name: component_name,
|
41
|
+
access_token: access_token,
|
42
|
+
transport: transport,
|
43
|
+
tags: tags,
|
44
|
+
propagator: propagator)
|
29
45
|
end
|
30
46
|
|
31
47
|
def max_log_records
|
@@ -53,6 +69,83 @@ module LightStep
|
|
53
69
|
|
54
70
|
# TODO(bhs): Support FollowsFrom and multiple references
|
55
71
|
|
72
|
+
# Creates a scope manager or returns the already-created one.
|
73
|
+
#
|
74
|
+
# @return [ScopeManager] the current ScopeManager, which may be a no-op but
|
75
|
+
# may not be nil.
|
76
|
+
def scope_manager
|
77
|
+
@scope_manager ||= LightStep::ScopeManager.new
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a newly started and activated Scope.
|
81
|
+
#
|
82
|
+
# If ScopeManager#active is not nil, no explicit references are provided,
|
83
|
+
# and `ignore_active_scope` is false, then an inferred References#CHILD_OF
|
84
|
+
# reference is created to the ScopeManager#active's SpanContext when
|
85
|
+
# start_active_span is invoked.
|
86
|
+
#
|
87
|
+
# @param operation_name [String] The operation name for the Span
|
88
|
+
# @param child_of [SpanContext, Span] SpanContext that acts as a parent to
|
89
|
+
# the newly-started Span. If a Span instance is provided, its
|
90
|
+
# context is automatically substituted. See [Reference] for more
|
91
|
+
# information.
|
92
|
+
#
|
93
|
+
# If specified, the `references` parameter must be omitted.
|
94
|
+
# @param references [Array<Reference>] An array of reference
|
95
|
+
# objects that identify one or more parent SpanContexts.
|
96
|
+
# @param start_time [Time] When the Span started, if not now
|
97
|
+
# @param tags [Hash] Tags to assign to the Span at start time
|
98
|
+
# @param ignore_active_scope [Boolean] whether to create an implicit
|
99
|
+
# References#CHILD_OF reference to the ScopeManager#active.
|
100
|
+
# @param finish_on_close [Boolean] whether span should automatically be
|
101
|
+
# finished when Scope#close is called
|
102
|
+
# @yield [Scope] If an optional block is passed to start_active_span it will
|
103
|
+
# yield the newly-started Scope. If `finish_on_close` is true then the
|
104
|
+
# Span will be finished automatically after the block is executed.
|
105
|
+
# @return [Scope, Object] If passed an optional block, start_active_span
|
106
|
+
# returns the block's return value, otherwise it returns the newly-started
|
107
|
+
# and activated Scope
|
108
|
+
def start_active_span(operation_name,
|
109
|
+
child_of: nil,
|
110
|
+
references: nil,
|
111
|
+
start_time: Time.now,
|
112
|
+
tags: nil,
|
113
|
+
ignore_active_scope: false,
|
114
|
+
finish_on_close: true)
|
115
|
+
if child_of.nil? && references.nil? && !ignore_active_scope
|
116
|
+
child_of = active_span
|
117
|
+
end
|
118
|
+
|
119
|
+
span = start_span(
|
120
|
+
operation_name,
|
121
|
+
child_of: child_of,
|
122
|
+
references: references,
|
123
|
+
start_time: start_time,
|
124
|
+
tags: tags,
|
125
|
+
ignore_active_scope: ignore_active_scope
|
126
|
+
)
|
127
|
+
|
128
|
+
scope_manager.activate(span: span, finish_on_close: finish_on_close).tap do |scope|
|
129
|
+
if block_given?
|
130
|
+
begin
|
131
|
+
return yield scope
|
132
|
+
ensure
|
133
|
+
scope.close
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns the span from the active scope, if any.
|
140
|
+
#
|
141
|
+
# @return [Span, nil] the active span. This is a shorthand for
|
142
|
+
# `scope_manager.active.span`, and nil will be returned if
|
143
|
+
# Scope#active is nil.
|
144
|
+
def active_span
|
145
|
+
scope = scope_manager.active
|
146
|
+
scope.span if scope
|
147
|
+
end
|
148
|
+
|
56
149
|
# Starts a new span.
|
57
150
|
#
|
58
151
|
# @param operation_name [String] The operation name for the Span
|
@@ -64,10 +157,21 @@ module LightStep
|
|
64
157
|
# are provided, their .span_context is automatically substituted.
|
65
158
|
# @param start_time [Time] When the Span started, if not now
|
66
159
|
# @param tags [Hash] Tags to assign to the Span at start time
|
67
|
-
# @
|
68
|
-
|
160
|
+
# @param ignore_active_scope [Boolean] whether to create an implicit
|
161
|
+
# References#CHILD_OF reference to the ScopeManager#active.
|
162
|
+
# @yield [Span] If passed an optional block, start_span will yield the
|
163
|
+
# newly-created span to the block. The span will be finished automatically
|
164
|
+
# after the block is executed.
|
165
|
+
# @return [Span, Object] If passed an optional block, start_span will return
|
166
|
+
# the block's return value, otherwise it returns the newly-started Span
|
167
|
+
# instance, which has not been automatically registered via the
|
168
|
+
# ScopeManager
|
169
|
+
def start_span(operation_name, child_of: nil, references: nil, start_time: nil, tags: nil, ignore_active_scope: false)
|
170
|
+
if child_of.nil? && references.nil? && !ignore_active_scope
|
171
|
+
child_of = active_span
|
172
|
+
end
|
69
173
|
|
70
|
-
|
174
|
+
span_options = {
|
71
175
|
tracer: self,
|
72
176
|
operation_name: operation_name,
|
73
177
|
child_of: child_of,
|
@@ -75,25 +179,27 @@ module LightStep
|
|
75
179
|
start_micros: start_time.nil? ? LightStep.micros(Time.now) : LightStep.micros(start_time),
|
76
180
|
tags: tags,
|
77
181
|
max_log_records: max_log_records,
|
78
|
-
|
182
|
+
}
|
183
|
+
|
184
|
+
Span.new(span_options).tap do |span|
|
185
|
+
if block_given?
|
186
|
+
begin
|
187
|
+
return yield span
|
188
|
+
ensure
|
189
|
+
span.finish
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
79
193
|
end
|
80
194
|
|
195
|
+
|
81
196
|
# Inject a SpanContext into the given carrier
|
82
197
|
#
|
83
198
|
# @param spancontext [SpanContext]
|
84
199
|
# @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY]
|
85
200
|
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
86
201
|
def inject(span_context, format, carrier)
|
87
|
-
|
88
|
-
when OpenTracing::FORMAT_TEXT_MAP
|
89
|
-
inject_to_text_map(span_context, carrier)
|
90
|
-
when OpenTracing::FORMAT_BINARY
|
91
|
-
warn 'Binary inject format not yet implemented'
|
92
|
-
when OpenTracing::FORMAT_RACK
|
93
|
-
inject_to_rack(span_context, carrier)
|
94
|
-
else
|
95
|
-
warn 'Unknown inject format'
|
96
|
-
end
|
202
|
+
@propagator.inject(span_context, format, carrier)
|
97
203
|
end
|
98
204
|
|
99
205
|
# Extract a SpanContext from a carrier
|
@@ -101,18 +207,7 @@ module LightStep
|
|
101
207
|
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
102
208
|
# @return [SpanContext] the extracted SpanContext or nil if none could be found
|
103
209
|
def extract(format, carrier)
|
104
|
-
|
105
|
-
when OpenTracing::FORMAT_TEXT_MAP
|
106
|
-
extract_from_text_map(carrier)
|
107
|
-
when OpenTracing::FORMAT_BINARY
|
108
|
-
warn 'Binary join format not yet implemented'
|
109
|
-
nil
|
110
|
-
when OpenTracing::FORMAT_RACK
|
111
|
-
extract_from_rack(carrier)
|
112
|
-
else
|
113
|
-
warn 'Unknown join format'
|
114
|
-
nil
|
115
|
-
end
|
210
|
+
@propagator.extract(format, carrier)
|
116
211
|
end
|
117
212
|
|
118
213
|
# @return true if the tracer is enabled
|
@@ -149,8 +244,12 @@ module LightStep
|
|
149
244
|
|
150
245
|
protected
|
151
246
|
|
152
|
-
def configure(component_name:,
|
153
|
-
|
247
|
+
def configure(component_name:,
|
248
|
+
access_token: nil,
|
249
|
+
transport: nil, tags: {},
|
250
|
+
propagator: :lightstep)
|
251
|
+
|
252
|
+
raise ConfigurationError, "component_name must be a string" unless component_name.is_a?(String)
|
154
253
|
raise ConfigurationError, "component_name cannot be blank" if component_name.empty?
|
155
254
|
|
156
255
|
if transport.nil? and !access_token.nil?
|
@@ -160,6 +259,8 @@ module LightStep
|
|
160
259
|
raise ConfigurationError, "you must provide an access token or a transport" if transport.nil?
|
161
260
|
raise ConfigurationError, "#{transport} is not a LightStep transport class" if !(LightStep::Transport::Base === transport)
|
162
261
|
|
262
|
+
@propagator = Propagation[propagator]
|
263
|
+
|
163
264
|
@guid = LightStep.guid
|
164
265
|
|
165
266
|
@reporter = LightStep::Reporter.new(
|
@@ -170,75 +271,5 @@ module LightStep
|
|
170
271
|
tags: tags
|
171
272
|
)
|
172
273
|
end
|
173
|
-
|
174
|
-
private
|
175
|
-
|
176
|
-
CARRIER_TRACER_STATE_PREFIX = 'ot-tracer-'.freeze
|
177
|
-
CARRIER_BAGGAGE_PREFIX = 'ot-baggage-'.freeze
|
178
|
-
|
179
|
-
CARRIER_SPAN_ID = (CARRIER_TRACER_STATE_PREFIX + 'spanid').freeze
|
180
|
-
CARRIER_TRACE_ID = (CARRIER_TRACER_STATE_PREFIX + 'traceid').freeze
|
181
|
-
CARRIER_SAMPLED = (CARRIER_TRACER_STATE_PREFIX + 'sampled').freeze
|
182
|
-
|
183
|
-
DEFAULT_MAX_LOG_RECORDS = 1000
|
184
|
-
MIN_MAX_LOG_RECORDS = 1
|
185
|
-
DEFAULT_MAX_SPAN_RECORDS = 1000
|
186
|
-
MIN_MAX_SPAN_RECORDS = 1
|
187
|
-
|
188
|
-
def inject_to_text_map(span_context, carrier)
|
189
|
-
carrier[CARRIER_SPAN_ID] = span_context.id
|
190
|
-
carrier[CARRIER_TRACE_ID] = span_context.trace_id unless span_context.trace_id.nil?
|
191
|
-
carrier[CARRIER_SAMPLED] = 'true'
|
192
|
-
|
193
|
-
span_context.baggage.each do |key, value|
|
194
|
-
carrier[CARRIER_BAGGAGE_PREFIX + key] = value
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def extract_from_text_map(carrier)
|
199
|
-
# If the carrier does not have both the span_id and trace_id key
|
200
|
-
# skip the processing and just return a normal span
|
201
|
-
if !carrier.has_key?(CARRIER_SPAN_ID) || !carrier.has_key?(CARRIER_TRACE_ID)
|
202
|
-
return nil
|
203
|
-
end
|
204
|
-
|
205
|
-
baggage = carrier.reduce({}) do |baggage, tuple|
|
206
|
-
key, value = tuple
|
207
|
-
if key.start_with?(CARRIER_BAGGAGE_PREFIX)
|
208
|
-
plain_key = key.to_s[CARRIER_BAGGAGE_PREFIX.length..key.to_s.length]
|
209
|
-
baggage[plain_key] = value
|
210
|
-
end
|
211
|
-
baggage
|
212
|
-
end
|
213
|
-
SpanContext.new(
|
214
|
-
id: carrier[CARRIER_SPAN_ID],
|
215
|
-
trace_id: carrier[CARRIER_TRACE_ID],
|
216
|
-
baggage: baggage,
|
217
|
-
)
|
218
|
-
end
|
219
|
-
|
220
|
-
def inject_to_rack(span_context, carrier)
|
221
|
-
carrier[CARRIER_SPAN_ID] = span_context.id
|
222
|
-
carrier[CARRIER_TRACE_ID] = span_context.trace_id unless span_context.trace_id.nil?
|
223
|
-
carrier[CARRIER_SAMPLED] = 'true'
|
224
|
-
|
225
|
-
span_context.baggage.each do |key, value|
|
226
|
-
if key =~ /[^A-Za-z0-9\-_]/
|
227
|
-
# TODO: log the error internally
|
228
|
-
next
|
229
|
-
end
|
230
|
-
carrier[CARRIER_BAGGAGE_PREFIX + key] = value
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
def extract_from_rack(env)
|
235
|
-
extract_from_text_map(env.reduce({}){|memo, tuple|
|
236
|
-
raw_header, value = tuple
|
237
|
-
header = raw_header.gsub(/^HTTP_/, '').gsub("_", "-").downcase
|
238
|
-
|
239
|
-
memo[header] = value if header.start_with?(CARRIER_TRACER_STATE_PREFIX, CARRIER_BAGGAGE_PREFIX)
|
240
|
-
memo
|
241
|
-
})
|
242
|
-
end
|
243
274
|
end
|
244
275
|
end
|