boost-jaeger-client 0.7.0
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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +47 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +57 -0
- data/Rakefile +9 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/boost-jaeger-client.gemspec +31 -0
- data/lib/jaeger/client/carrier.rb +26 -0
- data/lib/jaeger/client/collector.rb +91 -0
- data/lib/jaeger/client/samplers/const.rb +29 -0
- data/lib/jaeger/client/samplers/probabilistic.rb +30 -0
- data/lib/jaeger/client/samplers.rb +4 -0
- data/lib/jaeger/client/scope.rb +40 -0
- data/lib/jaeger/client/scope_manager/scope_identifier.rb +15 -0
- data/lib/jaeger/client/scope_manager/scope_stack.rb +35 -0
- data/lib/jaeger/client/scope_manager.rb +49 -0
- data/lib/jaeger/client/span/thrift_log_builder.rb +20 -0
- data/lib/jaeger/client/span/thrift_tag_builder.rb +45 -0
- data/lib/jaeger/client/span.rb +83 -0
- data/lib/jaeger/client/span_context.rb +78 -0
- data/lib/jaeger/client/trace_id.rb +13 -0
- data/lib/jaeger/client/tracer.rb +220 -0
- data/lib/jaeger/client/udp_sender/transport.rb +42 -0
- data/lib/jaeger/client/udp_sender.rb +82 -0
- data/lib/jaeger/client/version.rb +7 -0
- data/lib/jaeger/client.rb +44 -0
- data/script/create_follows_from_trace +52 -0
- data/script/create_trace +53 -0
- data/thrift/agent.thrift +32 -0
- data/thrift/gen-rb/jaeger/thrift/agent/agent.rb +118 -0
- data/thrift/gen-rb/jaeger/thrift/agent/agent_constants.rb +15 -0
- data/thrift/gen-rb/jaeger/thrift/agent/agent_types.rb +17 -0
- data/thrift/gen-rb/jaeger/thrift/agent.rb +116 -0
- data/thrift/gen-rb/jaeger/thrift/agent_constants.rb +13 -0
- data/thrift/gen-rb/jaeger/thrift/agent_types.rb +15 -0
- data/thrift/gen-rb/jaeger/thrift/collector.rb +82 -0
- data/thrift/gen-rb/jaeger/thrift/jaeger_constants.rb +13 -0
- data/thrift/gen-rb/jaeger/thrift/jaeger_types.rb +211 -0
- data/thrift/gen-rb/jaeger/thrift/zipkin/zipkin_collector.rb +84 -0
- data/thrift/gen-rb/jaeger/thrift/zipkin/zipkincore_constants.rb +41 -0
- data/thrift/gen-rb/jaeger/thrift/zipkin/zipkincore_types.rb +220 -0
- data/thrift/jaeger.thrift +88 -0
- data/thrift/zipkincore.thrift +300 -0
- metadata +190 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'span/thrift_tag_builder'
|
4
|
+
require_relative 'span/thrift_log_builder'
|
5
|
+
|
6
|
+
module Jaeger
|
7
|
+
module Client
|
8
|
+
class Span
|
9
|
+
attr_accessor :operation_name
|
10
|
+
|
11
|
+
attr_reader :context, :start_time, :references, :tags, :logs
|
12
|
+
|
13
|
+
# Creates a new {Span}
|
14
|
+
#
|
15
|
+
# @param context [SpanContext] the context of the span
|
16
|
+
# @param operation_name [String] the operation name
|
17
|
+
# @param collector [Collector] span collector
|
18
|
+
#
|
19
|
+
# @return [Span] a new Span
|
20
|
+
def initialize(context, operation_name, collector, start_time: Time.now, references: [], tags: {})
|
21
|
+
@context = context
|
22
|
+
@operation_name = operation_name
|
23
|
+
@collector = collector
|
24
|
+
@start_time = start_time
|
25
|
+
@references = references
|
26
|
+
@tags = tags.map { |key, value| ThriftTagBuilder.build(key, value) }
|
27
|
+
@logs = []
|
28
|
+
end
|
29
|
+
|
30
|
+
# Set a tag value on this span
|
31
|
+
#
|
32
|
+
# @param key [String] the key of the tag
|
33
|
+
# @param value [String, Numeric, Boolean] the value of the tag. If it's not
|
34
|
+
# a String, Numeric, or Boolean it will be encoded with to_s
|
35
|
+
def set_tag(key, value)
|
36
|
+
# Using Thrift::Tag to avoid unnecessary memory allocations
|
37
|
+
@tags << ThriftTagBuilder.build(key, value)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set a baggage item on the span
|
41
|
+
#
|
42
|
+
# @param key [String] the key of the baggage item
|
43
|
+
# @param value [String] the value of the baggage item
|
44
|
+
def set_baggage_item(key, value)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get a baggage item
|
49
|
+
#
|
50
|
+
# @param key [String] the key of the baggage item
|
51
|
+
#
|
52
|
+
# @return Value of the baggage item
|
53
|
+
def get_baggage_item(key)
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
# Add a log entry to this span
|
58
|
+
#
|
59
|
+
# @deprecated Use {#log_kv} instead.
|
60
|
+
def log(*args)
|
61
|
+
warn 'Span#log is deprecated. Please use Span#log_kv instead.'
|
62
|
+
log_kv(*args)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Add a log entry to this span
|
66
|
+
#
|
67
|
+
# @param timestamp [Time] time of the log
|
68
|
+
# @param fields [Hash] Additional information to log
|
69
|
+
def log_kv(timestamp: Time.now, **fields)
|
70
|
+
# Using Thrift::Log to avoid unnecessary memory allocations
|
71
|
+
@logs << ThriftLogBuilder.build(timestamp, fields)
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# Finish the {Span}
|
76
|
+
#
|
77
|
+
# @param end_time [Time] custom end time, if not now
|
78
|
+
def finish(end_time: Time.now)
|
79
|
+
@collector.send_span(self, end_time)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jaeger
|
4
|
+
module Client
|
5
|
+
# SpanContext holds the data for a span that gets inherited to child spans
|
6
|
+
class SpanContext
|
7
|
+
MAX_SIGNED_ID = (1 << 63) - 1
|
8
|
+
MAX_UNSIGNED_ID = (1 << 64)
|
9
|
+
ID_ATTRIBUTES = %i[span_id parent_id trace_id].freeze
|
10
|
+
|
11
|
+
module Flags
|
12
|
+
NONE = 0x00
|
13
|
+
SAMPLED = 0x01
|
14
|
+
DEBUG = 0x02
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create_parent_context(sampler = Samplers::Const.new(true))
|
18
|
+
trace_id = TraceId.generate
|
19
|
+
span_id = TraceId.generate
|
20
|
+
flags = sampler.sample?(trace_id) ? Flags::SAMPLED : Flags::NONE
|
21
|
+
new(trace_id: trace_id, span_id: span_id, flags: flags)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.create_from_parent_context(span_context)
|
25
|
+
trace_id = span_context.trace_id
|
26
|
+
parent_id = span_context.span_id
|
27
|
+
flags = span_context.flags
|
28
|
+
span_id = TraceId.generate
|
29
|
+
new(span_id: span_id, parent_id: parent_id, trace_id: trace_id, flags: flags)
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :baggage, :flags, *ID_ATTRIBUTES
|
33
|
+
|
34
|
+
ID_ATTRIBUTES.each do |attribute|
|
35
|
+
define_method "thrift_#{attribute}" do
|
36
|
+
id_to_thrift_int(public_send(attribute))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(span_id:, parent_id: 0, trace_id:, flags:, baggage: {})
|
41
|
+
@span_id = span_id
|
42
|
+
@parent_id = parent_id
|
43
|
+
@trace_id = trace_id
|
44
|
+
@baggage = baggage
|
45
|
+
@flags = flags
|
46
|
+
end
|
47
|
+
|
48
|
+
def sampled?
|
49
|
+
@flags & Flags::SAMPLED == Flags::SAMPLED
|
50
|
+
end
|
51
|
+
|
52
|
+
def debug?
|
53
|
+
@flags & Flags::DEBUG == Flags::DEBUG
|
54
|
+
end
|
55
|
+
|
56
|
+
def inspect
|
57
|
+
to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
"#<SpanContext @span_id=#{span_id.to_s(16)} " \
|
62
|
+
"@parent_id=#{parent_id.to_s(16)} " \
|
63
|
+
"@trace_id=#{trace_id.to_s(16)} " \
|
64
|
+
"@flags=#{flags}>"
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def id_to_thrift_int(id)
|
70
|
+
return unless id
|
71
|
+
|
72
|
+
puts id
|
73
|
+
id -= MAX_UNSIGNED_ID if id > MAX_SIGNED_ID
|
74
|
+
id
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jaeger
|
4
|
+
module Client
|
5
|
+
class Tracer
|
6
|
+
def initialize(collector, sender, sampler)
|
7
|
+
@collector = collector
|
8
|
+
@sender = sender
|
9
|
+
@sampler = sampler
|
10
|
+
@scope_manager = ScopeManager.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop
|
14
|
+
@sender.stop
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [ScopeManager] the current ScopeManager, which may be a no-op
|
18
|
+
# but may not be nil.
|
19
|
+
attr_reader :scope_manager
|
20
|
+
|
21
|
+
# @return [Span, nil] the active span. This is a shorthand for
|
22
|
+
# `scope_manager.active.span`, and nil will be returned if
|
23
|
+
# Scope#active is nil.
|
24
|
+
def active_span
|
25
|
+
scope = scope_manager.active
|
26
|
+
scope.span if scope
|
27
|
+
end
|
28
|
+
|
29
|
+
# Starts a new span.
|
30
|
+
#
|
31
|
+
# This is similar to #start_active_span, but the returned Span will not
|
32
|
+
# be registered via the ScopeManager.
|
33
|
+
#
|
34
|
+
# @param operation_name [String] The operation name for the Span
|
35
|
+
# @param child_of [SpanContext, Span] SpanContext that acts as a parent to
|
36
|
+
# the newly-started Span. If a Span instance is provided, its
|
37
|
+
# context is automatically substituted. See [Reference] for more
|
38
|
+
# information.
|
39
|
+
#
|
40
|
+
# If specified, the `references` parameter must be omitted.
|
41
|
+
# @param references [Array<Reference>] An array of reference
|
42
|
+
# objects that identify one or more parent SpanContexts.
|
43
|
+
# @param start_time [Time] When the Span started, if not now
|
44
|
+
# @param tags [Hash] Tags to assign to the Span at start time
|
45
|
+
# @param ignore_active_scope [Boolean] whether to create an implicit
|
46
|
+
# References#CHILD_OF reference to the ScopeManager#active.
|
47
|
+
#
|
48
|
+
# @return [Span] The newly-started Span
|
49
|
+
def start_span(operation_name,
|
50
|
+
child_of: nil,
|
51
|
+
references: nil,
|
52
|
+
start_time: Time.now,
|
53
|
+
tags: {},
|
54
|
+
ignore_active_scope: false,
|
55
|
+
**)
|
56
|
+
context = prepare_span_context(
|
57
|
+
child_of: child_of,
|
58
|
+
references: references,
|
59
|
+
ignore_active_scope: ignore_active_scope
|
60
|
+
)
|
61
|
+
Span.new(
|
62
|
+
context,
|
63
|
+
operation_name,
|
64
|
+
@collector,
|
65
|
+
start_time: start_time,
|
66
|
+
references: references,
|
67
|
+
tags: tags.merge(
|
68
|
+
:'sampler.type' => @sampler.type,
|
69
|
+
:'sampler.param' => @sampler.param
|
70
|
+
)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Creates a newly started and activated Scope
|
75
|
+
#
|
76
|
+
# If the Tracer's ScopeManager#active is not nil, no explicit references
|
77
|
+
# are provided, and `ignore_active_scope` is false, then an inferred
|
78
|
+
# References#CHILD_OF reference is created to the ScopeManager#active's
|
79
|
+
# SpanContext when start_active is invoked.
|
80
|
+
#
|
81
|
+
# @param operation_name [String] The operation name for the Span
|
82
|
+
# @param child_of [SpanContext, Span] SpanContext that acts as a parent to
|
83
|
+
# the newly-started Span. If a Span instance is provided, its
|
84
|
+
# context is automatically substituted. See [Reference] for more
|
85
|
+
# information.
|
86
|
+
#
|
87
|
+
# If specified, the `references` parameter must be omitted.
|
88
|
+
# @param references [Array<Reference>] An array of reference
|
89
|
+
# objects that identify one or more parent SpanContexts.
|
90
|
+
# @param start_time [Time] When the Span started, if not now
|
91
|
+
# @param tags [Hash] Tags to assign to the Span at start time
|
92
|
+
# @param ignore_active_scope [Boolean] whether to create an implicit
|
93
|
+
# References#CHILD_OF reference to the ScopeManager#active.
|
94
|
+
# @param finish_on_close [Boolean] whether span should automatically be
|
95
|
+
# finished when Scope#close is called
|
96
|
+
# @yield [Scope] If an optional block is passed to start_active it will
|
97
|
+
# yield the newly-started Scope. If `finish_on_close` is true then the
|
98
|
+
# Span will be finished automatically after the block is executed.
|
99
|
+
# @return [Scope] The newly-started and activated Scope
|
100
|
+
def start_active_span(operation_name,
|
101
|
+
child_of: nil,
|
102
|
+
references: nil,
|
103
|
+
start_time: Time.now,
|
104
|
+
tags: {},
|
105
|
+
ignore_active_scope: false,
|
106
|
+
finish_on_close: true,
|
107
|
+
**)
|
108
|
+
span = start_span(
|
109
|
+
operation_name,
|
110
|
+
child_of: child_of,
|
111
|
+
references: references,
|
112
|
+
start_time: start_time,
|
113
|
+
tags: tags,
|
114
|
+
ignore_active_scope: ignore_active_scope
|
115
|
+
)
|
116
|
+
scope = @scope_manager.activate(span, finish_on_close: finish_on_close)
|
117
|
+
|
118
|
+
if block_given?
|
119
|
+
begin
|
120
|
+
yield scope
|
121
|
+
ensure
|
122
|
+
scope.close
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
scope
|
127
|
+
end
|
128
|
+
|
129
|
+
# Inject a SpanContext into the given carrier
|
130
|
+
#
|
131
|
+
# @param span_context [SpanContext]
|
132
|
+
# @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
|
133
|
+
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
134
|
+
def inject(span_context, format, carrier)
|
135
|
+
case format
|
136
|
+
when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_RACK
|
137
|
+
carrier['uber-trace-id'] = [
|
138
|
+
span_context.trace_id.to_s(16),
|
139
|
+
span_context.span_id.to_s(16),
|
140
|
+
span_context.parent_id.to_s(16),
|
141
|
+
span_context.flags.to_s(16)
|
142
|
+
].join(':')
|
143
|
+
else
|
144
|
+
warn "Jaeger::Client with format #{format} is not supported yet"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Extract a SpanContext in the given format from the given carrier.
|
149
|
+
#
|
150
|
+
# @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
|
151
|
+
# @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
|
152
|
+
# @return [SpanContext] the extracted SpanContext or nil if none could be found
|
153
|
+
def extract(format, carrier)
|
154
|
+
case format
|
155
|
+
when OpenTracing::FORMAT_TEXT_MAP
|
156
|
+
parse_context(carrier['uber-trace-id'])
|
157
|
+
when OpenTracing::FORMAT_RACK
|
158
|
+
parse_context(carrier['HTTP_UBER_TRACE_ID'])
|
159
|
+
else
|
160
|
+
warn "Jaeger::Client with format #{format} is not supported yet"
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def parse_context(trace)
|
168
|
+
return nil if !trace || trace == ''
|
169
|
+
|
170
|
+
trace_arguments = trace.split(':').map { |arg| arg.to_i(16) }
|
171
|
+
return nil if trace_arguments.size != 4
|
172
|
+
|
173
|
+
trace_id, span_id, parent_id, flags = trace_arguments
|
174
|
+
return nil if trace_id.zero? || span_id.zero?
|
175
|
+
|
176
|
+
SpanContext.new(
|
177
|
+
trace_id: trace_id,
|
178
|
+
parent_id: parent_id,
|
179
|
+
span_id: span_id,
|
180
|
+
flags: flags
|
181
|
+
)
|
182
|
+
end
|
183
|
+
|
184
|
+
def prepare_span_context(child_of:, references:, ignore_active_scope:)
|
185
|
+
context =
|
186
|
+
context_from_child_of(child_of) ||
|
187
|
+
context_from_references(references) ||
|
188
|
+
context_from_active_scope(ignore_active_scope)
|
189
|
+
|
190
|
+
if context
|
191
|
+
SpanContext.create_from_parent_context(context)
|
192
|
+
else
|
193
|
+
SpanContext.create_parent_context(@sampler)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def context_from_child_of(child_of)
|
198
|
+
return nil unless child_of
|
199
|
+
child_of.respond_to?(:context) ? child_of.context : child_of
|
200
|
+
end
|
201
|
+
|
202
|
+
def context_from_references(references)
|
203
|
+
return nil if !references || references.none?
|
204
|
+
|
205
|
+
# Prefer CHILD_OF reference if present
|
206
|
+
ref = references.detect do |reference|
|
207
|
+
reference.type == OpenTracing::Reference::CHILD_OF
|
208
|
+
end
|
209
|
+
(ref || references[0]).context
|
210
|
+
end
|
211
|
+
|
212
|
+
def context_from_active_scope(ignore_active_scope)
|
213
|
+
return if ignore_active_scope
|
214
|
+
|
215
|
+
active_scope = @scope_manager.active
|
216
|
+
active_scope.span.context if active_scope
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jaeger
|
4
|
+
module Client
|
5
|
+
class UdpSender
|
6
|
+
class Transport
|
7
|
+
FLAGS = 0
|
8
|
+
|
9
|
+
def initialize(host, port)
|
10
|
+
@socket = UDPSocket.new
|
11
|
+
@host = host
|
12
|
+
@port = port
|
13
|
+
@buffer = ::Thrift::MemoryBufferTransport.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(str)
|
17
|
+
@buffer.write(str)
|
18
|
+
end
|
19
|
+
|
20
|
+
def flush
|
21
|
+
data = @buffer.read(@buffer.available)
|
22
|
+
send_bytes(data)
|
23
|
+
end
|
24
|
+
|
25
|
+
def open; end
|
26
|
+
|
27
|
+
def close; end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def send_bytes(bytes)
|
32
|
+
@socket.send(bytes, FLAGS, @host, @port)
|
33
|
+
@socket.flush
|
34
|
+
rescue Errno::ECONNREFUSED
|
35
|
+
warn 'Unable to connect to Jaeger Agent'
|
36
|
+
rescue StandardError => e
|
37
|
+
warn "Unable to send spans: #{e.message}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './udp_sender/transport'
|
4
|
+
require 'socket'
|
5
|
+
require 'thread'
|
6
|
+
|
7
|
+
module Jaeger
|
8
|
+
module Client
|
9
|
+
class UdpSender
|
10
|
+
def initialize(service_name:, host:, port:, collector:, flush_interval:, logger:)
|
11
|
+
@service_name = service_name
|
12
|
+
@collector = collector
|
13
|
+
@flush_interval = flush_interval
|
14
|
+
@logger = logger
|
15
|
+
|
16
|
+
@tags = [
|
17
|
+
Jaeger::Thrift::Tag.new(
|
18
|
+
'key' => 'jaeger.version',
|
19
|
+
'vType' => Jaeger::Thrift::TagType::STRING,
|
20
|
+
'vStr' => 'Ruby-' + Jaeger::Client::VERSION
|
21
|
+
),
|
22
|
+
Jaeger::Thrift::Tag.new(
|
23
|
+
'key' => 'hostname',
|
24
|
+
'vType' => Jaeger::Thrift::TagType::STRING,
|
25
|
+
'vStr' => Socket.gethostname
|
26
|
+
)
|
27
|
+
]
|
28
|
+
ipv4 = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }
|
29
|
+
unless ipv4.nil?
|
30
|
+
@tags << Jaeger::Thrift::Tag.new(
|
31
|
+
'key' => 'ip',
|
32
|
+
'vType' => Jaeger::Thrift::TagType::STRING,
|
33
|
+
'vStr' => ipv4.ip_address
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
transport = Transport.new(host, port)
|
38
|
+
protocol = ::Thrift::CompactProtocol.new(transport)
|
39
|
+
@client = Jaeger::Thrift::Agent::Client.new(protocol)
|
40
|
+
end
|
41
|
+
|
42
|
+
def start
|
43
|
+
# Sending spans in a separate thread to avoid blocking the main thread.
|
44
|
+
@thread = Thread.new do
|
45
|
+
loop do
|
46
|
+
emit_batch(@collector.retrieve)
|
47
|
+
sleep @flush_interval
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def stop
|
53
|
+
@thread.terminate if @thread
|
54
|
+
emit_batch(@collector.retrieve)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def emit_batch(thrift_spans)
|
60
|
+
return if thrift_spans.empty?
|
61
|
+
|
62
|
+
batch = Jaeger::Thrift::Batch.new(
|
63
|
+
'process' => Jaeger::Thrift::Process.new(
|
64
|
+
'serviceName' => @service_name,
|
65
|
+
'tags' => @tags
|
66
|
+
),
|
67
|
+
'spans' => thrift_spans
|
68
|
+
)
|
69
|
+
|
70
|
+
@client.emitBatch(batch)
|
71
|
+
rescue StandardError => error
|
72
|
+
log_error(error, batch)
|
73
|
+
end
|
74
|
+
|
75
|
+
def log_error(error, failed_batch)
|
76
|
+
return unless @logger
|
77
|
+
|
78
|
+
@logger.error("[jaeger-client] Failure while sending batch: #{failed_batch.inspect} with error: #{error}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push(File.dirname(__FILE__) + '/../../thrift/gen-rb')
|
4
|
+
|
5
|
+
require 'opentracing'
|
6
|
+
require 'jaeger/thrift/agent'
|
7
|
+
require 'logger'
|
8
|
+
|
9
|
+
require_relative 'client/tracer'
|
10
|
+
require_relative 'client/span'
|
11
|
+
require_relative 'client/span_context'
|
12
|
+
require_relative 'client/scope'
|
13
|
+
require_relative 'client/scope_manager'
|
14
|
+
require_relative 'client/carrier'
|
15
|
+
require_relative 'client/trace_id'
|
16
|
+
require_relative 'client/udp_sender'
|
17
|
+
require_relative 'client/collector'
|
18
|
+
require_relative 'client/version'
|
19
|
+
require_relative 'client/samplers'
|
20
|
+
|
21
|
+
module Jaeger
|
22
|
+
module Client
|
23
|
+
DEFAULT_FLUSH_INTERVAL = 10
|
24
|
+
|
25
|
+
def self.build(host: '127.0.0.1',
|
26
|
+
port: 6831,
|
27
|
+
service_name:,
|
28
|
+
flush_interval: DEFAULT_FLUSH_INTERVAL,
|
29
|
+
sampler: Samplers::Const.new(true),
|
30
|
+
logger: Logger.new(STDOUT))
|
31
|
+
collector = Collector.new
|
32
|
+
sender = UdpSender.new(
|
33
|
+
service_name: service_name,
|
34
|
+
host: host,
|
35
|
+
port: port,
|
36
|
+
collector: collector,
|
37
|
+
flush_interval: flush_interval,
|
38
|
+
logger: logger
|
39
|
+
)
|
40
|
+
sender.start
|
41
|
+
Tracer.new(collector, sender, sampler)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup
|
5
|
+
|
6
|
+
require 'jaeger/client'
|
7
|
+
|
8
|
+
host = ENV['JAEGER_HOST'] || '127.0.0.1'
|
9
|
+
port = ENV['JAEGER_HOST'] || 6831
|
10
|
+
|
11
|
+
tracer1 = Jaeger::Client.build(host: host, port: port.to_i, service_name: 'test-service', flush_interval: 1)
|
12
|
+
tracer2 = Jaeger::Client.build(host: host, port: port.to_i, service_name: 'downstream-service', flush_interval: 1)
|
13
|
+
|
14
|
+
rpc_span = tracer1.start_span(
|
15
|
+
'receive request',
|
16
|
+
tags: { 'span.kind' => 'server' }
|
17
|
+
)
|
18
|
+
sleep 0.1
|
19
|
+
rpc_span.log_kv(event: 'woop di doop', count: 5)
|
20
|
+
sleep 1
|
21
|
+
|
22
|
+
async_request_span = tracer1.start_span(
|
23
|
+
'request async action',
|
24
|
+
references: [
|
25
|
+
OpenTracing::Reference.child_of(rpc_span.context)
|
26
|
+
],
|
27
|
+
tags: { 'span.kind' => 'producer' }
|
28
|
+
)
|
29
|
+
sleep 0.1
|
30
|
+
|
31
|
+
async_request_span.finish
|
32
|
+
rpc_span.finish
|
33
|
+
|
34
|
+
sleep 0.5
|
35
|
+
|
36
|
+
async_span = tracer2.start_span(
|
37
|
+
'async span started after rpc span',
|
38
|
+
references: [
|
39
|
+
OpenTracing::Reference.follows_from(async_request_span.context)
|
40
|
+
],
|
41
|
+
tags: {
|
42
|
+
'span.kind' => 'consumer',
|
43
|
+
'peer.service' => 'downstream-service'
|
44
|
+
}
|
45
|
+
)
|
46
|
+
sleep 0.3 # emulate network delay
|
47
|
+
async_span.finish
|
48
|
+
|
49
|
+
tracer1.stop
|
50
|
+
tracer2.stop
|
51
|
+
|
52
|
+
puts 'Finished'
|
data/script/create_trace
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup
|
5
|
+
|
6
|
+
require 'jaeger/client'
|
7
|
+
|
8
|
+
host = ENV['JAEGER_HOST'] || '127.0.0.1'
|
9
|
+
port = ENV['JAEGER_HOST'] || 6831
|
10
|
+
|
11
|
+
tracer1 = Jaeger::Client.build(host: host, port: port.to_i, service_name: 'test-service', flush_interval: 1)
|
12
|
+
tracer2 = Jaeger::Client.build(host: host, port: port.to_i, service_name: 'downstream-service', flush_interval: 1)
|
13
|
+
|
14
|
+
outer_span = tracer1.start_span(
|
15
|
+
'receive request',
|
16
|
+
tags: { 'span.kind' => 'server' }
|
17
|
+
)
|
18
|
+
sleep 0.1
|
19
|
+
outer_span.log_kv(event: 'woop di doop', count: 5)
|
20
|
+
sleep 1
|
21
|
+
|
22
|
+
inner_span = tracer1.start_span(
|
23
|
+
'fetch info from downstream',
|
24
|
+
child_of: outer_span,
|
25
|
+
tags: {
|
26
|
+
'span.kind' => 'client',
|
27
|
+
'peer.service' => 'downstream-service',
|
28
|
+
'peer.ipv4' => '6.6.6.6',
|
29
|
+
'peer.port' => 443
|
30
|
+
}
|
31
|
+
)
|
32
|
+
inner_span.set_tag('error', false)
|
33
|
+
sleep 0.3 # emulate network delay
|
34
|
+
|
35
|
+
downstream_span = tracer2.start_span(
|
36
|
+
'downstream operation',
|
37
|
+
child_of: inner_span,
|
38
|
+
tags: { 'span.kind' => 'server' }
|
39
|
+
)
|
40
|
+
sleep 0.5
|
41
|
+
downstream_span.finish
|
42
|
+
|
43
|
+
sleep 0.2 # emulate network delay
|
44
|
+
|
45
|
+
inner_span.finish
|
46
|
+
|
47
|
+
sleep 0.1 # doing something with fetched info
|
48
|
+
outer_span.finish
|
49
|
+
|
50
|
+
tracer1.stop
|
51
|
+
tracer2.stop
|
52
|
+
|
53
|
+
puts 'Finished'
|