zipkin 1.6.0 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/zipkin/async_reporter.rb +39 -0
- data/lib/zipkin/async_reporter/buffer.rb +27 -0
- data/lib/zipkin/encoders.rb +3 -0
- data/lib/zipkin/encoders/json_encoder.rb +104 -0
- data/lib/zipkin/encoders/json_encoder/log_annotations.rb +34 -0
- data/lib/zipkin/encoders/json_encoder/timestamp.rb +13 -0
- data/lib/zipkin/endpoint.rb +19 -15
- data/lib/zipkin/{json_client.rb → http_client.rb} +6 -26
- data/lib/zipkin/span.rb +7 -6
- data/lib/zipkin/tracer.rb +12 -19
- data/script/create_follows_from_trace +3 -5
- data/script/create_http_trace +56 -0
- data/script/create_trace +34 -20
- data/zipkin.gemspec +1 -1
- metadata +11 -7
- data/lib/zipkin/collector.rb +0 -71
- data/lib/zipkin/collector/log_annotations.rb +0 -27
- data/lib/zipkin/collector/timestamp.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3b88fff10737cc10e0da917018436f4e0085e2f8bf384605fec56e84450595d3
|
4
|
+
data.tar.gz: 51ca7b5a0e4b1fca2a9eeeb02f73c9d139fe8cfaf78165850951cbb4d59bab09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c68750c7f6758f4d81d9efd045e040b30afcc36e0679c5f0f12b8623a69f2bdc7fec0ca58ee56bbd1080f710e6449e601b3a5e486e45ea6892aaf1fce942f51
|
7
|
+
data.tar.gz: 52a89cb097adfa8ff282ae95d10a22c2c799782ad13fb356769ef2e8f66830390c2e7e18280dc8bb1de969490d090fb98a2542721a11c8d9901f910b8a5e0bae
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
|
5
|
+
require_relative './async_reporter/buffer'
|
6
|
+
|
7
|
+
module Zipkin
|
8
|
+
class AsyncReporter
|
9
|
+
def self.create(sender:, flush_interval:)
|
10
|
+
reporter = new(sender)
|
11
|
+
|
12
|
+
# start flush thread
|
13
|
+
Thread.new do
|
14
|
+
loop do
|
15
|
+
reporter.flush
|
16
|
+
sleep(flush_interval)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
reporter
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(sender)
|
24
|
+
@sender = sender
|
25
|
+
@buffer = Buffer.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def flush
|
29
|
+
spans = @buffer.retrieve
|
30
|
+
@sender.send_spans(spans) if spans.any?
|
31
|
+
spans
|
32
|
+
end
|
33
|
+
|
34
|
+
def report(span)
|
35
|
+
return unless span.context.sampled?
|
36
|
+
@buffer << span
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zipkin
|
4
|
+
class AsyncReporter
|
5
|
+
class Buffer
|
6
|
+
def initialize
|
7
|
+
@buffer = []
|
8
|
+
@mutex = Mutex.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(element)
|
12
|
+
@mutex.synchronize do
|
13
|
+
@buffer << element
|
14
|
+
true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def retrieve
|
19
|
+
@mutex.synchronize do
|
20
|
+
elements = @buffer.dup
|
21
|
+
@buffer.clear
|
22
|
+
elements
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require_relative 'json_encoder/timestamp'
|
6
|
+
require_relative 'json_encoder/log_annotations'
|
7
|
+
|
8
|
+
module Zipkin
|
9
|
+
module Encoders
|
10
|
+
class JsonEncoder
|
11
|
+
OT_KIND_TO_ZIPKIN_KIND = {
|
12
|
+
'server' => 'SERVER',
|
13
|
+
'client' => 'CLIENT',
|
14
|
+
'producer' => 'PRODUCER',
|
15
|
+
'consumer' => 'CONSUMER'
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
CONTENT_TYPE = 'application/json'.freeze
|
19
|
+
|
20
|
+
module Fields
|
21
|
+
TRACE_ID = 'traceId'.freeze
|
22
|
+
SPAN_ID = 'id'.freeze
|
23
|
+
PARENT_ID = 'parentId'.freeze
|
24
|
+
OPERATION_NAME = 'name'.freeze
|
25
|
+
KIND = 'kind'.freeze
|
26
|
+
TIMESTAMP = 'timestamp'.freeze
|
27
|
+
DURATION = 'duration'.freeze
|
28
|
+
DEBUG = 'debug'.freeze
|
29
|
+
SHARED = 'shared'.freeze
|
30
|
+
LOCAL_ENDPOINT = 'localEndpoint'.freeze
|
31
|
+
REMOTE_ENDPOINT = 'remoteEndpoint'.freeze
|
32
|
+
ANNOTATIONS = 'annotations'.freeze
|
33
|
+
TAGS = 'tags'.freeze
|
34
|
+
|
35
|
+
module Endpoint
|
36
|
+
SERVICE_NAME = 'serviceName'.freeze
|
37
|
+
IPV4 = 'ipv4'.freeze
|
38
|
+
IPV6 = 'ipv6'.freeze
|
39
|
+
PORT = 'port'.freeze
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(local_endpoint)
|
44
|
+
@adapter = defined?(Oj) ? OjAdapter : JsonAdapter
|
45
|
+
@local_endpoint = serialize_endpoint(local_endpoint)
|
46
|
+
end
|
47
|
+
|
48
|
+
def content_type
|
49
|
+
CONTENT_TYPE
|
50
|
+
end
|
51
|
+
|
52
|
+
def encode(spans)
|
53
|
+
@adapter.dump(spans.map(&method(:serialize)))
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def serialize(span)
|
59
|
+
finish_ts = Timestamp.create(span.end_time)
|
60
|
+
start_ts = Timestamp.create(span.start_time)
|
61
|
+
duration = finish_ts - start_ts
|
62
|
+
|
63
|
+
{
|
64
|
+
Fields::TRACE_ID => span.context.trace_id,
|
65
|
+
Fields::SPAN_ID => span.context.span_id,
|
66
|
+
Fields::PARENT_ID => span.context.parent_id,
|
67
|
+
Fields::OPERATION_NAME => span.operation_name,
|
68
|
+
Fields::KIND => OT_KIND_TO_ZIPKIN_KIND[span.tags[:'span.kind'] || 'server'],
|
69
|
+
Fields::TIMESTAMP => start_ts,
|
70
|
+
Fields::DURATION => duration,
|
71
|
+
Fields::DEBUG => false,
|
72
|
+
Fields::SHARED => false,
|
73
|
+
Fields::LOCAL_ENDPOINT => @local_endpoint,
|
74
|
+
Fields::REMOTE_ENDPOINT => serialize_endpoint(Endpoint.remote_endpoint(span)),
|
75
|
+
Fields::ANNOTATIONS => LogAnnotations.build(span),
|
76
|
+
Fields::TAGS => span.tags
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def serialize_endpoint(endpoint)
|
81
|
+
return nil unless endpoint
|
82
|
+
|
83
|
+
{
|
84
|
+
Fields::Endpoint::SERVICE_NAME => endpoint.service_name,
|
85
|
+
Fields::Endpoint::IPV4 => endpoint.ipv4,
|
86
|
+
Fields::Endpoint::IPV6 => endpoint.ipv6,
|
87
|
+
Fields::Endpoint::PORT => endpoint.port
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
module OjAdapter
|
92
|
+
def self.dump(payload)
|
93
|
+
Oj.dump(payload, mode: :object)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
module JsonAdapter
|
98
|
+
def self.dump(payload)
|
99
|
+
JSON.dump(payload)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Zipkin
|
4
|
+
module Encoders
|
5
|
+
class JsonEncoder
|
6
|
+
module LogAnnotations
|
7
|
+
module Fields
|
8
|
+
TIMESTAMP = 'timestamp'.freeze
|
9
|
+
VALUE = 'value'.freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.build(span)
|
13
|
+
span.logs.map do |log|
|
14
|
+
{
|
15
|
+
Fields::TIMESTAMP => Timestamp.create(log.fetch(:timestamp)),
|
16
|
+
Fields::VALUE => format_log_value(log)
|
17
|
+
}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.format_log_value(log)
|
22
|
+
if log.keys == %i[event timestamp]
|
23
|
+
log.fetch(:event)
|
24
|
+
else
|
25
|
+
log
|
26
|
+
.reject { |key, _value| key == :timestamp }
|
27
|
+
.map { |key, value| "#{key}=#{value}" }
|
28
|
+
.join(' ')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/zipkin/endpoint.rb
CHANGED
@@ -17,10 +17,10 @@ module Zipkin
|
|
17
17
|
end
|
18
18
|
|
19
19
|
module PeerInfo
|
20
|
-
SERVICE =
|
21
|
-
IPV4 =
|
22
|
-
IPV6 =
|
23
|
-
PORT =
|
20
|
+
SERVICE = 'peer.service'.freeze
|
21
|
+
IPV4 = 'peer.ipv4'.freeze
|
22
|
+
IPV6 = 'peer.ipv6'.freeze
|
23
|
+
PORT = 'peer.port'.freeze
|
24
24
|
|
25
25
|
def self.keys
|
26
26
|
[SERVICE, IPV4, IPV6, PORT]
|
@@ -28,34 +28,38 @@ module Zipkin
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.local_endpoint(service_name)
|
31
|
-
|
32
|
-
serviceName: service_name,
|
33
|
-
ipv4: LOCAL_IP
|
34
|
-
}
|
31
|
+
new(service_name: service_name, ipv4: LOCAL_IP)
|
35
32
|
end
|
36
33
|
|
37
34
|
def self.remote_endpoint(span)
|
38
35
|
tags = span.tags
|
39
|
-
kind = tags[
|
36
|
+
kind = tags['span.kind'] || SpanKind::SERVER
|
40
37
|
|
41
38
|
case kind
|
42
39
|
when SpanKind::SERVER, SpanKind::CLIENT
|
43
40
|
return nil if (tags.keys & PeerInfo.keys).empty?
|
44
41
|
|
45
|
-
|
46
|
-
|
42
|
+
new(
|
43
|
+
service_name: tags[PeerInfo::SERVICE],
|
47
44
|
ipv4: tags[PeerInfo::IPV4],
|
48
45
|
ipv6: tags[PeerInfo::IPV6],
|
49
46
|
port: tags[PeerInfo::PORT]
|
50
|
-
|
47
|
+
)
|
51
48
|
when SpanKind::PRODUCER, SpanKind::CONSUMER
|
52
|
-
|
53
|
-
serviceName: 'broker'
|
54
|
-
}
|
49
|
+
new(service_name: 'broker')
|
55
50
|
else
|
56
51
|
warn "Unkown span kind: #{kind}"
|
57
52
|
nil
|
58
53
|
end
|
59
54
|
end
|
55
|
+
|
56
|
+
def initialize(service_name: nil, ipv4: nil, ipv6: nil, port: nil)
|
57
|
+
@service_name = service_name
|
58
|
+
@ipv4 = ipv4
|
59
|
+
@ipv6 = ipv6
|
60
|
+
@port = port
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_reader :service_name, :ipv4, :ipv6, :port
|
60
64
|
end
|
61
65
|
end
|
@@ -2,43 +2,23 @@
|
|
2
2
|
|
3
3
|
require 'net/http'
|
4
4
|
require 'uri'
|
5
|
-
require 'json'
|
6
5
|
|
7
6
|
module Zipkin
|
8
|
-
class
|
9
|
-
def initialize(url:,
|
10
|
-
@
|
11
|
-
@flush_interval = flush_interval
|
7
|
+
class HTTPClient
|
8
|
+
def initialize(url:, encoder:, logger:)
|
9
|
+
@encoder = encoder
|
12
10
|
@spans_uri = URI.parse("#{url}/api/v2/spans")
|
13
11
|
@logger = logger
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
@thread = Thread.new do
|
18
|
-
loop do
|
19
|
-
emit_batch(@collector.retrieve)
|
20
|
-
sleep @flush_interval
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def stop
|
26
|
-
@thread.terminate if @thread
|
27
|
-
emit_batch(@collector.retrieve)
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def emit_batch(spans)
|
33
|
-
return if spans.empty?
|
34
|
-
|
14
|
+
def send_spans(spans)
|
35
15
|
http = Net::HTTP.new(@spans_uri.host, @spans_uri.port)
|
36
16
|
http.use_ssl = @spans_uri.scheme == 'https'
|
37
17
|
request = Net::HTTP::Post.new(
|
38
18
|
@spans_uri.request_uri,
|
39
|
-
'Content-Type' =>
|
19
|
+
'Content-Type' => @encoder.content_type
|
40
20
|
)
|
41
|
-
request.body =
|
21
|
+
request.body = @encoder.encode(spans)
|
42
22
|
response = http.request(request)
|
43
23
|
|
44
24
|
if response.code != '202'
|
data/lib/zipkin/span.rb
CHANGED
@@ -4,26 +4,26 @@ module Zipkin
|
|
4
4
|
class Span
|
5
5
|
attr_accessor :operation_name
|
6
6
|
|
7
|
-
attr_reader :context, :start_time, :tags, :logs, :references
|
7
|
+
attr_reader :context, :start_time, :end_time, :tags, :logs, :references
|
8
8
|
|
9
9
|
# Creates a new {Span}
|
10
10
|
#
|
11
11
|
# @param context [SpanContext] the context of the span
|
12
12
|
# @param operation_name [String] the operation name
|
13
|
-
# @param
|
13
|
+
# @param reporter [#report] the span reporter
|
14
14
|
#
|
15
15
|
# @return [Span] a new Span
|
16
16
|
def initialize(
|
17
17
|
context,
|
18
18
|
operation_name,
|
19
|
-
|
19
|
+
reporter,
|
20
20
|
start_time: Time.now,
|
21
21
|
tags: {},
|
22
22
|
references: nil
|
23
23
|
)
|
24
24
|
@context = context
|
25
25
|
@operation_name = operation_name
|
26
|
-
@
|
26
|
+
@reporter = reporter
|
27
27
|
@start_time = start_time
|
28
28
|
@tags = {}
|
29
29
|
@logs = []
|
@@ -39,7 +39,7 @@ module Zipkin
|
|
39
39
|
# a String, Numeric, or Boolean it will be encoded with to_s
|
40
40
|
def set_tag(key, value)
|
41
41
|
sanitized_value = valid_tag_value?(value) ? value : value.to_s
|
42
|
-
@tags = @tags.merge(key.
|
42
|
+
@tags = @tags.merge(key.to_s => sanitized_value)
|
43
43
|
end
|
44
44
|
|
45
45
|
# Set a baggage item on the span
|
@@ -80,7 +80,8 @@ module Zipkin
|
|
80
80
|
#
|
81
81
|
# @param end_time [Time] custom end time, if not now
|
82
82
|
def finish(end_time: Time.now)
|
83
|
-
@
|
83
|
+
@end_time = end_time
|
84
|
+
@reporter.report(self)
|
84
85
|
end
|
85
86
|
|
86
87
|
private
|
data/lib/zipkin/tracer.rb
CHANGED
@@ -7,12 +7,13 @@ require_relative 'span'
|
|
7
7
|
require_relative 'span_context'
|
8
8
|
require_relative 'carrier'
|
9
9
|
require_relative 'trace_id'
|
10
|
-
require_relative '
|
10
|
+
require_relative 'http_client'
|
11
11
|
require_relative 'endpoint'
|
12
|
-
require_relative '
|
12
|
+
require_relative 'async_reporter'
|
13
13
|
require_relative 'scope_manager'
|
14
14
|
require_relative 'scope'
|
15
15
|
require_relative 'samplers'
|
16
|
+
require_relative 'encoders'
|
16
17
|
|
17
18
|
module Zipkin
|
18
19
|
class Tracer
|
@@ -22,30 +23,22 @@ module Zipkin
|
|
22
23
|
service_name:,
|
23
24
|
flush_interval: DEFAULT_FLUSH_INTERVAL,
|
24
25
|
logger: Logger.new(STDOUT),
|
25
|
-
sampler: Samplers::Const.new(true)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
logger: logger
|
32
|
-
)
|
33
|
-
sender.start
|
34
|
-
new(collector, sender, logger: logger, sampler: sampler)
|
26
|
+
sampler: Samplers::Const.new(true),
|
27
|
+
encoder: Encoders::JsonEncoder)
|
28
|
+
encoder = encoder.new(Endpoint.local_endpoint(service_name))
|
29
|
+
sender = HTTPClient.new(url: url, encoder: encoder, logger: logger)
|
30
|
+
reporter = AsyncReporter.create(sender: sender, flush_interval: flush_interval)
|
31
|
+
new(reporter, sender, logger: logger, sampler: sampler)
|
35
32
|
end
|
36
33
|
|
37
|
-
def initialize(
|
38
|
-
@
|
34
|
+
def initialize(reporter, sender, logger: Logger.new(STDOUT), sampler:)
|
35
|
+
@reporter = reporter
|
39
36
|
@sender = sender
|
40
37
|
@logger = logger
|
41
38
|
@scope_manager = ScopeManager.new
|
42
39
|
@sampler = sampler
|
43
40
|
end
|
44
41
|
|
45
|
-
def stop
|
46
|
-
@sender.stop
|
47
|
-
end
|
48
|
-
|
49
42
|
# @return [ScopeManager] the current ScopeManager, which may be a no-op but
|
50
43
|
# may not be nil.
|
51
44
|
attr_reader :scope_manager
|
@@ -93,7 +86,7 @@ module Zipkin
|
|
93
86
|
Span.new(
|
94
87
|
context,
|
95
88
|
operation_name,
|
96
|
-
@
|
89
|
+
@reporter,
|
97
90
|
start_time: start_time,
|
98
91
|
references: references,
|
99
92
|
tags: tags || {}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'bundler'
|
4
5
|
Bundler.setup
|
@@ -7,8 +8,8 @@ require 'zipkin/tracer'
|
|
7
8
|
|
8
9
|
url = ENV['ZIPKIN_URL'] || 'http://localhost:9411'
|
9
10
|
|
10
|
-
tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service')
|
11
|
-
tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service')
|
11
|
+
tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service', flush_interval: 1)
|
12
|
+
tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service', flush_interval: 1)
|
12
13
|
|
13
14
|
rpc_span = tracer1.start_span(
|
14
15
|
'receive request',
|
@@ -45,7 +46,4 @@ async_span = tracer2.start_span(
|
|
45
46
|
sleep 0.3 # emulate network delay
|
46
47
|
async_span.finish
|
47
48
|
|
48
|
-
tracer1.stop
|
49
|
-
tracer2.stop
|
50
|
-
|
51
49
|
puts 'Finished'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler'
|
5
|
+
Bundler.setup
|
6
|
+
|
7
|
+
require 'zipkin/tracer'
|
8
|
+
|
9
|
+
url = ENV['ZIPKIN_URL'] || 'http://localhost:9411'
|
10
|
+
|
11
|
+
tracer1 = Zipkin::Tracer.build(url: url, service_name: 'user-service', flush_interval: 1)
|
12
|
+
tracer2 = Zipkin::Tracer.build(url: url, service_name: 'name-service', flush_interval: 1)
|
13
|
+
|
14
|
+
root_span = tracer1.start_span(
|
15
|
+
'GET /users/:id',
|
16
|
+
tags: {
|
17
|
+
'span.kind' => 'server',
|
18
|
+
'http.method' => 'get',
|
19
|
+
'http.url' => 'http://example.com/users/5'
|
20
|
+
}
|
21
|
+
)
|
22
|
+
sleep 1
|
23
|
+
|
24
|
+
fetch_name_span = tracer1.start_span(
|
25
|
+
'get',
|
26
|
+
child_of: root_span,
|
27
|
+
tags: {
|
28
|
+
'span.kind' => 'client',
|
29
|
+
'http.method' => 'get',
|
30
|
+
'http.url' => 'GET /users/5/name'
|
31
|
+
}
|
32
|
+
)
|
33
|
+
sleep 0.3 # emulate network delay
|
34
|
+
|
35
|
+
name_service_span = tracer2.start_span(
|
36
|
+
'GET /users/:id/name',
|
37
|
+
child_of: fetch_name_span,
|
38
|
+
tags: {
|
39
|
+
'span.kind' => 'server',
|
40
|
+
'http.method' => 'get',
|
41
|
+
'http.url' => 'http://example.com/users/5/name'
|
42
|
+
}
|
43
|
+
)
|
44
|
+
sleep 0.5
|
45
|
+
name_service_span.finish
|
46
|
+
|
47
|
+
sleep 0.2 # emulate network delay
|
48
|
+
fetch_name_span.finish
|
49
|
+
|
50
|
+
sleep 0.1 # doing something with fetched info
|
51
|
+
root_span.finish
|
52
|
+
|
53
|
+
puts 'Finishing...'
|
54
|
+
sleep 3
|
55
|
+
|
56
|
+
puts 'Finished'
|
data/script/create_trace
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'bundler'
|
4
5
|
Bundler.setup
|
@@ -7,10 +8,10 @@ require 'zipkin/tracer'
|
|
7
8
|
|
8
9
|
url = ENV['ZIPKIN_URL'] || 'http://localhost:9411'
|
9
10
|
|
10
|
-
tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service')
|
11
|
-
tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service')
|
11
|
+
tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service', flush_interval: 1)
|
12
|
+
tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service-1', flush_interval: 1)
|
12
13
|
|
13
|
-
|
14
|
+
root_span = tracer1.start_span(
|
14
15
|
'receive request',
|
15
16
|
tags: {
|
16
17
|
'span.kind' => 'server'
|
@@ -18,39 +19,52 @@ outer_span = tracer1.start_span(
|
|
18
19
|
)
|
19
20
|
sleep 1
|
20
21
|
|
21
|
-
|
22
|
-
'fetch info from
|
23
|
-
child_of:
|
22
|
+
fetch_info_from_service1_span = tracer1.start_span(
|
23
|
+
'fetch info from service 1',
|
24
|
+
child_of: root_span,
|
24
25
|
tags: {
|
25
26
|
'span.kind' => 'client',
|
26
|
-
'peer.
|
27
|
-
'peer.ipv4' => '6.6.6.6',
|
27
|
+
'peer.ipv4' => '2.2.2.2',
|
28
28
|
'peer.port' => 443
|
29
29
|
}
|
30
30
|
)
|
31
31
|
sleep 0.3 # emulate network delay
|
32
32
|
|
33
|
-
|
34
|
-
'
|
35
|
-
child_of:
|
36
|
-
tags: {
|
33
|
+
service1_span = tracer2.start_span(
|
34
|
+
'service 1 operation',
|
35
|
+
child_of: fetch_info_from_service1_span,
|
36
|
+
tags: {
|
37
|
+
'span.kind' => 'server',
|
38
|
+
'peer.ipv4' => '1.1.1.1',
|
39
|
+
'peer.port' => 443
|
40
|
+
}
|
37
41
|
)
|
38
|
-
|
39
|
-
|
42
|
+
service1_span.log_kv(event: 'custom-event')
|
43
|
+
service1_span.log_kv(foo: 'bar', baz: 'buz')
|
40
44
|
sleep 0.5
|
41
|
-
|
45
|
+
service1_span.finish
|
42
46
|
|
43
47
|
sleep 0.2 # emulate network delay
|
44
48
|
|
45
|
-
|
49
|
+
fetch_info_from_service1_span.finish
|
50
|
+
|
51
|
+
fetch_info_from_service2_span = tracer1.start_span(
|
52
|
+
'fetch info from service 2 which does not have tracing',
|
53
|
+
child_of: root_span,
|
54
|
+
tags: {
|
55
|
+
'span.kind' => 'client',
|
56
|
+
'peer.service' => 'downstream-service-2',
|
57
|
+
'peer.ipv4' => '3.3.3.3',
|
58
|
+
'peer.port' => 443
|
59
|
+
}
|
60
|
+
)
|
61
|
+
sleep 0.3 # emulate network delay
|
62
|
+
fetch_info_from_service2_span.finish
|
46
63
|
|
47
64
|
sleep 0.1 # doing something with fetched info
|
48
|
-
|
65
|
+
root_span.finish
|
49
66
|
|
50
67
|
puts 'Finishing...'
|
51
68
|
sleep 3
|
52
69
|
|
53
|
-
tracer1.stop
|
54
|
-
tracer2.stop
|
55
|
-
|
56
70
|
puts 'Finished'
|
data/zipkin.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zipkin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.1
|
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-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -126,12 +126,15 @@ files:
|
|
126
126
|
- bin/console
|
127
127
|
- bin/setup
|
128
128
|
- lib/zipkin.rb
|
129
|
+
- lib/zipkin/async_reporter.rb
|
130
|
+
- lib/zipkin/async_reporter/buffer.rb
|
129
131
|
- lib/zipkin/carrier.rb
|
130
|
-
- lib/zipkin/
|
131
|
-
- lib/zipkin/
|
132
|
-
- lib/zipkin/
|
132
|
+
- lib/zipkin/encoders.rb
|
133
|
+
- lib/zipkin/encoders/json_encoder.rb
|
134
|
+
- lib/zipkin/encoders/json_encoder/log_annotations.rb
|
135
|
+
- lib/zipkin/encoders/json_encoder/timestamp.rb
|
133
136
|
- lib/zipkin/endpoint.rb
|
134
|
-
- lib/zipkin/
|
137
|
+
- lib/zipkin/http_client.rb
|
135
138
|
- lib/zipkin/samplers.rb
|
136
139
|
- lib/zipkin/samplers/const.rb
|
137
140
|
- lib/zipkin/samplers/probabilistic.rb
|
@@ -144,6 +147,7 @@ files:
|
|
144
147
|
- lib/zipkin/trace_id.rb
|
145
148
|
- lib/zipkin/tracer.rb
|
146
149
|
- script/create_follows_from_trace
|
150
|
+
- script/create_http_trace
|
147
151
|
- script/create_trace
|
148
152
|
- zipkin.gemspec
|
149
153
|
homepage: ''
|
@@ -166,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
166
170
|
version: '0'
|
167
171
|
requirements: []
|
168
172
|
rubyforge_project:
|
169
|
-
rubygems_version: 2.6
|
173
|
+
rubygems_version: 2.7.6
|
170
174
|
signing_key:
|
171
175
|
specification_version: 4
|
172
176
|
summary: OpenTracing Tracer implementation for Zipkin in Ruby
|
data/lib/zipkin/collector.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'thread'
|
4
|
-
|
5
|
-
require_relative './collector/timestamp'
|
6
|
-
require_relative './collector/log_annotations'
|
7
|
-
|
8
|
-
module Zipkin
|
9
|
-
class Collector
|
10
|
-
OT_KIND_TO_ZIPKIN_KIND = {
|
11
|
-
'server' => 'SERVER',
|
12
|
-
'client' => 'CLIENT',
|
13
|
-
'producer' => 'PRODUCER',
|
14
|
-
'consumer' => 'CONSUMER'
|
15
|
-
}.freeze
|
16
|
-
|
17
|
-
def initialize(local_endpoint)
|
18
|
-
@buffer = Buffer.new
|
19
|
-
@local_endpoint = local_endpoint
|
20
|
-
end
|
21
|
-
|
22
|
-
def retrieve
|
23
|
-
@buffer.retrieve
|
24
|
-
end
|
25
|
-
|
26
|
-
def send_span(span, end_time)
|
27
|
-
finish_ts = Timestamp.create(end_time)
|
28
|
-
start_ts = Timestamp.create(span.start_time)
|
29
|
-
duration = finish_ts - start_ts
|
30
|
-
return unless span.context.sampled?
|
31
|
-
|
32
|
-
@buffer << {
|
33
|
-
traceId: span.context.trace_id,
|
34
|
-
id: span.context.span_id,
|
35
|
-
parentId: span.context.parent_id,
|
36
|
-
name: span.operation_name,
|
37
|
-
kind: OT_KIND_TO_ZIPKIN_KIND[span.tags[:'span.kind'] || 'server'],
|
38
|
-
timestamp: start_ts,
|
39
|
-
duration: duration,
|
40
|
-
debug: false,
|
41
|
-
shared: false,
|
42
|
-
localEndpoint: @local_endpoint,
|
43
|
-
remoteEndpoint: Endpoint.remote_endpoint(span),
|
44
|
-
annotations: LogAnnotations.build(span),
|
45
|
-
tags: span.tags
|
46
|
-
}
|
47
|
-
end
|
48
|
-
|
49
|
-
class Buffer
|
50
|
-
def initialize
|
51
|
-
@buffer = []
|
52
|
-
@mutex = Mutex.new
|
53
|
-
end
|
54
|
-
|
55
|
-
def <<(element)
|
56
|
-
@mutex.synchronize do
|
57
|
-
@buffer << element
|
58
|
-
true
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def retrieve
|
63
|
-
@mutex.synchronize do
|
64
|
-
elements = @buffer.dup
|
65
|
-
@buffer.clear
|
66
|
-
elements
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Zipkin
|
4
|
-
class Collector
|
5
|
-
module LogAnnotations
|
6
|
-
def self.build(span)
|
7
|
-
span.logs.map do |log|
|
8
|
-
{
|
9
|
-
timestamp: Timestamp.create(log.fetch(:timestamp)),
|
10
|
-
value: format_log_value(log)
|
11
|
-
}
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.format_log_value(log)
|
16
|
-
if log.keys == %i[event timestamp]
|
17
|
-
log.fetch(:event)
|
18
|
-
else
|
19
|
-
log
|
20
|
-
.reject { |key, _value| key == :timestamp }
|
21
|
-
.map { |key, value| "#{key}=#{value}" }
|
22
|
-
.join(' ')
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|