jaeger-client 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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