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 +4 -4
- data/.rubocop.yml +15 -0
- data/README.md +23 -3
- data/jaeger-client.gemspec +0 -1
- data/lib/jaeger/client.rb +12 -2
- data/lib/jaeger/client/carrier.rb +2 -0
- data/lib/jaeger/client/collector.rb +5 -23
- data/lib/jaeger/client/samplers.rb +4 -0
- data/lib/jaeger/client/samplers/const.rb +29 -0
- data/lib/jaeger/client/samplers/probabilistic.rb +30 -0
- data/lib/jaeger/client/scope.rb +40 -0
- data/lib/jaeger/client/scope_manager.rb +49 -0
- data/lib/jaeger/client/scope_manager/scope_identifier.rb +15 -0
- data/lib/jaeger/client/scope_manager/scope_stack.rb +35 -0
- data/lib/jaeger/client/span.rb +20 -12
- data/lib/jaeger/client/span/thrift_log_builder.rb +20 -0
- data/lib/jaeger/client/span/thrift_tag_builder.rb +45 -0
- data/lib/jaeger/client/span_context.rb +13 -2
- data/lib/jaeger/client/trace_id.rb +2 -0
- data/lib/jaeger/client/tracer.rb +117 -11
- data/lib/jaeger/client/udp_sender.rb +2 -1
- data/lib/jaeger/client/udp_sender/transport.rb +5 -2
- data/lib/jaeger/client/version.rb +3 -1
- data/script/create_trace +2 -1
- metadata +11 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 180ed5153f692c630fd0e0006b3d6265c5839875
|
|
4
|
+
data.tar.gz: 98dea74437333796b07bf81afba0558652b51623
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
1
|
+
Jaeger::Client
|
|
2
|
+
================
|
|
3
|
+
[](https://rubygems.org/gems/jaeger-client)
|
|
4
|
+
[](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
|
-
|
|
20
|
-
|
|
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.
|
data/jaeger-client.gemspec
CHANGED
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',
|
|
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
|
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' =>
|
|
25
|
-
'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,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
|
data/lib/jaeger/client/span.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
55
|
-
|
|
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
|
data/lib/jaeger/client/tracer.rb
CHANGED
|
@@ -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
|
-
#
|
|
18
|
-
#
|
|
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,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
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,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
|
-
@
|
|
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'
|
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.
|
|
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
|
+
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-
|
|
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
|