jaeger-client 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 569f7aab000d228eac45be1f7d5831251b886ea0372c83f26d6eee58cb4aebbc
4
- data.tar.gz: ce36d49763c06f2fbad18d69587c1c66c9f047bcdc24bcbdb7c1b7bc99fdb803
3
+ metadata.gz: 8f0b04e0c6c305df9d1f5ec5c0b76ad40c60a5e8b27c5475b29e414ade9ef59b
4
+ data.tar.gz: 672aa006cb7ad30269615cda53b05eed141205689d37b472b0acdc91b257d074
5
5
  SHA512:
6
- metadata.gz: 7c1e3bf462504c1f0b83dfe460d3001dcb45fb8dece53245f6b9d25a3065332f6a16bba3a425ffe34d74bef5ab0d67d5cd7caaafc36d9b930eab067040c88dbf
7
- data.tar.gz: 0f9c0a1c60ccb748c3f50a63e01f28d2756f8485f35b4aa111544e596f19685f2200f0446962c56b17d2273c976f638ec7c00764fccd88fbbb73c5814dd8cee8
6
+ metadata.gz: 188e7434f62b4023b9a4d03ec1c18589c6d9b3a79810a2a000b6ef987b8532d1e5ec9f7d0e21ba2383b197b3f1bd6064c602839e49d185b3241365a664a7a5f2
7
+ data.tar.gz: 6335ba661fbfbd92ee543ba30d794fe9cffa4a7b30c36e300a63f48331bbcc81b33a5f2585ebe266f51faefddd3600d481f9a0326b6c5740e0fe95bf34b01cf5
data/.rubocop.yml CHANGED
@@ -19,6 +19,9 @@ RSpec/ExampleLength:
19
19
  RSpec/MultipleExpectations:
20
20
  Enabled: no
21
21
 
22
+ RSpec/MessageSpies:
23
+ Enabled: no
24
+
22
25
  Metrics/BlockLength:
23
26
  Enabled: no
24
27
 
data/README.md CHANGED
@@ -28,6 +28,18 @@ OpenTracing.start_active_span('span name') do
28
28
  end
29
29
  ```
30
30
 
31
+ The tracer can also take an externally configured sender. For example, the `HttpSender` can be configured with a different endpoint and headers for authentication.
32
+ ```ruby
33
+ require 'jaeger/client'
34
+ require 'jaeger/client/http_sender'
35
+
36
+ headers = { "auth_token" => token }
37
+ encoder = Jaeger::Client::Encoders::ThriftEncoder.new(service_name: "service_name")
38
+ sender = Jaeger::Client::HttpSender.new(url: "http://localhost:14268/api/traces", headers: headers, encoder: encoder)
39
+
40
+ OpenTracing.global_tracer = Jaeger::Client.build(service_name: "service_name", sender: sender)
41
+ ```
42
+
31
43
  See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more examples.
32
44
 
33
45
  ### Samplers
@@ -40,6 +52,28 @@ See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more
40
52
 
41
53
  `Probabilistic` sampler samples traces with probability equal to `rate` (must be between 0.0 and 1.0). This can be enabled by setting `Jaeger::Client::Samplers::Probabilistic.new(rate: 0.1)`
42
54
 
55
+ ### Zipkin HTTP B3 compatible header propagation
56
+
57
+ Jaeger Tracer supports Zipkin B3 Propagation HTTP headers, which are used by a lot of Zipkin tracers. This means that you can use Jaeger in conjunction with OpenZipkin tracers.
58
+
59
+ To set it up you need to change FORMAT_RACK injector and extractor.
60
+
61
+ ```
62
+ OpenTracing.global_tracer = Jaeger::Client.build(
63
+ service_name: 'service_name',
64
+ injectors: {
65
+ OpenTracing::FORMAT_RACK => [Jaeger::Client::Injectors::B3RackCodec]
66
+ },
67
+ extractors: {
68
+ OpenTracing::FORMAT_RACK => [Jaeger::Client::Extractors::B3RackCodec]
69
+ }
70
+ )
71
+ ```
72
+
73
+ It's also possible to set up multiple injectors and extractors. Each injector will be called in sequence. Note that if multiple injectors are using the same keys then the values will be overwritten.
74
+
75
+ If multiple extractors is used then the span context from the first match will be returned.
76
+
43
77
  ## Development
44
78
 
45
79
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/lib/jaeger/client.rb CHANGED
@@ -14,9 +14,12 @@ require_relative 'client/scope_manager'
14
14
  require_relative 'client/carrier'
15
15
  require_relative 'client/trace_id'
16
16
  require_relative 'client/udp_sender'
17
- require_relative 'client/collector'
17
+ require_relative 'client/async_reporter'
18
18
  require_relative 'client/version'
19
19
  require_relative 'client/samplers'
20
+ require_relative 'client/encoders/thrift_encoder'
21
+ require_relative 'client/injectors'
22
+ require_relative 'client/extractors'
20
23
 
21
24
  module Jaeger
22
25
  module Client
@@ -27,18 +30,24 @@ module Jaeger
27
30
  service_name:,
28
31
  flush_interval: DEFAULT_FLUSH_INTERVAL,
29
32
  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
33
+ logger: Logger.new(STDOUT),
34
+ sender: nil,
35
+ injectors: {},
36
+ extractors: {})
37
+ encoder = Encoders::ThriftEncoder.new(service_name: service_name)
38
+
39
+ if sender.nil?
40
+ sender = UdpSender.new(host: host, port: port, encoder: encoder, logger: logger)
41
+ end
42
+
43
+ reporter = AsyncReporter.create(sender: sender, flush_interval: flush_interval)
44
+
45
+ Tracer.new(
46
+ reporter: reporter,
47
+ sampler: sampler,
48
+ injectors: Injectors.prepare(injectors),
49
+ extractors: Extractors.prepare(extractors)
39
50
  )
40
- sender.start
41
- Tracer.new(collector, sender, sampler)
42
51
  end
43
52
  end
44
53
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thread'
4
+
5
+ require_relative './async_reporter/buffer'
6
+
7
+ module Jaeger
8
+ module Client
9
+ class AsyncReporter
10
+ def self.create(sender:, flush_interval:)
11
+ reporter = new(sender)
12
+
13
+ # start flush thread
14
+ Thread.new do
15
+ loop do
16
+ reporter.flush
17
+ sleep(flush_interval)
18
+ end
19
+ end
20
+
21
+ reporter
22
+ end
23
+
24
+ def initialize(sender)
25
+ @sender = sender
26
+ @buffer = Buffer.new
27
+ end
28
+
29
+ def flush
30
+ spans = @buffer.retrieve
31
+ @sender.send_spans(spans) if spans.any?
32
+ spans
33
+ end
34
+
35
+ def report(span)
36
+ return if !span.context.sampled? && !span.context.debug?
37
+ @buffer << span
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ class AsyncReporter
6
+ class Buffer
7
+ def initialize
8
+ @buffer = []
9
+ @mutex = Mutex.new
10
+ end
11
+
12
+ def <<(element)
13
+ @mutex.synchronize do
14
+ @buffer << element
15
+ true
16
+ end
17
+ end
18
+
19
+ def retrieve
20
+ @mutex.synchronize do
21
+ elements = @buffer.dup
22
+ @buffer.clear
23
+ elements
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Encoders
6
+ class ThriftEncoder
7
+ def initialize(service_name:)
8
+ @service_name = service_name
9
+ @tags = [
10
+ Jaeger::Thrift::Tag.new(
11
+ 'key' => 'jaeger.version',
12
+ 'vType' => Jaeger::Thrift::TagType::STRING,
13
+ 'vStr' => 'Ruby-' + Jaeger::Client::VERSION
14
+ ),
15
+ Jaeger::Thrift::Tag.new(
16
+ 'key' => 'hostname',
17
+ 'vType' => Jaeger::Thrift::TagType::STRING,
18
+ 'vStr' => Socket.gethostname
19
+ )
20
+ ]
21
+ ipv4 = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }
22
+ unless ipv4.nil? # rubocop:disable Style/GuardClause
23
+ @tags << Jaeger::Thrift::Tag.new(
24
+ 'key' => 'ip',
25
+ 'vType' => Jaeger::Thrift::TagType::STRING,
26
+ 'vStr' => ipv4.ip_address
27
+ )
28
+ end
29
+ end
30
+
31
+ def encode(spans)
32
+ Jaeger::Thrift::Batch.new(
33
+ 'process' => Jaeger::Thrift::Process.new(
34
+ 'serviceName' => @service_name,
35
+ 'tags' => @tags
36
+ ),
37
+ 'spans' => spans.map(&method(:encode_span))
38
+ )
39
+ end
40
+
41
+ private
42
+
43
+ def encode_span(span)
44
+ context = span.context
45
+ start_ts, duration = build_timestamps(span)
46
+
47
+ Jaeger::Thrift::Span.new(
48
+ 'traceIdLow' => TraceId.uint64_id_to_int64(context.trace_id),
49
+ 'traceIdHigh' => 0,
50
+ 'spanId' => TraceId.uint64_id_to_int64(context.span_id),
51
+ 'parentSpanId' => TraceId.uint64_id_to_int64(context.parent_id),
52
+ 'operationName' => span.operation_name,
53
+ 'references' => build_references(span.references || []),
54
+ 'flags' => context.flags,
55
+ 'startTime' => start_ts,
56
+ 'duration' => duration,
57
+ 'tags' => span.tags,
58
+ 'logs' => span.logs
59
+ )
60
+ end
61
+
62
+ def build_references(references)
63
+ references.map do |ref|
64
+ Jaeger::Thrift::SpanRef.new(
65
+ 'refType' => span_ref_type(ref.type),
66
+ 'traceIdLow' => ref.context.trace_id,
67
+ 'traceIdHigh' => 0,
68
+ 'spanId' => ref.context.span_id
69
+ )
70
+ end
71
+ end
72
+
73
+ def build_timestamps(span)
74
+ start_ts = (span.start_time.to_f * 1_000_000).to_i
75
+ end_ts = (span.end_time.to_f * 1_000_000).to_i
76
+ duration = end_ts - start_ts
77
+ [start_ts, duration]
78
+ end
79
+
80
+ def span_ref_type(type)
81
+ case type
82
+ when OpenTracing::Reference::CHILD_OF
83
+ Jaeger::Thrift::SpanRefType::CHILD_OF
84
+ when OpenTracing::Reference::FOLLOWS_FROM
85
+ Jaeger::Thrift::SpanRefType::FOLLOWS_FROM
86
+ else
87
+ warn "Jaeger::Client with format #{type} is not supported yet"
88
+ nil
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Extractors
6
+ class SerializedJaegerTrace
7
+ def self.parse(trace)
8
+ return nil if !trace || trace == ''
9
+
10
+ trace_arguments = trace.split(':').map(&TraceId.method(:base16_hex_id_to_uint64))
11
+ return nil if trace_arguments.size != 4
12
+
13
+ trace_id, span_id, parent_id, flags = trace_arguments
14
+ return nil if trace_id.zero? || span_id.zero?
15
+
16
+ SpanContext.new(
17
+ trace_id: trace_id,
18
+ parent_id: parent_id,
19
+ span_id: span_id,
20
+ flags: flags
21
+ )
22
+ end
23
+ end
24
+
25
+ class JaegerTextMapCodec
26
+ def self.extract(carrier)
27
+ SerializedJaegerTrace.parse(carrier['uber-trace-id'])
28
+ end
29
+ end
30
+
31
+ class JaegerRackCodec
32
+ def self.extract(carrier)
33
+ SerializedJaegerTrace.parse(carrier['HTTP_UBER_TRACE_ID'])
34
+ end
35
+ end
36
+
37
+ class JaegerBinaryCodec
38
+ def self.extract(_carrier)
39
+ warn 'Jaeger::Client with binary format is not supported yet'
40
+ end
41
+ end
42
+
43
+ class B3RackCodec
44
+ def self.extract(carrier)
45
+ trace_id = TraceId.base16_hex_id_to_uint64(carrier['HTTP_X_B3_TRACEID'])
46
+ span_id = TraceId.base16_hex_id_to_uint64(carrier['HTTP_X_B3_SPANID'])
47
+ parent_id = TraceId.base16_hex_id_to_uint64(carrier['HTTP_X_B3_PARENTSPANID'])
48
+ flags = parse_flags(carrier['HTTP_X_B3_FLAGS'], carrier['HTTP_X_B3_SAMPLED'])
49
+
50
+ return nil if span_id.nil? || trace_id.nil?
51
+ return nil if span_id.zero? || trace_id.zero?
52
+
53
+ SpanContext.new(
54
+ trace_id: trace_id,
55
+ parent_id: parent_id,
56
+ span_id: span_id,
57
+ flags: flags
58
+ )
59
+ end
60
+
61
+ # if the flags header is '1' then the sampled header should not be present
62
+ def self.parse_flags(flags_header, sampled_header)
63
+ if flags_header == '1'
64
+ Jaeger::Client::SpanContext::Flags::DEBUG
65
+ else
66
+ TraceId.base16_hex_id_to_uint64(sampled_header)
67
+ end
68
+ end
69
+ private_class_method :parse_flags
70
+ end
71
+
72
+ DEFAULT_EXTRACTORS = {
73
+ OpenTracing::FORMAT_TEXT_MAP => JaegerTextMapCodec,
74
+ OpenTracing::FORMAT_BINARY => JaegerBinaryCodec,
75
+ OpenTracing::FORMAT_RACK => JaegerRackCodec
76
+ }.freeze
77
+
78
+ def self.prepare(extractors)
79
+ DEFAULT_EXTRACTORS.reduce(extractors) do |acc, (format, default)|
80
+ provided_extractors = Array(extractors[format])
81
+ provided_extractors += [default] if provided_extractors.empty?
82
+
83
+ acc.merge(format => provided_extractors)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module Jaeger
6
+ module Client
7
+ class HttpSender
8
+ def initialize(url:, headers: {}, encoder:, logger: Logger.new(STDOUT))
9
+ @encoder = encoder
10
+ @logger = logger
11
+
12
+ @uri = URI(url)
13
+ @uri.query = 'format=jaeger.thrift'
14
+
15
+ @transport = ::Thrift::HTTPClientTransport.new(@uri.to_s)
16
+ @transport.add_headers(headers)
17
+
18
+ @serializer = ::Thrift::Serializer.new
19
+ end
20
+
21
+ def send_spans(spans)
22
+ batch = @encoder.encode(spans)
23
+ @transport.write(@serializer.serialize(batch))
24
+ @transport.flush
25
+ rescue StandardError => error
26
+ @logger.error("Failure while sending a batch of spans: #{error}")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Injectors
6
+ class JaegerTextMapCodec
7
+ def self.inject(span_context, carrier)
8
+ carrier['uber-trace-id'] = [
9
+ span_context.trace_id.to_s(16),
10
+ span_context.span_id.to_s(16),
11
+ span_context.parent_id.to_s(16),
12
+ span_context.flags.to_s(16)
13
+ ].join(':')
14
+ end
15
+ end
16
+
17
+ class JaegerBinaryCodec
18
+ def self.inject(_span_context, _carrier)
19
+ warn 'Jaeger::Client with binary format is not supported yet'
20
+ end
21
+ end
22
+
23
+ class B3RackCodec
24
+ def self.inject(span_context, carrier)
25
+ carrier['x-b3-traceid'] = TraceId.to_hex(span_context.trace_id)
26
+ carrier['x-b3-spanid'] = TraceId.to_hex(span_context.span_id)
27
+ carrier['x-b3-parentspanid'] = TraceId.to_hex(span_context.parent_id)
28
+
29
+ # flags (for debug) and sampled headers are mutually exclusive
30
+ if span_context.flags == Jaeger::Client::SpanContext::Flags::DEBUG
31
+ carrier['x-b3-flags'] = '1'
32
+ else
33
+ carrier['x-b3-sampled'] = span_context.flags.to_s(16)
34
+ end
35
+ end
36
+ end
37
+
38
+ DEFAULT_INJECTORS = {
39
+ OpenTracing::FORMAT_TEXT_MAP => JaegerTextMapCodec,
40
+ OpenTracing::FORMAT_BINARY => JaegerBinaryCodec,
41
+ OpenTracing::FORMAT_RACK => JaegerTextMapCodec
42
+ }.freeze
43
+
44
+ def self.prepare(extractors)
45
+ DEFAULT_INJECTORS.reduce(extractors) do |acc, (format, default)|
46
+ provided_extractors = Array(extractors[format])
47
+ provided_extractors += [default] if provided_extractors.empty?
48
+
49
+ acc.merge(format => provided_extractors)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -8,19 +8,19 @@ module Jaeger
8
8
  class Span
9
9
  attr_accessor :operation_name
10
10
 
11
- attr_reader :context, :start_time, :references, :tags, :logs
11
+ attr_reader :context, :start_time, :end_time, :references, :tags, :logs
12
12
 
13
13
  # Creates a new {Span}
14
14
  #
15
15
  # @param context [SpanContext] the context of the span
16
16
  # @param operation_name [String] the operation name
17
- # @param collector [Collector] span collector
17
+ # @param reporter [#report] span reporter
18
18
  #
19
19
  # @return [Span] a new Span
20
- def initialize(context, operation_name, collector, start_time: Time.now, references: [], tags: {})
20
+ def initialize(context, operation_name, reporter, start_time: Time.now, references: [], tags: {})
21
21
  @context = context
22
22
  @operation_name = operation_name
23
- @collector = collector
23
+ @reporter = reporter
24
24
  @start_time = start_time
25
25
  @references = references
26
26
  @tags = tags.map { |key, value| ThriftTagBuilder.build(key, value) }
@@ -76,7 +76,8 @@ module Jaeger
76
76
  #
77
77
  # @param end_time [Time] custom end time, if not now
78
78
  def finish(end_time: Time.now)
79
- @collector.send_span(self, end_time)
79
+ @end_time = end_time
80
+ @reporter.report(self)
80
81
  end
81
82
  end
82
83
  end
@@ -22,6 +22,20 @@ module Jaeger
22
22
  def self.uint64_id_to_int64(id)
23
23
  id > MAX_64BIT_SIGNED_INT ? id - MAX_64BIT_UNSIGNED_INT - 1 : id
24
24
  end
25
+
26
+ # Convert an integer id into a 0 padded hex string.
27
+ # If the string is shorter than 16 characters, it will be padded to 16.
28
+ # If it is longer than 16 characters, it is padded to 32.
29
+ def self.to_hex(id)
30
+ hex_str = id.to_s(16)
31
+
32
+ # pad the string with '0's to 16 or 32 characters
33
+ if hex_str.length > 16
34
+ hex_str.rjust(32, '0')
35
+ else
36
+ hex_str.rjust(16, '0')
37
+ end
38
+ end
25
39
  end
26
40
  end
27
41
  end
@@ -3,17 +3,14 @@
3
3
  module Jaeger
4
4
  module Client
5
5
  class Tracer
6
- def initialize(collector, sender, sampler)
7
- @collector = collector
8
- @sender = sender
6
+ def initialize(reporter:, sampler:, injectors:, extractors:)
7
+ @reporter = reporter
9
8
  @sampler = sampler
9
+ @injectors = injectors
10
+ @extractors = extractors
10
11
  @scope_manager = ScopeManager.new
11
12
  end
12
13
 
13
- def stop
14
- @sender.stop
15
- end
16
-
17
14
  # @return [ScopeManager] the current ScopeManager, which may be a no-op
18
15
  # but may not be nil.
19
16
  attr_reader :scope_manager
@@ -61,7 +58,7 @@ module Jaeger
61
58
  Span.new(
62
59
  context,
63
60
  operation_name,
64
- @collector,
61
+ @reporter,
65
62
  start_time: start_time,
66
63
  references: references,
67
64
  tags: tags.merge(
@@ -132,16 +129,8 @@ module Jaeger
132
129
  # @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
133
130
  # @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
134
131
  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"
132
+ @injectors.fetch(format).each do |injector|
133
+ injector.inject(span_context, carrier)
145
134
  end
146
135
  end
147
136
 
@@ -151,36 +140,16 @@ module Jaeger
151
140
  # @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
152
141
  # @return [SpanContext] the extracted SpanContext or nil if none could be found
153
142
  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
143
+ @extractors
144
+ .fetch(format)
145
+ .lazy
146
+ .map { |extractor| extractor.extract(carrier) }
147
+ .reject(&:nil?)
148
+ .first
163
149
  end
164
150
 
165
151
  private
166
152
 
167
- def parse_context(trace)
168
- return nil if !trace || trace == ''
169
-
170
- trace_arguments = trace.split(':').map(&TraceId.method(:base16_hex_id_to_uint64))
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
153
  def prepare_span_context(child_of:, references:, ignore_active_scope:)
185
154
  context =
186
155
  context_from_child_of(child_of) ||
@@ -7,66 +7,17 @@ require 'thread'
7
7
  module Jaeger
8
8
  module Client
9
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
10
+ def initialize(host:, port:, encoder:, logger:)
11
+ @encoder = encoder
14
12
  @logger = logger
15
13
 
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
14
  transport = Transport.new(host, port)
38
15
  protocol = ::Thrift::CompactProtocol.new(transport)
39
16
  @client = Jaeger::Thrift::Agent::Client.new(protocol)
40
17
  end
41
18
 
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
-
19
+ def send_spans(spans)
20
+ batch = @encoder.encode(spans)
70
21
  @client.emitBatch(batch)
71
22
  rescue StandardError => error
72
23
  @logger.error("Failure while sending a batch of spans: #{error}")
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jaeger
4
4
  module Client
5
- VERSION = '0.6.1'.freeze
5
+ VERSION = '0.7.0'.freeze
6
6
  end
7
7
  end
@@ -46,7 +46,6 @@ async_span = tracer2.start_span(
46
46
  sleep 0.3 # emulate network delay
47
47
  async_span.finish
48
48
 
49
- tracer1.stop
50
- tracer2.stop
49
+ sleep 2
51
50
 
52
51
  puts 'Finished'
data/script/create_trace CHANGED
@@ -47,7 +47,6 @@ inner_span.finish
47
47
  sleep 0.1 # doing something with fetched info
48
48
  outer_span.finish
49
49
 
50
- tracer1.stop
51
- tracer2.stop
50
+ sleep 2
52
51
 
53
52
  puts 'Finished'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jaeger-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SaleMove TechMovers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-22 00:00:00.000000000 Z
11
+ date: 2018-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,8 +127,13 @@ files:
127
127
  - bin/setup
128
128
  - jaeger-client.gemspec
129
129
  - lib/jaeger/client.rb
130
+ - lib/jaeger/client/async_reporter.rb
131
+ - lib/jaeger/client/async_reporter/buffer.rb
130
132
  - lib/jaeger/client/carrier.rb
131
- - lib/jaeger/client/collector.rb
133
+ - lib/jaeger/client/encoders/thrift_encoder.rb
134
+ - lib/jaeger/client/extractors.rb
135
+ - lib/jaeger/client/http_sender.rb
136
+ - lib/jaeger/client/injectors.rb
132
137
  - lib/jaeger/client/samplers.rb
133
138
  - lib/jaeger/client/samplers/const.rb
134
139
  - lib/jaeger/client/samplers/probabilistic.rb
@@ -182,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
182
187
  version: '0'
183
188
  requirements: []
184
189
  rubyforge_project:
185
- rubygems_version: 2.7.6
190
+ rubygems_version: 2.7.7
186
191
  signing_key:
187
192
  specification_version: 4
188
193
  summary: OpenTracing Tracer implementation for Jaeger in Ruby
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'thread'
4
-
5
- module Jaeger
6
- module Client
7
- class Collector
8
- def initialize
9
- @buffer = Buffer.new
10
- end
11
-
12
- def send_span(span, end_time)
13
- context = span.context
14
- start_ts, duration = build_timestamps(span, end_time)
15
- return if !context.sampled? && !context.debug?
16
-
17
- @buffer << Jaeger::Thrift::Span.new(
18
- 'traceIdLow' => TraceId.uint64_id_to_int64(context.trace_id),
19
- 'traceIdHigh' => 0,
20
- 'spanId' => TraceId.uint64_id_to_int64(context.span_id),
21
- 'parentSpanId' => TraceId.uint64_id_to_int64(context.parent_id),
22
- 'operationName' => span.operation_name,
23
- 'references' => build_references(span.references || []),
24
- 'flags' => context.flags,
25
- 'startTime' => start_ts,
26
- 'duration' => duration,
27
- 'tags' => span.tags,
28
- 'logs' => span.logs
29
- )
30
- end
31
-
32
- def retrieve
33
- @buffer.retrieve
34
- end
35
-
36
- private
37
-
38
- def build_references(references)
39
- references.map do |ref|
40
- Jaeger::Thrift::SpanRef.new(
41
- 'refType' => span_ref_type(ref.type),
42
- 'traceIdLow' => ref.context.trace_id,
43
- 'traceIdHigh' => 0,
44
- 'spanId' => ref.context.span_id
45
- )
46
- end
47
- end
48
-
49
- def build_timestamps(span, end_time)
50
- start_ts = (span.start_time.to_f * 1_000_000).to_i
51
- end_ts = (end_time.to_f * 1_000_000).to_i
52
- duration = end_ts - start_ts
53
- [start_ts, duration]
54
- end
55
-
56
- def span_ref_type(type)
57
- case type
58
- when OpenTracing::Reference::CHILD_OF
59
- Jaeger::Thrift::SpanRefType::CHILD_OF
60
- when OpenTracing::Reference::FOLLOWS_FROM
61
- Jaeger::Thrift::SpanRefType::FOLLOWS_FROM
62
- else
63
- warn "Jaeger::Client with format #{type} is not supported yet"
64
- nil
65
- end
66
- end
67
-
68
- class Buffer
69
- def initialize
70
- @buffer = []
71
- @mutex = Mutex.new
72
- end
73
-
74
- def <<(element)
75
- @mutex.synchronize do
76
- @buffer << element
77
- true
78
- end
79
- end
80
-
81
- def retrieve
82
- @mutex.synchronize do
83
- elements = @buffer.dup
84
- @buffer.clear
85
- elements
86
- end
87
- end
88
- end
89
- end
90
- end
91
- end