jaeger-client 0.9.0 → 0.10.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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -16
  3. data/crossdock/server +1 -1
  4. data/lib/jaeger/client.rb +25 -15
  5. data/lib/jaeger/client/version.rb +1 -1
  6. data/lib/jaeger/encoders/thrift_encoder.rb +92 -0
  7. data/lib/jaeger/extractors.rb +109 -0
  8. data/lib/jaeger/http_sender.rb +28 -0
  9. data/lib/jaeger/injectors.rb +69 -0
  10. data/lib/jaeger/rate_limiter.rb +61 -0
  11. data/lib/jaeger/{client/reporters.rb → reporters.rb} +0 -0
  12. data/lib/jaeger/reporters/composite_reporter.rb +17 -0
  13. data/lib/jaeger/reporters/in_memory_reporter.rb +30 -0
  14. data/lib/jaeger/reporters/logging_reporter.rb +22 -0
  15. data/lib/jaeger/reporters/null_reporter.rb +11 -0
  16. data/lib/jaeger/reporters/remote_reporter.rb +42 -0
  17. data/lib/jaeger/reporters/remote_reporter/buffer.rb +29 -0
  18. data/lib/jaeger/{client/samplers.rb → samplers.rb} +0 -0
  19. data/lib/jaeger/samplers/const.rb +24 -0
  20. data/lib/jaeger/samplers/guaranteed_throughput_probabilistic.rb +40 -0
  21. data/lib/jaeger/samplers/per_operation.rb +47 -0
  22. data/lib/jaeger/samplers/probabilistic.rb +26 -0
  23. data/lib/jaeger/samplers/rate_limiting.rb +33 -0
  24. data/lib/jaeger/scope.rb +38 -0
  25. data/lib/jaeger/scope_manager.rb +47 -0
  26. data/lib/jaeger/scope_manager/scope_identifier.rb +13 -0
  27. data/lib/jaeger/scope_manager/scope_stack.rb +33 -0
  28. data/lib/jaeger/span.rb +98 -0
  29. data/lib/jaeger/span/thrift_log_builder.rb +18 -0
  30. data/lib/jaeger/span/thrift_tag_builder.rb +43 -0
  31. data/lib/jaeger/span_context.rb +57 -0
  32. data/lib/jaeger/trace_id.rb +39 -0
  33. data/lib/jaeger/tracer.rb +195 -0
  34. data/lib/jaeger/udp_sender.rb +24 -0
  35. data/lib/jaeger/udp_sender/transport.rb +40 -0
  36. metadata +31 -32
  37. data/lib/jaeger/client/carrier.rb +0 -26
  38. data/lib/jaeger/client/encoders/thrift_encoder.rb +0 -94
  39. data/lib/jaeger/client/extractors.rb +0 -111
  40. data/lib/jaeger/client/http_sender.rb +0 -30
  41. data/lib/jaeger/client/injectors.rb +0 -71
  42. data/lib/jaeger/client/rate_limiter.rb +0 -63
  43. data/lib/jaeger/client/reporters/composite_reporter.rb +0 -19
  44. data/lib/jaeger/client/reporters/in_memory_reporter.rb +0 -32
  45. data/lib/jaeger/client/reporters/logging_reporter.rb +0 -24
  46. data/lib/jaeger/client/reporters/null_reporter.rb +0 -13
  47. data/lib/jaeger/client/reporters/remote_reporter.rb +0 -44
  48. data/lib/jaeger/client/reporters/remote_reporter/buffer.rb +0 -31
  49. data/lib/jaeger/client/samplers/const.rb +0 -26
  50. data/lib/jaeger/client/samplers/guaranteed_throughput_probabilistic.rb +0 -42
  51. data/lib/jaeger/client/samplers/per_operation.rb +0 -49
  52. data/lib/jaeger/client/samplers/probabilistic.rb +0 -28
  53. data/lib/jaeger/client/samplers/rate_limiting.rb +0 -35
  54. data/lib/jaeger/client/scope.rb +0 -40
  55. data/lib/jaeger/client/scope_manager.rb +0 -49
  56. data/lib/jaeger/client/scope_manager/scope_identifier.rb +0 -15
  57. data/lib/jaeger/client/scope_manager/scope_stack.rb +0 -35
  58. data/lib/jaeger/client/span.rb +0 -100
  59. data/lib/jaeger/client/span/thrift_log_builder.rb +0 -20
  60. data/lib/jaeger/client/span/thrift_tag_builder.rb +0 -45
  61. data/lib/jaeger/client/span_context.rb +0 -59
  62. data/lib/jaeger/client/trace_id.rb +0 -41
  63. data/lib/jaeger/client/tracer.rb +0 -197
  64. data/lib/jaeger/client/udp_sender.rb +0 -27
  65. data/lib/jaeger/client/udp_sender/transport.rb +0 -42
@@ -1,49 +0,0 @@
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
@@ -1,15 +0,0 @@
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
@@ -1,35 +0,0 @@
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,100 +0,0 @@
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, :end_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 reporter [#report] span reporter
18
- #
19
- # @return [Span] a new Span
20
- def initialize(context, operation_name, reporter, start_time: Time.now, references: [], tags: {})
21
- @context = context
22
- @operation_name = operation_name
23
- @reporter = reporter
24
- @start_time = start_time
25
- @references = references
26
- @tags = []
27
- @logs = []
28
-
29
- tags.each { |key, value| set_tag(key, value) }
30
- end
31
-
32
- # Set a tag value on this span
33
- #
34
- # @param key [String] the key of the tag
35
- # @param value [String, Numeric, Boolean] the value of the tag. If it's not
36
- # a String, Numeric, or Boolean it will be encoded with to_s
37
- def set_tag(key, value)
38
- if key == 'sampling.priority'
39
- if value.to_i > 0
40
- return self if @context.debug?
41
-
42
- @context.flags = @context.flags | SpanContext::Flags::SAMPLED | SpanContext::Flags::DEBUG
43
- else
44
- @context.flags = @context.flags & ~SpanContext::Flags::SAMPLED
45
- end
46
- return self
47
- end
48
-
49
- # Using Thrift::Tag to avoid unnecessary memory allocations
50
- @tags << ThriftTagBuilder.build(key, value)
51
-
52
- self
53
- end
54
-
55
- # Set a baggage item on the span
56
- #
57
- # @param key [String] the key of the baggage item
58
- # @param value [String] the value of the baggage item
59
- def set_baggage_item(key, value)
60
- @context.set_baggage_item(key, value)
61
- self
62
- end
63
-
64
- # Get a baggage item
65
- #
66
- # @param key [String] the key of the baggage item
67
- #
68
- # @return Value of the baggage item
69
- def get_baggage_item(key)
70
- @context.get_baggage_item(key)
71
- end
72
-
73
- # Add a log entry to this span
74
- #
75
- # @deprecated Use {#log_kv} instead.
76
- def log(*args)
77
- warn 'Span#log is deprecated. Please use Span#log_kv instead.'
78
- log_kv(*args)
79
- end
80
-
81
- # Add a log entry to this span
82
- #
83
- # @param timestamp [Time] time of the log
84
- # @param fields [Hash] Additional information to log
85
- def log_kv(timestamp: Time.now, **fields)
86
- # Using Thrift::Log to avoid unnecessary memory allocations
87
- @logs << ThriftLogBuilder.build(timestamp, fields)
88
- nil
89
- end
90
-
91
- # Finish the {Span}
92
- #
93
- # @param end_time [Time] custom end time, if not now
94
- def finish(end_time: Time.now)
95
- @end_time = end_time
96
- @reporter.report(self)
97
- end
98
- end
99
- end
100
- end
@@ -1,20 +0,0 @@
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
@@ -1,45 +0,0 @@
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,59 +0,0 @@
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
- module Flags
8
- NONE = 0x00
9
- SAMPLED = 0x01
10
- DEBUG = 0x02
11
- end
12
-
13
- def self.create_from_parent_context(span_context)
14
- new(
15
- trace_id: span_context.trace_id,
16
- parent_id: span_context.span_id,
17
- span_id: TraceId.generate,
18
- flags: span_context.flags,
19
- baggage: span_context.baggage.dup
20
- )
21
- end
22
-
23
- attr_reader :span_id, :parent_id, :trace_id, :baggage, :flags
24
- attr_writer :flags
25
-
26
- def initialize(span_id:, parent_id: 0, trace_id:, flags:, baggage: {})
27
- @span_id = span_id
28
- @parent_id = parent_id
29
- @trace_id = trace_id
30
- @baggage = baggage
31
- @flags = flags
32
- end
33
-
34
- def sampled?
35
- @flags & Flags::SAMPLED == Flags::SAMPLED
36
- end
37
-
38
- def debug?
39
- @flags & Flags::DEBUG == Flags::DEBUG
40
- end
41
-
42
- def to_trace_id
43
- @to_trace_id ||= @trace_id.to_s(16)
44
- end
45
-
46
- def to_span_id
47
- @to_span_id ||= @span_id.to_s(16)
48
- end
49
-
50
- def set_baggage_item(key, value)
51
- @baggage[key.to_s] = value.to_s
52
- end
53
-
54
- def get_baggage_item(key)
55
- @baggage[key.to_s]
56
- end
57
- end
58
- end
59
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Jaeger
4
- module Client
5
- module TraceId
6
- MAX_64BIT_SIGNED_INT = (1 << 63) - 1
7
- MAX_64BIT_UNSIGNED_INT = (1 << 64) - 1
8
- TRACE_ID_UPPER_BOUND = MAX_64BIT_UNSIGNED_INT + 1
9
-
10
- def self.generate
11
- rand(TRACE_ID_UPPER_BOUND)
12
- end
13
-
14
- def self.base16_hex_id_to_uint64(id)
15
- return nil unless id
16
- value = id.to_i(16)
17
- value > MAX_64BIT_UNSIGNED_INT || value < 0 ? 0 : value
18
- end
19
-
20
- # Thrift defines ID fields as i64, which is signed, therefore we convert
21
- # large IDs (> 2^63) to negative longs
22
- def self.uint64_id_to_int64(id)
23
- id > MAX_64BIT_SIGNED_INT ? id - MAX_64BIT_UNSIGNED_INT - 1 : id
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
39
- end
40
- end
41
- end
@@ -1,197 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Jaeger
4
- module Client
5
- class Tracer
6
- def initialize(reporter:, sampler:, injectors:, extractors:)
7
- @reporter = reporter
8
- @sampler = sampler
9
- @injectors = injectors
10
- @extractors = extractors
11
- @scope_manager = ScopeManager.new
12
- end
13
-
14
- # @return [ScopeManager] the current ScopeManager, which may be a no-op
15
- # but may not be nil.
16
- attr_reader :scope_manager
17
-
18
- # @return [Span, nil] the active span. This is a shorthand for
19
- # `scope_manager.active.span`, and nil will be returned if
20
- # Scope#active is nil.
21
- def active_span
22
- scope = scope_manager.active
23
- scope.span if scope
24
- end
25
-
26
- # Starts a new span.
27
- #
28
- # This is similar to #start_active_span, but the returned Span will not
29
- # be registered via the ScopeManager.
30
- #
31
- # @param operation_name [String] The operation name for the Span
32
- # @param child_of [SpanContext, Span] SpanContext that acts as a parent to
33
- # the newly-started Span. If a Span instance is provided, its
34
- # context is automatically substituted. See [Reference] for more
35
- # information.
36
- #
37
- # If specified, the `references` parameter must be omitted.
38
- # @param references [Array<Reference>] An array of reference
39
- # objects that identify one or more parent SpanContexts.
40
- # @param start_time [Time] When the Span started, if not now
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.
44
- #
45
- # @return [Span] The newly-started Span
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, sampler_tags = prepare_span_context(
54
- operation_name: operation_name,
55
- child_of: child_of,
56
- references: references,
57
- ignore_active_scope: ignore_active_scope
58
- )
59
- Span.new(
60
- context,
61
- operation_name,
62
- @reporter,
63
- start_time: start_time,
64
- references: references,
65
- tags: tags.merge(sampler_tags)
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
118
- end
119
- end
120
-
121
- scope
122
- end
123
-
124
- # Inject a SpanContext into the given carrier
125
- #
126
- # @param span_context [SpanContext]
127
- # @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
128
- # @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
129
- def inject(span_context, format, carrier)
130
- @injectors.fetch(format).each do |injector|
131
- injector.inject(span_context, carrier)
132
- end
133
- end
134
-
135
- # Extract a SpanContext in the given format from the given carrier.
136
- #
137
- # @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
138
- # @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
139
- # @return [SpanContext] the extracted SpanContext or nil if none could be found
140
- def extract(format, carrier)
141
- @extractors
142
- .fetch(format)
143
- .lazy
144
- .map { |extractor| extractor.extract(carrier) }
145
- .reject(&:nil?)
146
- .first
147
- end
148
-
149
- private
150
-
151
- def prepare_span_context(operation_name:, child_of:, references:, ignore_active_scope:)
152
- context =
153
- context_from_child_of(child_of) ||
154
- context_from_references(references) ||
155
- context_from_active_scope(ignore_active_scope)
156
-
157
- if context
158
- [SpanContext.create_from_parent_context(context), {}]
159
- else
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]
171
- end
172
- end
173
-
174
- def context_from_child_of(child_of)
175
- return nil unless child_of
176
- child_of.respond_to?(:context) ? child_of.context : child_of
177
- end
178
-
179
- def context_from_references(references)
180
- return nil if !references || references.none?
181
-
182
- # Prefer CHILD_OF reference if present
183
- ref = references.detect do |reference|
184
- reference.type == OpenTracing::Reference::CHILD_OF
185
- end
186
- (ref || references[0]).context
187
- end
188
-
189
- def context_from_active_scope(ignore_active_scope)
190
- return if ignore_active_scope
191
-
192
- active_scope = @scope_manager.active
193
- active_scope.span.context if active_scope
194
- end
195
- end
196
- end
197
- end