boost-jaeger-client 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +47 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +57 -0
  9. data/Rakefile +9 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/boost-jaeger-client.gemspec +31 -0
  13. data/lib/jaeger/client/carrier.rb +26 -0
  14. data/lib/jaeger/client/collector.rb +91 -0
  15. data/lib/jaeger/client/samplers/const.rb +29 -0
  16. data/lib/jaeger/client/samplers/probabilistic.rb +30 -0
  17. data/lib/jaeger/client/samplers.rb +4 -0
  18. data/lib/jaeger/client/scope.rb +40 -0
  19. data/lib/jaeger/client/scope_manager/scope_identifier.rb +15 -0
  20. data/lib/jaeger/client/scope_manager/scope_stack.rb +35 -0
  21. data/lib/jaeger/client/scope_manager.rb +49 -0
  22. data/lib/jaeger/client/span/thrift_log_builder.rb +20 -0
  23. data/lib/jaeger/client/span/thrift_tag_builder.rb +45 -0
  24. data/lib/jaeger/client/span.rb +83 -0
  25. data/lib/jaeger/client/span_context.rb +78 -0
  26. data/lib/jaeger/client/trace_id.rb +13 -0
  27. data/lib/jaeger/client/tracer.rb +220 -0
  28. data/lib/jaeger/client/udp_sender/transport.rb +42 -0
  29. data/lib/jaeger/client/udp_sender.rb +82 -0
  30. data/lib/jaeger/client/version.rb +7 -0
  31. data/lib/jaeger/client.rb +44 -0
  32. data/script/create_follows_from_trace +52 -0
  33. data/script/create_trace +53 -0
  34. data/thrift/agent.thrift +32 -0
  35. data/thrift/gen-rb/jaeger/thrift/agent/agent.rb +118 -0
  36. data/thrift/gen-rb/jaeger/thrift/agent/agent_constants.rb +15 -0
  37. data/thrift/gen-rb/jaeger/thrift/agent/agent_types.rb +17 -0
  38. data/thrift/gen-rb/jaeger/thrift/agent.rb +116 -0
  39. data/thrift/gen-rb/jaeger/thrift/agent_constants.rb +13 -0
  40. data/thrift/gen-rb/jaeger/thrift/agent_types.rb +15 -0
  41. data/thrift/gen-rb/jaeger/thrift/collector.rb +82 -0
  42. data/thrift/gen-rb/jaeger/thrift/jaeger_constants.rb +13 -0
  43. data/thrift/gen-rb/jaeger/thrift/jaeger_types.rb +211 -0
  44. data/thrift/gen-rb/jaeger/thrift/zipkin/zipkin_collector.rb +84 -0
  45. data/thrift/gen-rb/jaeger/thrift/zipkin/zipkincore_constants.rb +41 -0
  46. data/thrift/gen-rb/jaeger/thrift/zipkin/zipkincore_types.rb +220 -0
  47. data/thrift/jaeger.thrift +88 -0
  48. data/thrift/zipkincore.thrift +300 -0
  49. 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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module TraceId
6
+ TRACE_ID_UPPER_BOUND = 2**64 - 1
7
+
8
+ def self.generate
9
+ rand(TRACE_ID_UPPER_BOUND)
10
+ end
11
+ end
12
+ end
13
+ 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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ VERSION = '0.7.0'.freeze
6
+ end
7
+ 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'
@@ -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'