jaeger-client 0.8.0 → 0.9.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: 46d05119eb9543907c6e1182a80346da57b634623425a4eeb74e06d637b73799
4
- data.tar.gz: 171cdd21fd1872db8d1adef226e901dffd595ed7eab76f8c99f902363b638f9d
3
+ metadata.gz: c9af8a3a945af29ffe9f0045a2eff121fa519c689d04a680a41c7346a198cbf6
4
+ data.tar.gz: aad37d03df89f03707f91d3fd2f58b0af5b84122736b24f35edff791bb5f0b7a
5
5
  SHA512:
6
- metadata.gz: 756a18ecf9e931670df3a9058613a5af99a2391eceabfc7c7fdeea5a1371c12757f818fd71e8616d96aa3a544dc0a0cb7728d22b9f4ae7dfb62863f7f37f1c4e
7
- data.tar.gz: e89a5e9ff633cca38e030b31cd7a9df68bfa7bcbebfbd5f68ad61a663d04ade3c517465e2b8fcc707afe80696d2aad330ac51caf14a32551788b08322cd4ee4b
6
+ metadata.gz: 975e4605ee85e4e1b34b763233c16fe6ec3ec0ad88a01f8d1239b523e97bc8fde5844a2ca0d152c71a3b7f601be6237fd70303f31229cb995d896958180aaef7
7
+ data.tar.gz: 490214bc62f0a922e869b24ccbf5510538fa84365d50aafa1e892fe498aaa79e7bcb7d47da97445db8e07c4ebfb2481ecc6cb6aaeac7f81224e5a1ec90eb4616
data/README.md CHANGED
@@ -28,18 +28,56 @@ 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.
31
+ See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more examples.
32
+
33
+ ### Reporters
34
+
35
+ #### RemoteReporter (default)
36
+
37
+ RemoteReporter buffers spans in memory and sends them out of process using Sender.
38
+
39
+ There are two senders: `UdpSender` (default) and `HttpSender`.
40
+
41
+ To use `HttpSender`:
42
+
32
43
  ```ruby
33
- require 'jaeger/client'
34
- require 'jaeger/client/http_sender'
44
+ OpenTracing.global_tracer = Jaeger::Client.build(
45
+ service_name: 'service_name',
46
+ reporter: Jaeger::Client::Reporter::RemoteReporter.new(
47
+ sender: Jaeger::Client::HttpSender.new(
48
+ url: 'http://localhost:14268/api/traces',
49
+ headers: { 'key' => 'value' }, # headers key is optional
50
+ encoder: Jaeger::Client::Encoders::ThriftEncoder.new(service_name: 'service_name')
51
+ ),
52
+ flush_interval: 10
53
+ )
54
+ )
55
+ ```
56
+
57
+ #### NullReporter
35
58
 
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)
59
+ NullReporter ignores all spans.
39
60
 
40
- OpenTracing.global_tracer = Jaeger::Client.build(service_name: "service_name", sender: sender)
61
+ ```ruby
62
+ OpenTracing.global_tracer = Jaeger::Client.build(
63
+ service_name: 'service_name',
64
+ reporter: Jaeger::Client::Reporter::NullReporter.new
65
+ )
41
66
  ```
42
67
 
68
+ #### LoggingReporter
69
+
70
+ LoggingReporter prints some details about the span using `logger`. This is meant only for debugging. Do not parse and use this information for anything critical. The implemenation can change at any time.
71
+
72
+ ```ruby
73
+ OpenTracing.global_tracer = Jaeger::Client.build(
74
+ service_name: 'service_name',
75
+ reporter: Jaeger::Client::Reporter::LoggingReporter.new
76
+ )
77
+ ```
78
+
79
+ LoggingReporter can also use a custom logger. For this provide logger using `logger` keyword argument.
80
+
43
81
  See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more examples.
44
82
 
45
83
  ### Samplers
@@ -52,6 +90,37 @@ See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more
52
90
 
53
91
  `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)`
54
92
 
93
+ #### RateLimiting sampler
94
+
95
+ `RateLimiting` sampler samples at most `max_traces_per_second`. The distribution of sampled traces follows burstiness of the service, i.e. a service with uniformly distributed requests will have those requests sampled uniformly as well, but if requests are bursty, especially sub-second, then a number of sequential requests can be sampled each second.
96
+
97
+ Set `sampler` to `Jaeger::Client::Samplers::RateLimiting.new(max_traces_per_second: 100)`
98
+
99
+ #### GuaranteedThroughputProbabilistic sampler
100
+
101
+ `GuaranteedThroughputProbabilistic` is a sampler that guarantees a throughput by using a Probabilistic sampler and RateLimiting sampler The RateLimiting sampler is used to establish a lower_bound so that every operation is sampled at least once in the time interval defined by the lower_bound.
102
+
103
+ Set `sampler` to `Jaeger::Client::Samplers::GuaranteedThroughputProbabilistic.new(lower_bound: 10, rate: 0.001)`
104
+
105
+ #### PerOperation sampler
106
+
107
+ `PerOperation` sampler leverages both Probabilistic sampler and RateLimiting sampler via the GuaranteedThroughputProbabilistic sampler. This sampler keeps track of all operations and delegates calls the the respective GuaranteedThroughputProbabilistic sampler.
108
+
109
+ Set `sampler` to
110
+ ```
111
+ Jaeger::Client::Samplers::PerOperation.new(
112
+ strategies: {
113
+ per_operation_strategies: [
114
+ { operation: 'GET /articles', probabilistic_sampling: 0.5 },
115
+ { operation: 'POST /articles', probabilistic_sampling: 1.0 }
116
+ ],
117
+ default_sampling_probability: 0.001,
118
+ default_lower_bound_traces_per_second: 1.0 / (10.0 * 60.0)
119
+ },
120
+ max_operations: 1000
121
+ )
122
+ ```
123
+
55
124
  ### Zipkin HTTP B3 compatible header propagation
56
125
 
57
126
  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.
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = 'OpenTracing Tracer implementation for Jaeger in Ruby'
13
13
  spec.description = ''
14
- spec.homepage = ''
14
+ spec.homepage = 'https://github.com/salemove/jaeger-client-ruby'
15
15
  spec.license = 'MIT'
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'rspec', '~> 3.0'
26
26
  spec.add_development_dependency 'rubocop', '~> 0.54.0'
27
27
  spec.add_development_dependency 'rubocop-rspec', '~> 1.24.0'
28
+ spec.add_development_dependency 'timecop', '~> 0.9'
28
29
 
29
30
  spec.add_dependency 'opentracing', '~> 0.3'
30
31
  spec.add_dependency 'thrift'
@@ -14,12 +14,14 @@ 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/async_reporter'
17
+ require_relative 'client/http_sender'
18
+ require_relative 'client/reporters'
18
19
  require_relative 'client/version'
19
20
  require_relative 'client/samplers'
20
21
  require_relative 'client/encoders/thrift_encoder'
21
22
  require_relative 'client/injectors'
22
23
  require_relative 'client/extractors'
24
+ require_relative 'client/rate_limiter'
23
25
 
24
26
  module Jaeger
25
27
  module Client
@@ -32,15 +34,20 @@ module Jaeger
32
34
  sampler: Samplers::Const.new(true),
33
35
  logger: Logger.new(STDOUT),
34
36
  sender: nil,
37
+ reporter: nil,
35
38
  injectors: {},
36
39
  extractors: {})
37
40
  encoder = Encoders::ThriftEncoder.new(service_name: service_name)
38
41
 
39
- if sender.nil?
40
- sender = UdpSender.new(host: host, port: port, encoder: encoder, logger: logger)
42
+ if sender
43
+ warn '[DEPRECATION] Passing `sender` directly to Jaeger::Client.build is deprecated.' \
44
+ 'Please use `reporter` instead.'
41
45
  end
42
46
 
43
- reporter = AsyncReporter.create(sender: sender, flush_interval: flush_interval)
47
+ reporter ||= Reporters::RemoteReporter.new(
48
+ sender: sender || UdpSender.new(host: host, port: port, encoder: encoder, logger: logger),
49
+ flush_interval: flush_interval
50
+ )
44
51
 
45
52
  Tracer.new(
46
53
  reporter: reporter,
@@ -49,7 +49,7 @@ module Jaeger
49
49
  baggage_match = key.match(/\AHTTP_UBERCTX_(\w+)\Z/)
50
50
  if baggage_match
51
51
  key = baggage_match[1].downcase.tr('_', '-')
52
- context.set_baggage_item(key, value)
52
+ context.set_baggage_item(key, CGI.unescape(value))
53
53
  end
54
54
  end
55
55
 
@@ -26,7 +26,7 @@ module Jaeger
26
26
  carrier['uber-trace-id'] =
27
27
  CGI.escape(Injectors.context_as_jaeger_string(span_context))
28
28
  span_context.baggage.each do |key, value|
29
- carrier["uberctx-#{key}"] = value
29
+ carrier["uberctx-#{key}"] = CGI.escape(value)
30
30
  end
31
31
  end
32
32
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ # RateLimiter is based on leaky bucket algorithm, formulated in terms of a
6
+ # credits balance that is replenished every time check_credit() method is
7
+ # called (tick) by the amount proportional to the time elapsed since the
8
+ # last tick, up to the max_balance. A call to check_credit() takes a cost
9
+ # of an item we want to pay with the balance. If the balance exceeds the
10
+ # cost of the item, the item is "purchased" and the balance reduced,
11
+ # indicated by returned value of true. Otherwise the balance is unchanged
12
+ # and return false.
13
+ #
14
+ # This can be used to limit a rate of messages emitted by a service by
15
+ # instantiating the Rate Limiter with the max number of messages a service
16
+ # is allowed to emit per second, and calling check_credit(1.0) for each
17
+ # message to determine if the message is within the rate limit.
18
+ #
19
+ # It can also be used to limit the rate of traffic in bytes, by setting
20
+ # credits_per_second to desired throughput as bytes/second, and calling
21
+ # check_credit() with the actual message size.
22
+ class RateLimiter
23
+ def initialize(credits_per_second:, max_balance:)
24
+ @credits_per_second = credits_per_second
25
+ @max_balance = max_balance
26
+ @balance = max_balance
27
+ @last_tick = Time.now
28
+ end
29
+
30
+ def check_credit(item_cost)
31
+ update_balance
32
+
33
+ return false if @balance < item_cost
34
+
35
+ @balance -= item_cost
36
+ true
37
+ end
38
+
39
+ def update(credits_per_second:, max_balance:)
40
+ update_balance
41
+
42
+ @credits_per_second = credits_per_second
43
+
44
+ # The new balance should be proportional to the old balance
45
+ @balance = max_balance * @balance / @max_balance
46
+ @max_balance = max_balance
47
+ end
48
+
49
+ private
50
+
51
+ def update_balance
52
+ current_time = Time.now
53
+ elapsed_time = current_time - @last_tick
54
+ @last_tick = current_time
55
+
56
+ @balance += elapsed_time * @credits_per_second
57
+ return if @balance <= @max_balance
58
+
59
+ @balance = @max_balance
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'reporters/composite_reporter'
4
+ require_relative 'reporters/in_memory_reporter'
5
+ require_relative 'reporters/logging_reporter'
6
+ require_relative 'reporters/null_reporter'
7
+ require_relative 'reporters/remote_reporter'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Reporters
6
+ class CompositeReporter
7
+ def initialize(reporters:)
8
+ @reporters = reporters
9
+ end
10
+
11
+ def report(span)
12
+ @reporters.each do |reporter|
13
+ reporter.report(span)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,25 +2,28 @@
2
2
 
3
3
  module Jaeger
4
4
  module Client
5
- class AsyncReporter
6
- class Buffer
5
+ module Reporters
6
+ class InMemoryReporter
7
7
  def initialize
8
- @buffer = []
8
+ @spans = []
9
9
  @mutex = Mutex.new
10
10
  end
11
11
 
12
- def <<(element)
12
+ def report(span)
13
13
  @mutex.synchronize do
14
- @buffer << element
15
- true
14
+ @spans << span
16
15
  end
17
16
  end
18
17
 
19
- def retrieve
18
+ def spans
20
19
  @mutex.synchronize do
21
- elements = @buffer.dup
22
- @buffer.clear
23
- elements
20
+ @spans
21
+ end
22
+ end
23
+
24
+ def clear
25
+ @mutex.synchronize do
26
+ @spans.clear
24
27
  end
25
28
  end
26
29
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Reporters
6
+ class LoggingReporter
7
+ def initialize(logger: Logger.new($stdout))
8
+ @logger = logger
9
+ end
10
+
11
+ def report(span)
12
+ span_info = {
13
+ operation_name: span.operation_name,
14
+ start_time: span.start_time.iso8601,
15
+ end_time: span.end_time.iso8601,
16
+ trace_id: span.context.to_trace_id,
17
+ span_id: span.context.to_span_id
18
+ }
19
+ @logger.info "Span reported: #{span_info}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Reporters
6
+ class NullReporter
7
+ def report(_span)
8
+ # no-op
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './remote_reporter/buffer'
4
+
5
+ module Jaeger
6
+ module Client
7
+ module Reporters
8
+ class RemoteReporter
9
+ def initialize(sender:, flush_interval:)
10
+ @sender = sender
11
+ @flush_interval = flush_interval
12
+ @buffer = Buffer.new
13
+ end
14
+
15
+ def flush
16
+ spans = @buffer.retrieve
17
+ @sender.send_spans(spans) if spans.any?
18
+ spans
19
+ end
20
+
21
+ def report(span)
22
+ return if !span.context.sampled? && !span.context.debug?
23
+
24
+ init_reporter_thread
25
+ @buffer << span
26
+ end
27
+
28
+ private
29
+
30
+ def init_reporter_thread
31
+ return if @initializer_pid == Process.pid
32
+
33
+ @initializer_pid = Process.pid
34
+ Thread.new do
35
+ loop do
36
+ flush
37
+ sleep(@flush_interval)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Reporters
6
+ class RemoteReporter
7
+ class Buffer
8
+ def initialize
9
+ @buffer = []
10
+ @mutex = Mutex.new
11
+ end
12
+
13
+ def <<(element)
14
+ @mutex.synchronize do
15
+ @buffer << element
16
+ true
17
+ end
18
+ end
19
+
20
+ def retrieve
21
+ @mutex.synchronize do
22
+ elements = @buffer.dup
23
+ @buffer.clear
24
+ elements
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'samplers/const'
4
+ require_relative 'samplers/guaranteed_throughput_probabilistic'
5
+ require_relative 'samplers/per_operation'
4
6
  require_relative 'samplers/probabilistic'
7
+ require_relative 'samplers/rate_limiting'
@@ -11,18 +11,15 @@ module Jaeger
11
11
  class Const
12
12
  def initialize(decision)
13
13
  @decision = decision
14
- @param = decision ? '1' : '0'
14
+ @tags = {
15
+ 'sampler.type' => 'const',
16
+ 'sampler.param' => @decision ? 1 : 0
17
+ }
15
18
  end
16
19
 
17
20
  def sample?(*)
18
- @decision
21
+ [@decision, @tags]
19
22
  end
20
-
21
- def type
22
- 'const'
23
- end
24
-
25
- attr_reader :param
26
23
  end
27
24
  end
28
25
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Samplers
6
+ # A sampler that leverages both Probabilistic sampler and RateLimiting
7
+ # sampler. The RateLimiting is used as a guaranteed lower bound sampler
8
+ # such that every operation is sampled at least once in a time interval
9
+ # defined by the lower_bound. ie a lower_bound of 1.0 / (60 * 10) will
10
+ # sample an operation at least once every 10 minutes.
11
+ #
12
+ # The Probabilistic sampler is given higher priority when tags are
13
+ # emitted, ie. if is_sampled() for both samplers return true, the tags
14
+ # for Probabilistic sampler will be used.
15
+ class GuaranteedThroughputProbabilistic
16
+ attr_reader :tags
17
+
18
+ def initialize(lower_bound:, rate:, lower_bound_sampler: nil)
19
+ @probabilistic_sampler = Probabilistic.new(rate: rate)
20
+ @lower_bound_sampler = lower_bound_sampler || RateLimiting.new(max_traces_per_second: lower_bound)
21
+ @lower_bound_tags = {
22
+ 'sampler.type' => 'lowerbound',
23
+ 'sampler.param' => lower_bound
24
+ }
25
+ end
26
+
27
+ def sample?(*args)
28
+ is_sampled, probabilistic_tags = @probabilistic_sampler.sample?(*args)
29
+ if is_sampled
30
+ # We still call lower_bound_sampler to update the rate limiter budget
31
+ @lower_bound_sampler.sample?(*args)
32
+
33
+ return [is_sampled, probabilistic_tags]
34
+ end
35
+
36
+ is_sampled, _tags = @lower_bound_sampler.sample?(*args)
37
+ [is_sampled, @lower_bound_tags]
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Samplers
6
+ # A sampler that leverages both Probabilistic sampler and RateLimiting
7
+ # sampler via the GuaranteedThroughputProbabilistic sampler. This sampler
8
+ # keeps track of all operations and delegates calls the the respective
9
+ # GuaranteedThroughputProbabilistic sampler.
10
+ class PerOperation
11
+ DEFAULT_SAMPLING_PROBABILITY = 0.001
12
+ DEFAULT_LOWER_BOUND = 1.0 / (10.0 * 60.0) # sample once every 10 minutes'
13
+
14
+ def initialize(strategies:, max_operations:)
15
+ @max_operations = max_operations
16
+ @default_sampling_probability =
17
+ strategies[:default_sampling_probability] || DEFAULT_SAMPLING_PROBABILITY
18
+ @lower_bound = strategies[:default_lower_bound_traces_per_second] || DEFAULT_LOWER_BOUND
19
+
20
+ @default_sampler = Probabilistic.new(rate: @default_sampling_probability)
21
+ @samplers = (strategies[:per_operation_strategies] || []).reduce({}) do |acc, strategy|
22
+ operation = strategy.fetch(:operation)
23
+ rate = strategy.fetch(:probabilistic_sampling)
24
+ sampler = GuaranteedThroughputProbabilistic.new(
25
+ lower_bound: @lower_bound,
26
+ rate: rate
27
+ )
28
+ acc.merge(operation => sampler)
29
+ end
30
+ end
31
+
32
+ def sample?(opts)
33
+ operation_name = opts.fetch(:operation_name)
34
+ sampler = @samplers[operation_name]
35
+ return sampler.sample?(opts) if sampler
36
+
37
+ return @default_sampler.sample?(opts) if @samplers.length >= @max_operations
38
+
39
+ sampler = GuaranteedThroughputProbabilistic.new(
40
+ lower_bound: @lower_bound,
41
+ rate: @default_sampling_probability
42
+ )
43
+ @samplers[operation_name] = sampler
44
+ sampler.sample?(opts)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -8,22 +8,20 @@ module Jaeger
8
8
  # Sample a portion of traces using trace_id as the random decision
9
9
  class Probabilistic
10
10
  def initialize(rate: 0.001)
11
- @param = rate.to_s
12
11
  if rate < 0.0 || rate > 1.0
13
12
  raise "Sampling rate must be between 0.0 and 1.0, got #{rate.inspect}"
14
13
  end
15
- @boundary = TraceId::TRACE_ID_UPPER_BOUND * rate
16
- end
17
14
 
18
- def sample?(trace_id)
19
- @boundary >= trace_id
15
+ @boundary = TraceId::TRACE_ID_UPPER_BOUND * rate
16
+ @tags = {
17
+ 'sampler.type' => 'probabilistic',
18
+ 'sampler.param' => rate
19
+ }
20
20
  end
21
21
 
22
- def type
23
- 'probabilistic'
22
+ def sample?(trace_id:, **)
23
+ [@boundary >= trace_id, @tags]
24
24
  end
25
-
26
- attr_reader :param
27
25
  end
28
26
  end
29
27
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Samplers
6
+ # Samples at most max_traces_per_second. The distribution of sampled
7
+ # traces follows burstiness of the service, i.e. a service with uniformly
8
+ # distributed requests will have those requests sampled uniformly as
9
+ # well, but if requests are bursty, especially sub-second, then a number
10
+ # of sequential requests can be sampled each second.
11
+ class RateLimiting
12
+ attr_reader :tags
13
+
14
+ def initialize(max_traces_per_second: 10)
15
+ if max_traces_per_second < 0.0
16
+ raise "max_traces_per_second must not be negative, got #{max_traces_per_second}"
17
+ end
18
+
19
+ @rate_limiter = RateLimiter.new(
20
+ credits_per_second: max_traces_per_second,
21
+ max_balance: [max_traces_per_second, 1.0].max
22
+ )
23
+ @tags = {
24
+ 'sampler.type' => 'ratelimiting',
25
+ 'sampler.param' => max_traces_per_second
26
+ }
27
+ end
28
+
29
+ def sample?(*)
30
+ [@rate_limiter.check_credit(1.0), @tags]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -10,13 +10,6 @@ module Jaeger
10
10
  DEBUG = 0x02
11
11
  end
12
12
 
13
- def self.create_parent_context(sampler = Samplers::Const.new(true))
14
- trace_id = TraceId.generate
15
- span_id = TraceId.generate
16
- flags = sampler.sample?(trace_id) ? Flags::SAMPLED : Flags::NONE
17
- new(trace_id: trace_id, span_id: span_id, flags: flags)
18
- end
19
-
20
13
  def self.create_from_parent_context(span_context)
21
14
  new(
22
15
  trace_id: span_context.trace_id,
@@ -50,7 +50,8 @@ module Jaeger
50
50
  tags: {},
51
51
  ignore_active_scope: false,
52
52
  **)
53
- context = prepare_span_context(
53
+ context, sampler_tags = prepare_span_context(
54
+ operation_name: operation_name,
54
55
  child_of: child_of,
55
56
  references: references,
56
57
  ignore_active_scope: ignore_active_scope
@@ -61,10 +62,7 @@ module Jaeger
61
62
  @reporter,
62
63
  start_time: start_time,
63
64
  references: references,
64
- tags: tags.merge(
65
- :'sampler.type' => @sampler.type,
66
- :'sampler.param' => @sampler.param
67
- )
65
+ tags: tags.merge(sampler_tags)
68
66
  )
69
67
  end
70
68
 
@@ -150,16 +148,26 @@ module Jaeger
150
148
 
151
149
  private
152
150
 
153
- def prepare_span_context(child_of:, references:, ignore_active_scope:)
151
+ def prepare_span_context(operation_name:, child_of:, references:, ignore_active_scope:)
154
152
  context =
155
153
  context_from_child_of(child_of) ||
156
154
  context_from_references(references) ||
157
155
  context_from_active_scope(ignore_active_scope)
158
156
 
159
157
  if context
160
- SpanContext.create_from_parent_context(context)
158
+ [SpanContext.create_from_parent_context(context), {}]
161
159
  else
162
- SpanContext.create_parent_context(@sampler)
160
+ trace_id = TraceId.generate
161
+ is_sampled, tags = @sampler.sample?(
162
+ trace_id: trace_id,
163
+ operation_name: operation_name
164
+ )
165
+ span_context = SpanContext.new(
166
+ trace_id: trace_id,
167
+ span_id: trace_id,
168
+ flags: is_sampled ? SpanContext::Flags::SAMPLED : SpanContext::Flags::NONE
169
+ )
170
+ [span_context, tags]
163
171
  end
164
172
  end
165
173
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Jaeger
4
4
  module Client
5
- VERSION = '0.8.0'.freeze
5
+ VERSION = '0.9.0'.freeze
6
6
  end
7
7
  end
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.8.0
4
+ version: 0.9.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-12-21 00:00:00.000000000 Z
11
+ date: 2018-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: 1.24.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: timecop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.9'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.9'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: opentracing
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -136,16 +150,25 @@ files:
136
150
  - crossdock/server
137
151
  - jaeger-client.gemspec
138
152
  - lib/jaeger/client.rb
139
- - lib/jaeger/client/async_reporter.rb
140
- - lib/jaeger/client/async_reporter/buffer.rb
141
153
  - lib/jaeger/client/carrier.rb
142
154
  - lib/jaeger/client/encoders/thrift_encoder.rb
143
155
  - lib/jaeger/client/extractors.rb
144
156
  - lib/jaeger/client/http_sender.rb
145
157
  - lib/jaeger/client/injectors.rb
158
+ - lib/jaeger/client/rate_limiter.rb
159
+ - lib/jaeger/client/reporters.rb
160
+ - lib/jaeger/client/reporters/composite_reporter.rb
161
+ - lib/jaeger/client/reporters/in_memory_reporter.rb
162
+ - lib/jaeger/client/reporters/logging_reporter.rb
163
+ - lib/jaeger/client/reporters/null_reporter.rb
164
+ - lib/jaeger/client/reporters/remote_reporter.rb
165
+ - lib/jaeger/client/reporters/remote_reporter/buffer.rb
146
166
  - lib/jaeger/client/samplers.rb
147
167
  - lib/jaeger/client/samplers/const.rb
168
+ - lib/jaeger/client/samplers/guaranteed_throughput_probabilistic.rb
169
+ - lib/jaeger/client/samplers/per_operation.rb
148
170
  - lib/jaeger/client/samplers/probabilistic.rb
171
+ - lib/jaeger/client/samplers/rate_limiting.rb
149
172
  - lib/jaeger/client/scope.rb
150
173
  - lib/jaeger/client/scope_manager.rb
151
174
  - lib/jaeger/client/scope_manager/scope_identifier.rb
@@ -176,7 +199,7 @@ files:
176
199
  - thrift/gen-rb/jaeger/thrift/zipkin/zipkincore_types.rb
177
200
  - thrift/jaeger.thrift
178
201
  - thrift/zipkincore.thrift
179
- homepage: ''
202
+ homepage: https://github.com/salemove/jaeger-client-ruby
180
203
  licenses:
181
204
  - MIT
182
205
  metadata: {}
@@ -1,48 +0,0 @@
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
- new(sender, flush_interval)
12
- end
13
-
14
- def initialize(sender, flush_interval)
15
- @sender = sender
16
- @flush_interval = flush_interval
17
- @buffer = Buffer.new
18
- end
19
-
20
- def flush
21
- spans = @buffer.retrieve
22
- @sender.send_spans(spans) if spans.any?
23
- spans
24
- end
25
-
26
- def report(span)
27
- return if !span.context.sampled? && !span.context.debug?
28
-
29
- init_reporter_thread
30
- @buffer << span
31
- end
32
-
33
- private
34
-
35
- def init_reporter_thread
36
- return if @initializer_pid == Process.pid
37
-
38
- @initializer_pid = Process.pid
39
- Thread.new do
40
- loop do
41
- flush
42
- sleep(@flush_interval)
43
- end
44
- end
45
- end
46
- end
47
- end
48
- end