jaeger-client 0.7.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/.rubocop.yml +3 -0
  4. data/.travis.yml +11 -2
  5. data/Makefile +1 -0
  6. data/README.md +127 -13
  7. data/crossdock/Dockerfile +29 -0
  8. data/crossdock/Gemfile +6 -0
  9. data/crossdock/Gemfile.lock +35 -0
  10. data/crossdock/docker-compose.yml +68 -0
  11. data/crossdock/jaeger-docker-compose.yml +48 -0
  12. data/crossdock/rules.mk +35 -0
  13. data/crossdock/server +173 -0
  14. data/jaeger-client.gemspec +4 -2
  15. data/lib/jaeger/client.rb +42 -18
  16. data/lib/jaeger/client/version.rb +1 -1
  17. data/lib/jaeger/encoders/thrift_encoder.rb +142 -0
  18. data/lib/jaeger/extractors.rb +173 -0
  19. data/lib/jaeger/http_sender.rb +28 -0
  20. data/lib/jaeger/injectors.rb +83 -0
  21. data/lib/jaeger/rate_limiter.rb +61 -0
  22. data/lib/jaeger/recurring_executor.rb +35 -0
  23. data/lib/jaeger/reporters.rb +7 -0
  24. data/lib/jaeger/reporters/composite_reporter.rb +17 -0
  25. data/lib/jaeger/reporters/in_memory_reporter.rb +30 -0
  26. data/lib/jaeger/reporters/logging_reporter.rb +22 -0
  27. data/lib/jaeger/reporters/null_reporter.rb +11 -0
  28. data/lib/jaeger/{client/async_reporter.rb → reporters/remote_reporter.rb} +21 -20
  29. data/lib/jaeger/{client/async_reporter → reporters/remote_reporter}/buffer.rb +2 -2
  30. data/lib/jaeger/samplers.rb +8 -0
  31. data/lib/jaeger/samplers/const.rb +24 -0
  32. data/lib/jaeger/samplers/guaranteed_throughput_probabilistic.rb +47 -0
  33. data/lib/jaeger/samplers/per_operation.rb +79 -0
  34. data/lib/jaeger/samplers/probabilistic.rb +38 -0
  35. data/lib/jaeger/samplers/rate_limiting.rb +51 -0
  36. data/lib/jaeger/samplers/remote_controlled.rb +119 -0
  37. data/lib/jaeger/samplers/remote_controlled/instructions_fetcher.rb +34 -0
  38. data/lib/jaeger/scope.rb +38 -0
  39. data/lib/jaeger/scope_manager.rb +47 -0
  40. data/lib/jaeger/scope_manager/scope_identifier.rb +13 -0
  41. data/lib/jaeger/scope_manager/scope_stack.rb +33 -0
  42. data/lib/jaeger/span.rb +97 -0
  43. data/lib/jaeger/span/thrift_log_builder.rb +18 -0
  44. data/lib/jaeger/span_context.rb +57 -0
  45. data/lib/jaeger/thrift_tag_builder.rb +41 -0
  46. data/lib/jaeger/trace_id.rb +48 -0
  47. data/lib/jaeger/tracer.rb +213 -0
  48. data/lib/jaeger/udp_sender.rb +26 -0
  49. data/lib/jaeger/udp_sender/transport.rb +40 -0
  50. metadata +78 -31
  51. data/lib/jaeger/client/carrier.rb +0 -26
  52. data/lib/jaeger/client/encoders/thrift_encoder.rb +0 -94
  53. data/lib/jaeger/client/extractors.rb +0 -88
  54. data/lib/jaeger/client/http_sender.rb +0 -30
  55. data/lib/jaeger/client/injectors.rb +0 -54
  56. data/lib/jaeger/client/samplers.rb +0 -4
  57. data/lib/jaeger/client/samplers/const.rb +0 -29
  58. data/lib/jaeger/client/samplers/probabilistic.rb +0 -30
  59. data/lib/jaeger/client/scope.rb +0 -40
  60. data/lib/jaeger/client/scope_manager.rb +0 -49
  61. data/lib/jaeger/client/scope_manager/scope_identifier.rb +0 -15
  62. data/lib/jaeger/client/scope_manager/scope_stack.rb +0 -35
  63. data/lib/jaeger/client/span.rb +0 -84
  64. data/lib/jaeger/client/span/thrift_log_builder.rb +0 -20
  65. data/lib/jaeger/client/span/thrift_tag_builder.rb +0 -45
  66. data/lib/jaeger/client/span_context.rb +0 -59
  67. data/lib/jaeger/client/trace_id.rb +0 -41
  68. data/lib/jaeger/client/tracer.rb +0 -189
  69. data/lib/jaeger/client/udp_sender.rb +0 -27
  70. data/lib/jaeger/client/udp_sender/transport.rb +0 -42
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'logger'
4
-
5
- module Jaeger
6
- module Client
7
- class HttpSender
8
- def initialize(url:, headers: {}, encoder:, logger: Logger.new(STDOUT))
9
- @encoder = encoder
10
- @logger = logger
11
-
12
- @uri = URI(url)
13
- @uri.query = 'format=jaeger.thrift'
14
-
15
- @transport = ::Thrift::HTTPClientTransport.new(@uri.to_s)
16
- @transport.add_headers(headers)
17
-
18
- @serializer = ::Thrift::Serializer.new
19
- end
20
-
21
- def send_spans(spans)
22
- batch = @encoder.encode(spans)
23
- @transport.write(@serializer.serialize(batch))
24
- @transport.flush
25
- rescue StandardError => error
26
- @logger.error("Failure while sending a batch of spans: #{error}")
27
- end
28
- end
29
- end
30
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Jaeger
4
- module Client
5
- module Injectors
6
- class JaegerTextMapCodec
7
- def self.inject(span_context, carrier)
8
- carrier['uber-trace-id'] = [
9
- span_context.trace_id.to_s(16),
10
- span_context.span_id.to_s(16),
11
- span_context.parent_id.to_s(16),
12
- span_context.flags.to_s(16)
13
- ].join(':')
14
- end
15
- end
16
-
17
- class JaegerBinaryCodec
18
- def self.inject(_span_context, _carrier)
19
- warn 'Jaeger::Client with binary format is not supported yet'
20
- end
21
- end
22
-
23
- class B3RackCodec
24
- def self.inject(span_context, carrier)
25
- carrier['x-b3-traceid'] = TraceId.to_hex(span_context.trace_id)
26
- carrier['x-b3-spanid'] = TraceId.to_hex(span_context.span_id)
27
- carrier['x-b3-parentspanid'] = TraceId.to_hex(span_context.parent_id)
28
-
29
- # flags (for debug) and sampled headers are mutually exclusive
30
- if span_context.flags == Jaeger::Client::SpanContext::Flags::DEBUG
31
- carrier['x-b3-flags'] = '1'
32
- else
33
- carrier['x-b3-sampled'] = span_context.flags.to_s(16)
34
- end
35
- end
36
- end
37
-
38
- DEFAULT_INJECTORS = {
39
- OpenTracing::FORMAT_TEXT_MAP => JaegerTextMapCodec,
40
- OpenTracing::FORMAT_BINARY => JaegerBinaryCodec,
41
- OpenTracing::FORMAT_RACK => JaegerTextMapCodec
42
- }.freeze
43
-
44
- def self.prepare(extractors)
45
- DEFAULT_INJECTORS.reduce(extractors) do |acc, (format, default)|
46
- provided_extractors = Array(extractors[format])
47
- provided_extractors += [default] if provided_extractors.empty?
48
-
49
- acc.merge(format => provided_extractors)
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'samplers/const'
4
- require_relative 'samplers/probabilistic'
@@ -1,29 +0,0 @@
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
@@ -1,30 +0,0 @@
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
@@ -1,40 +0,0 @@
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
@@ -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,84 +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 = tags.map { |key, value| ThriftTagBuilder.build(key, value) }
27
- @logs = []
28
- end
29
-
30
- # Set a tag value on this span
31
- #
32
- # @param key [String] the key of the tag
33
- # @param value [String, Numeric, Boolean] the value of the tag. If it's not
34
- # a String, Numeric, or Boolean it will be encoded with to_s
35
- def set_tag(key, value)
36
- # Using Thrift::Tag to avoid unnecessary memory allocations
37
- @tags << ThriftTagBuilder.build(key, value)
38
- end
39
-
40
- # Set a baggage item on the span
41
- #
42
- # @param key [String] the key of the baggage item
43
- # @param value [String] the value of the baggage item
44
- def set_baggage_item(key, value)
45
- self
46
- end
47
-
48
- # Get a baggage item
49
- #
50
- # @param key [String] the key of the baggage item
51
- #
52
- # @return Value of the baggage item
53
- def get_baggage_item(key)
54
- nil
55
- end
56
-
57
- # Add a log entry to this span
58
- #
59
- # @deprecated Use {#log_kv} instead.
60
- def log(*args)
61
- warn 'Span#log is deprecated. Please use Span#log_kv instead.'
62
- log_kv(*args)
63
- end
64
-
65
- # Add a log entry to this span
66
- #
67
- # @param timestamp [Time] time of the log
68
- # @param fields [Hash] Additional information to log
69
- def log_kv(timestamp: Time.now, **fields)
70
- # Using Thrift::Log to avoid unnecessary memory allocations
71
- @logs << ThriftLogBuilder.build(timestamp, fields)
72
- nil
73
- end
74
-
75
- # Finish the {Span}
76
- #
77
- # @param end_time [Time] custom end time, if not now
78
- def finish(end_time: Time.now)
79
- @end_time = end_time
80
- @reporter.report(self)
81
- end
82
- end
83
- end
84
- 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