jaeger-client 0.4.2 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75c88fcea8c5fa02b502e8c2c6cb3838a246e714
4
- data.tar.gz: 12d8f676f98d486d1b9db5e73c7dc757e46477a8
3
+ metadata.gz: 180ed5153f692c630fd0e0006b3d6265c5839875
4
+ data.tar.gz: 98dea74437333796b07bf81afba0558652b51623
5
5
  SHA512:
6
- metadata.gz: 2eedd11ef42e96094a128fd32df3c3bf5a152d498dd09933a667930caa5af7f287c00bddf9524cc87429898ff78a7e3cc1d2da1b38f560be9f3731bfe0f42ac1
7
- data.tar.gz: c478b9e68a708fd6a093d08b38c844136535a4b3723dd717392dd7ce5852ac01ba2a6b0948f954924cbe9a46daf6ea9e13f8d87242bb58a647fb44a0d0695d6f
6
+ metadata.gz: ef49bfeb6aee4d16534c256580efe859d6468f7f68c748db31166c10ba700416a8035d18c51d26d5b863dccae71c036f6e7a3645eb49c323d2a1ed80a9507f0f
7
+ data.tar.gz: 1965becd08d299d65067e503e64d926dfffe95b216b306334c562c3a9db703eba2bc4171e53586c4b180e262a3fda7bb9ceed38ec9b021ba475b680e5728ebe9
data/.rubocop.yml CHANGED
@@ -16,6 +16,9 @@ RSpec/NestedGroups:
16
16
  RSpec/ExampleLength:
17
17
  Enabled: no
18
18
 
19
+ RSpec/MultipleExpectations:
20
+ Enabled: no
21
+
19
22
  Metrics/BlockLength:
20
23
  Enabled: no
21
24
 
@@ -25,8 +28,20 @@ Metrics/MethodLength:
25
28
  Metrics/AbcSize:
26
29
  Enabled: no
27
30
 
31
+ Metrics/ClassLength:
32
+ Enabled: no
33
+
34
+ Metrics/ParameterLists:
35
+ Enabled: no
36
+
28
37
  Lint/UnusedMethodArgument:
29
38
  Enabled: no
30
39
 
40
+ Style/FrozenStringLiteralComment:
41
+ Enabled: yes
42
+ EnforcedStyle: always
43
+ Include:
44
+ - 'lib/**/*'
45
+
31
46
  Metrics/LineLength:
32
47
  Max: 120
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
- # Jaeger::Client
1
+ Jaeger::Client
2
+ ================
3
+ [![Gem Version](https://badge.fury.io/rb/jaeger-client.svg)](https://rubygems.org/gems/jaeger-client)
4
+ [![Build Status](https://travis-ci.org/salemove/jaeger-client-ruby.svg)](https://travis-ci.org/salemove/jaeger-client-ruby)
2
5
 
3
6
  OpenTracing Tracer implementation for Jaeger in Ruby
4
7
 
@@ -16,10 +19,27 @@ gem 'jaeger-client'
16
19
  require 'jaeger/client'
17
20
  OpenTracing.global_tracer = Jaeger::Client.build(host: 'localhost', port: 6831, service_name: 'echo')
18
21
 
19
- span = OpenTracing.start_span('span name')
20
- span.finish
22
+ OpenTracing.start_active_span('span name') do
23
+ # do something
24
+
25
+ OpenTracing.start_active_span('inner span name') do
26
+ # do something else
27
+ end
28
+ end
21
29
  ```
22
30
 
31
+ See [opentracing-ruby](https://github.com/opentracing/opentracing-ruby) for more examples.
32
+
33
+ ### Samplers
34
+
35
+ #### Const sampler
36
+
37
+ `Const` sampler always makes the same decision for new traces depending on the initialization value. Set `sampler` to: `Jaeger::Client::Samplers::Const.new(true)` to mark all new traces as sampled.
38
+
39
+ #### Probabilistic sampler
40
+
41
+ `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
+
23
43
  ## Development
24
44
 
25
45
  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.
@@ -1,4 +1,3 @@
1
-
2
1
  lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
 
data/lib/jaeger/client.rb CHANGED
@@ -1,21 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.push(File.dirname(__FILE__) + '/../../thrift/gen-rb')
2
4
 
3
5
  require 'opentracing'
6
+ require 'jaeger/thrift/agent'
4
7
 
5
8
  require_relative 'client/tracer'
6
9
  require_relative 'client/span'
7
10
  require_relative 'client/span_context'
11
+ require_relative 'client/scope'
12
+ require_relative 'client/scope_manager'
8
13
  require_relative 'client/carrier'
9
14
  require_relative 'client/trace_id'
10
15
  require_relative 'client/udp_sender'
11
16
  require_relative 'client/collector'
12
17
  require_relative 'client/version'
18
+ require_relative 'client/samplers'
13
19
 
14
20
  module Jaeger
15
21
  module Client
16
22
  DEFAULT_FLUSH_INTERVAL = 10
17
23
 
18
- def self.build(host: '127.0.0.1', port: 6831, service_name:, flush_interval: DEFAULT_FLUSH_INTERVAL)
24
+ def self.build(host: '127.0.0.1',
25
+ port: 6831,
26
+ service_name:,
27
+ flush_interval: DEFAULT_FLUSH_INTERVAL,
28
+ sampler: Samplers::Const.new(true))
19
29
  collector = Collector.new
20
30
  sender = UdpSender.new(
21
31
  service_name: service_name,
@@ -25,7 +35,7 @@ module Jaeger
25
35
  flush_interval: flush_interval
26
36
  )
27
37
  sender.start
28
- Tracer.new(collector, sender)
38
+ Tracer.new(collector, sender, sampler)
29
39
  end
30
40
  end
31
41
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jaeger
2
4
  module Client
3
5
  # Carriers are used for inject and extract operations. A carrier should be a
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thread'
2
4
 
3
5
  module Jaeger
@@ -10,6 +12,7 @@ module Jaeger
10
12
  def send_span(span, end_time)
11
13
  context = span.context
12
14
  start_ts, duration = build_timestamps(span, end_time)
15
+ return if !context.sampled? && !context.debug?
13
16
 
14
17
  @buffer << Jaeger::Thrift::Span.new(
15
18
  'traceIdLow' => context.trace_id,
@@ -21,8 +24,8 @@ module Jaeger
21
24
  'flags' => context.flags,
22
25
  'startTime' => start_ts,
23
26
  'duration' => duration,
24
- 'tags' => build_tags(span.tags),
25
- 'logs' => build_logs(span.logs)
27
+ 'tags' => span.tags,
28
+ 'logs' => span.logs
26
29
  )
27
30
  end
28
31
 
@@ -32,27 +35,6 @@ module Jaeger
32
35
 
33
36
  private
34
37
 
35
- def build_tags(tags)
36
- tags.map { |name, value| build_tag(name, value) }
37
- end
38
-
39
- def build_logs(logs)
40
- logs.map do |timestamp:, fields:|
41
- Jaeger::Thrift::Log.new(
42
- 'timestamp' => (timestamp.to_f * 1_000_000).to_i,
43
- 'fields' => fields.map { |name, value| build_tag(name, value) }
44
- )
45
- end
46
- end
47
-
48
- def build_tag(name, value)
49
- Jaeger::Thrift::Tag.new(
50
- 'key' => name.to_s,
51
- 'vType' => Jaeger::Thrift::TagType::STRING,
52
- 'vStr' => value.to_s
53
- )
54
- end
55
-
56
38
  def build_timestamps(span, end_time)
57
39
  start_ts = (span.start_time.to_f * 1_000_000).to_i
58
40
  end_ts = (end_time.to_f * 1_000_000).to_i
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'samplers/const'
4
+ require_relative 'samplers/probabilistic'
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Samplers
6
+ # Const sampler
7
+ #
8
+ # A sampler that always makes the same decision for new traces depending
9
+ # on the initialization value. Use `Jaeger::Client::Samplers::Const.new(true)`
10
+ # to mark all new traces as sampled.
11
+ class Const
12
+ def initialize(decision)
13
+ @decision = decision
14
+ @param = decision ? '1' : '0'
15
+ end
16
+
17
+ def sample?(*)
18
+ @decision
19
+ end
20
+
21
+ def type
22
+ 'const'
23
+ end
24
+
25
+ attr_reader :param
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ module Samplers
6
+ # Probabilistic sampler
7
+ #
8
+ # Sample a portion of traces using trace_id as the random decision
9
+ class Probabilistic
10
+ def initialize(rate: 0.001)
11
+ @param = rate.to_s
12
+ if rate < 0.0 || rate > 1.0
13
+ raise "Sampling rate must be between 0.0 and 1.0, got #{rate.inspect}"
14
+ end
15
+ @boundary = TraceId::TRACE_ID_UPPER_BOUND * rate
16
+ end
17
+
18
+ def sample?(trace_id)
19
+ @boundary >= trace_id
20
+ end
21
+
22
+ def type
23
+ 'probabilistic'
24
+ end
25
+
26
+ attr_reader :param
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ # Scope represents an OpenTracing Scope
6
+ #
7
+ # See http://www.opentracing.io for more information.
8
+ class Scope
9
+ def initialize(span, scope_stack, finish_on_close:)
10
+ @span = span
11
+ @scope_stack = scope_stack
12
+ @finish_on_close = finish_on_close
13
+ @closed = false
14
+ end
15
+
16
+ # Return the Span scoped by this Scope
17
+ #
18
+ # @return [Span]
19
+ attr_reader :span
20
+
21
+ # Close scope
22
+ #
23
+ # Mark the end of the active period for the current thread and Scope,
24
+ # updating the ScopeManager#active in the process.
25
+ def close
26
+ raise "Tried to close already closed span: #{inspect}" if @closed
27
+ @closed = true
28
+
29
+ @span.finish if @finish_on_close
30
+ removed_scope = @scope_stack.pop
31
+
32
+ if removed_scope != self # rubocop:disable Style/GuardClause
33
+ raise 'Removed non-active scope, ' \
34
+ "removed: #{removed_scope.inspect}, "\
35
+ "expected: #{inspect}"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'scope_manager/scope_stack'
4
+ require_relative 'scope_manager/scope_identifier'
5
+
6
+ module Jaeger
7
+ module Client
8
+ # ScopeManager represents an OpenTracing ScopeManager
9
+ #
10
+ # See http://www.opentracing.io for more information.
11
+ #
12
+ # The ScopeManager interface abstracts both the activation of Span instances
13
+ # via ScopeManager#activate and access to an active Span/Scope via
14
+ # ScopeManager#active
15
+ #
16
+ class ScopeManager
17
+ def initialize
18
+ @scope_stack = ScopeStack.new
19
+ end
20
+
21
+ # Make a span instance active
22
+ #
23
+ # @param span [Span] the Span that should become active
24
+ # @param finish_on_close [Boolean] whether the Span should automatically be
25
+ # finished when Scope#close is called
26
+ # @return [Scope] instance to control the end of the active period for the
27
+ # Span. It is a programming error to neglect to call Scope#close on the
28
+ # returned instance.
29
+ def activate(span, finish_on_close: true)
30
+ return active if active && active.span == span
31
+ scope = Scope.new(span, @scope_stack, finish_on_close: finish_on_close)
32
+ @scope_stack.push(scope)
33
+ scope
34
+ end
35
+
36
+ # Return active scope
37
+ #
38
+ # If there is a non-null Scope, its wrapped Span becomes an implicit parent
39
+ # (as Reference#CHILD_OF) of any newly-created Span at
40
+ # Tracer#start_active_span or Tracer#start_span time.
41
+ #
42
+ # @return [Scope] the currently active Scope which can be used to access the
43
+ # currently active Span.
44
+ def active
45
+ @scope_stack.peek
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ class ScopeManager
6
+ # @api private
7
+ class ScopeIdentifier
8
+ def self.generate
9
+ # 65..90.chr are characters between A and Z
10
+ "opentracing_#{(0...8).map { rand(65..90).chr }.join}".to_sym
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ class ScopeManager
6
+ # @api private
7
+ class ScopeStack
8
+ def initialize
9
+ # Generate a random identifier to use as the Thread.current key. This is
10
+ # needed so that it would be possible to create multiple tracers in one
11
+ # thread (mostly useful for testing purposes)
12
+ @scope_identifier = ScopeIdentifier.generate
13
+ end
14
+
15
+ def push(scope)
16
+ store << scope
17
+ end
18
+
19
+ def pop
20
+ store.pop
21
+ end
22
+
23
+ def peek
24
+ store.last
25
+ end
26
+
27
+ private
28
+
29
+ def store
30
+ Thread.current[@scope_identifier] ||= []
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,3 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'span/thrift_tag_builder'
4
+ require_relative 'span/thrift_log_builder'
5
+
1
6
  module Jaeger
2
7
  module Client
3
8
  class Span
@@ -17,7 +22,7 @@ module Jaeger
17
22
  @operation_name = operation_name
18
23
  @collector = collector
19
24
  @start_time = start_time
20
- @tags = tags
25
+ @tags = tags.map { |key, value| ThriftTagBuilder.build(key, value) }
21
26
  @logs = []
22
27
  end
23
28
 
@@ -27,7 +32,8 @@ module Jaeger
27
32
  # @param value [String, Numeric, Boolean] the value of the tag. If it's not
28
33
  # a String, Numeric, or Boolean it will be encoded with to_s
29
34
  def set_tag(key, value)
30
- @tags = @tags.merge(key => value)
35
+ # Using Thrift::Tag to avoid unnecessary memory allocations
36
+ @tags << ThriftTagBuilder.build(key, value)
31
37
  end
32
38
 
33
39
  # Set a baggage item on the span
@@ -47,12 +53,22 @@ module Jaeger
47
53
  nil
48
54
  end
49
55
 
56
+ # Add a log entry to this span
57
+ #
58
+ # @deprecated Use {#log_kv} instead.
59
+ def log(*args)
60
+ warn 'Span#log is deprecated. Please use Span#log_kv instead.'
61
+ log_kv(*args)
62
+ end
63
+
50
64
  # Add a log entry to this span
51
65
  #
52
66
  # @param timestamp [Time] time of the log
53
67
  # @param fields [Hash] Additional information to log
54
- def log(timestamp: Time.now, **fields)
55
- @logs << { timestamp: timestamp, fields: fields }
68
+ def log_kv(timestamp: Time.now, **fields)
69
+ # Using Thrift::Log to avoid unnecessary memory allocations
70
+ @logs << ThriftLogBuilder.build(timestamp, fields)
71
+ nil
56
72
  end
57
73
 
58
74
  # Finish the {Span}
@@ -61,14 +77,6 @@ module Jaeger
61
77
  def finish(end_time: Time.now)
62
78
  @collector.send_span(self, end_time)
63
79
  end
64
-
65
- private
66
-
67
- def build_binary_annotations
68
- @tags.map do |name, value|
69
- { key: name, value: value.to_s }
70
- end
71
- end
72
80
  end
73
81
  end
74
82
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ class Span
6
+ class ThriftLogBuilder
7
+ FIELDS = Jaeger::Thrift::Log::FIELDS
8
+ TIMESTAMP = FIELDS[Jaeger::Thrift::Log::TIMESTAMP].fetch(:name)
9
+ LOG_FIELDS = FIELDS[Jaeger::Thrift::Log::LOG_FIELDS].fetch(:name)
10
+
11
+ def self.build(timestamp, fields)
12
+ Jaeger::Thrift::Log.new(
13
+ TIMESTAMP => (timestamp.to_f * 1_000_000).to_i,
14
+ LOG_FIELDS => fields.map { |key, value| ThriftTagBuilder.build(key, value) }
15
+ )
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jaeger
4
+ module Client
5
+ class Span
6
+ class ThriftTagBuilder
7
+ FIELDS = Jaeger::Thrift::Tag::FIELDS
8
+ KEY = FIELDS[Jaeger::Thrift::Tag::KEY].fetch(:name)
9
+ VTYPE = FIELDS[Jaeger::Thrift::Tag::VTYPE].fetch(:name)
10
+ VLONG = FIELDS[Jaeger::Thrift::Tag::VLONG].fetch(:name)
11
+ VDOUBLE = FIELDS[Jaeger::Thrift::Tag::VDOUBLE].fetch(:name)
12
+ VBOOL = FIELDS[Jaeger::Thrift::Tag::VBOOL].fetch(:name)
13
+ VSTR = FIELDS[Jaeger::Thrift::Tag::VSTR].fetch(:name)
14
+
15
+ def self.build(key, value)
16
+ if value.is_a?(Integer)
17
+ Jaeger::Thrift::Tag.new(
18
+ KEY => key.to_s,
19
+ VTYPE => Jaeger::Thrift::TagType::LONG,
20
+ VLONG => value
21
+ )
22
+ elsif value.is_a?(Float)
23
+ Jaeger::Thrift::Tag.new(
24
+ KEY => key.to_s,
25
+ VTYPE => Jaeger::Thrift::TagType::DOUBLE,
26
+ VDOUBLE => value
27
+ )
28
+ elsif value.is_a?(TrueClass) || value.is_a?(FalseClass)
29
+ Jaeger::Thrift::Tag.new(
30
+ KEY => key.to_s,
31
+ VTYPE => Jaeger::Thrift::TagType::BOOL,
32
+ VBOOL => value
33
+ )
34
+ else
35
+ Jaeger::Thrift::Tag.new(
36
+ KEY => key.to_s,
37
+ VTYPE => Jaeger::Thrift::TagType::STRING,
38
+ VSTR => value.to_s
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,16 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jaeger
2
4
  module Client
3
5
  # SpanContext holds the data for a span that gets inherited to child spans
4
6
  class SpanContext
5
7
  module Flags
8
+ NONE = 0x00
6
9
  SAMPLED = 0x01
7
10
  DEBUG = 0x02
8
11
  end
9
12
 
10
- def self.create_parent_context
13
+ def self.create_parent_context(sampler = Samplers::Const.new(true))
11
14
  trace_id = TraceId.generate
12
15
  span_id = TraceId.generate
13
- flags = Flags::SAMPLED
16
+ flags = sampler.sample?(trace_id) ? Flags::SAMPLED : Flags::NONE
14
17
  new(trace_id: trace_id, span_id: span_id, flags: flags)
15
18
  end
16
19
 
@@ -32,6 +35,14 @@ module Jaeger
32
35
  @flags = flags
33
36
  end
34
37
 
38
+ def sampled?
39
+ @flags & Flags::SAMPLED == Flags::SAMPLED
40
+ end
41
+
42
+ def debug?
43
+ @flags & Flags::DEBUG == Flags::DEBUG
44
+ end
45
+
35
46
  def inspect
36
47
  to_s
37
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jaeger
2
4
  module Client
3
5
  module TraceId
@@ -1,34 +1,124 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jaeger
2
4
  module Client
3
5
  class Tracer
4
- def initialize(collector, sender)
6
+ def initialize(collector, sender, sampler)
5
7
  @collector = collector
6
8
  @sender = sender
9
+ @sampler = sampler
10
+ @scope_manager = ScopeManager.new
7
11
  end
8
12
 
9
13
  def stop
10
14
  @sender.stop
11
15
  end
12
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
+
13
29
  # Starts a new span.
14
30
  #
31
+ # This is similar to #start_active_span, but the returned Span will not
32
+ # be registered via the ScopeManager.
33
+ #
15
34
  # @param operation_name [String] The operation name for the Span
16
35
  # @param child_of [SpanContext, Span] SpanContext that acts as a parent to
17
- # the newly-started Span. If a Span instance is provided, its
18
- # context is automatically substituted.
36
+ # the newly-started Span. If a Span instance is provided, its
37
+ # context is automatically substituted.
38
+ # @param references [Array<Reference>] An array of reference
39
+ # objects that identify one or more parent SpanContexts.
19
40
  # @param start_time [Time] When the Span started, if not now
20
41
  # @param tags [Hash] Tags to assign to the Span at start time
42
+ # @param ignore_active_scope [Boolean] whether to create an implicit
43
+ # References#CHILD_OF reference to the ScopeManager#active.
21
44
  #
22
45
  # @return [Span] The newly-started Span
23
- def start_span(operation_name, child_of: nil, start_time: Time.now, tags: {}, **)
24
- context =
25
- if child_of
26
- parent_context = child_of.respond_to?(:context) ? child_of.context : child_of
27
- SpanContext.create_from_parent_context(parent_context)
28
- else
29
- SpanContext.create_parent_context
46
+ def start_span(operation_name,
47
+ child_of: nil,
48
+ references: nil,
49
+ start_time: Time.now,
50
+ tags: {},
51
+ ignore_active_scope: false,
52
+ **)
53
+ context = prepare_span_context(
54
+ child_of: child_of,
55
+ ignore_active_scope: ignore_active_scope
56
+ )
57
+ Span.new(
58
+ context,
59
+ operation_name,
60
+ @collector,
61
+ start_time: start_time,
62
+ tags: tags.merge(
63
+ :'sampler.type' => @sampler.type,
64
+ :'sampler.param' => @sampler.param
65
+ )
66
+ )
67
+ end
68
+
69
+ # Creates a newly started and activated Scope
70
+ #
71
+ # If the Tracer's ScopeManager#active is not nil, no explicit references
72
+ # are provided, and `ignore_active_scope` is false, then an inferred
73
+ # References#CHILD_OF reference is created to the ScopeManager#active's
74
+ # SpanContext when start_active is invoked.
75
+ #
76
+ # @param operation_name [String] The operation name for the Span
77
+ # @param child_of [SpanContext, Span] SpanContext that acts as a parent to
78
+ # the newly-started Span. If a Span instance is provided, its
79
+ # context is automatically substituted. See [Reference] for more
80
+ # information.
81
+ #
82
+ # If specified, the `references` parameter must be omitted.
83
+ # @param references [Array<Reference>] An array of reference
84
+ # objects that identify one or more parent SpanContexts.
85
+ # @param start_time [Time] When the Span started, if not now
86
+ # @param tags [Hash] Tags to assign to the Span at start time
87
+ # @param ignore_active_scope [Boolean] whether to create an implicit
88
+ # References#CHILD_OF reference to the ScopeManager#active.
89
+ # @param finish_on_close [Boolean] whether span should automatically be
90
+ # finished when Scope#close is called
91
+ # @yield [Scope] If an optional block is passed to start_active it will
92
+ # yield the newly-started Scope. If `finish_on_close` is true then the
93
+ # Span will be finished automatically after the block is executed.
94
+ # @return [Scope] The newly-started and activated Scope
95
+ def start_active_span(operation_name,
96
+ child_of: nil,
97
+ references: nil,
98
+ start_time: Time.now,
99
+ tags: {},
100
+ ignore_active_scope: false,
101
+ finish_on_close: true,
102
+ **)
103
+ span = start_span(
104
+ operation_name,
105
+ child_of: child_of,
106
+ references: references,
107
+ start_time: start_time,
108
+ tags: tags,
109
+ ignore_active_scope: ignore_active_scope
110
+ )
111
+ scope = @scope_manager.activate(span, finish_on_close: finish_on_close)
112
+
113
+ if block_given?
114
+ begin
115
+ yield scope
116
+ ensure
117
+ scope.close
30
118
  end
31
- Span.new(context, operation_name, @collector, start_time: start_time, tags: tags)
119
+ end
120
+
121
+ scope
32
122
  end
33
123
 
34
124
  # Inject a SpanContext into the given carrier
@@ -91,6 +181,22 @@ module Jaeger
91
181
  mask = 2**(bits - 1)
92
182
  (num & ~mask) - (num & mask)
93
183
  end
184
+
185
+ def prepare_span_context(child_of:, ignore_active_scope:)
186
+ if child_of
187
+ parent_context = child_of.respond_to?(:context) ? child_of.context : child_of
188
+ return SpanContext.create_from_parent_context(parent_context)
189
+ end
190
+
191
+ unless ignore_active_scope
192
+ active_scope = @scope_manager.active
193
+ if active_scope
194
+ return SpanContext.create_from_parent_context(active_scope.span.context)
195
+ end
196
+ end
197
+
198
+ SpanContext.create_parent_context(@sampler)
199
+ end
94
200
  end
95
201
  end
96
202
  end
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative './udp_sender/transport'
2
- require 'jaeger/thrift/agent'
3
4
  require 'socket'
4
5
  require 'thread'
5
6
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jaeger
2
4
  module Client
3
5
  class UdpSender
@@ -6,7 +8,8 @@ module Jaeger
6
8
 
7
9
  def initialize(host, port)
8
10
  @socket = UDPSocket.new
9
- @socket.connect(host, port)
11
+ @host = host
12
+ @port = port
10
13
  @buffer = ::Thrift::MemoryBufferTransport.new
11
14
  end
12
15
 
@@ -26,7 +29,7 @@ module Jaeger
26
29
  private
27
30
 
28
31
  def send_bytes(bytes)
29
- @socket.send(bytes, FLAGS)
32
+ @socket.send(bytes, FLAGS, @host, @port)
30
33
  @socket.flush
31
34
  rescue Errno::ECONNREFUSED
32
35
  warn 'Unable to connect to Jaeger Agent'
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jaeger
2
4
  module Client
3
- VERSION = '0.4.2'.freeze
5
+ VERSION = '0.5.0'.freeze
4
6
  end
5
7
  end
data/script/create_trace CHANGED
@@ -16,7 +16,7 @@ outer_span = tracer1.start_span(
16
16
  tags: { 'span.kind' => 'server' }
17
17
  )
18
18
  sleep 0.1
19
- outer_span.log(event: 'woop di doop', count: 5)
19
+ outer_span.log_kv(event: 'woop di doop', count: 5)
20
20
  sleep 1
21
21
 
22
22
  inner_span = tracer1.start_span(
@@ -29,6 +29,7 @@ inner_span = tracer1.start_span(
29
29
  'peer.port' => 443
30
30
  }
31
31
  )
32
+ inner_span.set_tag('error', false)
32
33
  sleep 0.3 # emulate network delay
33
34
 
34
35
  downstream_span = tracer2.start_span(
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.4.2
4
+ version: 0.5.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-04-06 00:00:00.000000000 Z
11
+ date: 2018-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -129,7 +129,16 @@ files:
129
129
  - lib/jaeger/client.rb
130
130
  - lib/jaeger/client/carrier.rb
131
131
  - lib/jaeger/client/collector.rb
132
+ - lib/jaeger/client/samplers.rb
133
+ - lib/jaeger/client/samplers/const.rb
134
+ - lib/jaeger/client/samplers/probabilistic.rb
135
+ - lib/jaeger/client/scope.rb
136
+ - lib/jaeger/client/scope_manager.rb
137
+ - lib/jaeger/client/scope_manager/scope_identifier.rb
138
+ - lib/jaeger/client/scope_manager/scope_stack.rb
132
139
  - lib/jaeger/client/span.rb
140
+ - lib/jaeger/client/span/thrift_log_builder.rb
141
+ - lib/jaeger/client/span/thrift_tag_builder.rb
133
142
  - lib/jaeger/client/span_context.rb
134
143
  - lib/jaeger/client/trace_id.rb
135
144
  - lib/jaeger/client/tracer.rb