zipkin-tracer 0.32.4 → 0.33.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/lib/zipkin-tracer/excon/zipkin-tracer.rb +9 -19
- data/lib/zipkin-tracer/faraday/zipkin-tracer.rb +14 -19
- data/lib/zipkin-tracer/hostname_resolver.rb +10 -15
- data/lib/zipkin-tracer/rack/zipkin-tracer.rb +2 -3
- data/lib/zipkin-tracer/rack/zipkin_env.rb +5 -3
- data/lib/zipkin-tracer/trace.rb +38 -54
- data/lib/zipkin-tracer/version.rb +1 -1
- data/lib/zipkin-tracer/zipkin_json_tracer.rb +1 -1
- data/lib/zipkin-tracer/zipkin_tracer_base.rb +3 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0da9730b55f7aa56b8b1080b4de79c731e6e09997e1c8ed958f0954d9f9acd70
|
4
|
+
data.tar.gz: 5a780069dfa04fe86a86fd805c89f00db11ba5af1f29057625b90d6aa03adf87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 95aab26491cde2e63b9d1e8a304b0edbac6658ee524143b202e53486a5f5552e738749fd16b274b74e7fc894c0d8bc30097e5bca2a5a26441815df662c389b3d
|
7
|
+
data.tar.gz: 8826d81412e97b9f0dd1c551bebd959b56782a690a76779d7da81169259c6bcad14cb8a5674c92d7fc6384ef55f5db932aad6d601628339c056439279632f5c7
|
@@ -28,10 +28,7 @@ module ZipkinTracer
|
|
28
28
|
def response_call(datum)
|
29
29
|
if span = datum[:span]
|
30
30
|
status = response_status(datum)
|
31
|
-
if status
|
32
|
-
record_response_tags(span, status, local_endpoint)
|
33
|
-
end
|
34
|
-
span.record(Trace::Annotation::CLIENT_RECV, local_endpoint)
|
31
|
+
record_response_tags(span, status) if status
|
35
32
|
Trace.tracer.end_span(span)
|
36
33
|
end
|
37
34
|
|
@@ -53,12 +50,8 @@ module ZipkinTracer
|
|
53
50
|
}
|
54
51
|
end
|
55
52
|
|
56
|
-
def local_endpoint
|
57
|
-
Trace.default_endpoint # The rack middleware set this up for us.
|
58
|
-
end
|
59
|
-
|
60
53
|
def remote_endpoint(url, service_name)
|
61
|
-
Trace::Endpoint.remote_endpoint(url, service_name,
|
54
|
+
Trace::Endpoint.remote_endpoint(url, service_name, Trace.default_endpoint.ip_format) # The endpoint we are calling.
|
62
55
|
end
|
63
56
|
|
64
57
|
def service_name(datum, default)
|
@@ -69,12 +62,9 @@ module ZipkinTracer
|
|
69
62
|
datum[:response] && datum[:response][:status] && datum[:response][:status].to_s
|
70
63
|
end
|
71
64
|
|
72
|
-
def record_response_tags(span, status
|
73
|
-
span.record_tag(Trace::
|
74
|
-
if STATUS_ERROR_REGEXP.match(status)
|
75
|
-
span.record_tag(Trace::BinaryAnnotation::ERROR, status,
|
76
|
-
Trace::BinaryAnnotation::Type::STRING, local_endpoint)
|
77
|
-
end
|
65
|
+
def record_response_tags(span, status)
|
66
|
+
span.record_tag(Trace::Span::Tag::STATUS, status)
|
67
|
+
span.record_tag(Trace::Span::Tag::ERROR, status) if STATUS_ERROR_REGEXP.match(status)
|
78
68
|
end
|
79
69
|
|
80
70
|
def trace!(datum, trace_id)
|
@@ -85,10 +75,10 @@ module ZipkinTracer
|
|
85
75
|
|
86
76
|
span = Trace.tracer.start_span(trace_id, method.downcase)
|
87
77
|
# annotate with method (GET/POST/etc.) and uri path
|
88
|
-
span.
|
89
|
-
span.
|
90
|
-
span.record_tag(Trace::
|
91
|
-
span.
|
78
|
+
span.kind = Trace::Span::Kind::CLIENT
|
79
|
+
span.remote_endpoint = remote_endpoint(url, service_name)
|
80
|
+
span.record_tag(Trace::Span::Tag::METHOD, method.upcase)
|
81
|
+
span.record_tag(Trace::Span::Tag::PATH, url.path)
|
92
82
|
|
93
83
|
# store the span in the datum hash so it can be used in the response_call
|
94
84
|
datum[:span] = span
|
@@ -44,42 +44,37 @@ module ZipkinTracer
|
|
44
44
|
# handle either a URI object (passed by Faraday v0.8.x in testing), or something string-izable
|
45
45
|
method = env[:method].to_s
|
46
46
|
url = env[:url].respond_to?(:host) ? env[:url] : URI.parse(env[:url].to_s)
|
47
|
-
|
48
|
-
remote_endpoint = Trace::Endpoint.remote_endpoint(url, @service_name, local_endpoint.ip_format) # The endpoint we are calling.
|
47
|
+
remote_endpoint = Trace::Endpoint.remote_endpoint(url, @service_name, Trace.default_endpoint.ip_format) # The endpoint we are calling.
|
49
48
|
Trace.tracer.with_new_span(trace_id, method.downcase) do |span|
|
50
49
|
@span = span # So we can record on exceptions
|
51
50
|
# annotate with method (GET/POST/etc.) and uri path
|
52
|
-
span.
|
53
|
-
span.
|
54
|
-
span.record_tag(Trace::
|
55
|
-
span.
|
51
|
+
span.kind = Trace::Span::Kind::CLIENT
|
52
|
+
span.remote_endpoint = remote_endpoint
|
53
|
+
span.record_tag(Trace::Span::Tag::METHOD, method.upcase)
|
54
|
+
span.record_tag(Trace::Span::Tag::PATH, url.path)
|
56
55
|
response = @app.call(env).on_complete do |renv|
|
57
|
-
record_response_tags(span, renv[:status].to_s
|
56
|
+
record_response_tags(span, renv[:status].to_s)
|
58
57
|
end
|
59
|
-
span.record(Trace::Annotation::CLIENT_RECV, local_endpoint)
|
60
58
|
end
|
61
59
|
response
|
62
60
|
rescue Net::ReadTimeout
|
63
|
-
record_error(@span, 'Request timed out.'
|
61
|
+
record_error(@span, 'Request timed out.')
|
64
62
|
raise
|
65
63
|
rescue Faraday::ConnectionFailed
|
66
|
-
record_error(@span, 'Request connection failed.'
|
64
|
+
record_error(@span, 'Request connection failed.')
|
67
65
|
raise
|
68
66
|
rescue Faraday::ClientError
|
69
|
-
record_error(@span, 'Generic Faraday client error.'
|
67
|
+
record_error(@span, 'Generic Faraday client error.')
|
70
68
|
raise
|
71
69
|
end
|
72
70
|
|
73
|
-
def record_error(span, msg
|
74
|
-
span.record_tag(Trace::
|
71
|
+
def record_error(span, msg)
|
72
|
+
span.record_tag(Trace::Span::Tag::ERROR, msg)
|
75
73
|
end
|
76
74
|
|
77
|
-
def record_response_tags(span, status
|
78
|
-
span.record_tag(Trace::
|
79
|
-
if STATUS_ERROR_REGEXP.match(status)
|
80
|
-
span.record_tag(Trace::BinaryAnnotation::ERROR, status,
|
81
|
-
Trace::BinaryAnnotation::Type::STRING, local_endpoint)
|
82
|
-
end
|
75
|
+
def record_response_tags(span, status)
|
76
|
+
span.record_tag(Trace::Span::Tag::STATUS, status)
|
77
|
+
span.record_tag(Trace::Span::Tag::ERROR, status) if STATUS_ERROR_REGEXP.match(status)
|
83
78
|
end
|
84
79
|
|
85
80
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
require 'resolv'
|
2
2
|
|
3
3
|
module ZipkinTracer
|
4
|
-
# Resolves hostnames in the endpoints of the
|
4
|
+
# Resolves hostnames in the endpoints of the spans.
|
5
5
|
# Resolving hostnames is a very expensive operation. We want to store them raw in the main thread
|
6
6
|
# and resolve them in a different thread where we do not affect execution times.
|
7
7
|
class HostnameResolver
|
8
8
|
def spans_with_ips(spans)
|
9
9
|
host_to_ip = hosts_to_ipv4(spans)
|
10
10
|
|
11
|
-
|
12
|
-
hostname =
|
11
|
+
each_endpoint(spans) do |endpoint|
|
12
|
+
hostname = endpoint.ipv4
|
13
13
|
unless resolved_ip_address?(hostname.to_s)
|
14
|
-
|
14
|
+
endpoint.ipv4 = host_to_ip[hostname]
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -28,24 +28,19 @@ module ZipkinTracer
|
|
28
28
|
ip_string.to_i.to_s == ip_string
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def each_endpoint(spans, &block)
|
32
32
|
spans.each do |span|
|
33
|
-
span.
|
34
|
-
yield
|
35
|
-
end
|
36
|
-
span.binary_annotations.each do |annotation|
|
37
|
-
yield annotation
|
33
|
+
[span.local_endpoint, span.remote_endpoint].each do |endpoint|
|
34
|
+
yield endpoint if endpoint
|
38
35
|
end
|
39
36
|
end
|
40
37
|
end
|
41
38
|
|
42
|
-
# Annotations come in pairs like CS/CR, SS/SR.
|
43
|
-
# Each annnotation has a hostname so we, for sure, will have the same host multiple times.
|
44
39
|
# Using this to resolve only once per host
|
45
40
|
def hosts_to_ipv4(spans)
|
46
41
|
hosts = []
|
47
|
-
|
48
|
-
hosts.push(
|
42
|
+
each_endpoint(spans) do |endpoint|
|
43
|
+
hosts.push(endpoint)
|
49
44
|
end
|
50
45
|
hosts.uniq!
|
51
46
|
resolve(hosts)
|
@@ -61,7 +56,7 @@ module ZipkinTracer
|
|
61
56
|
end
|
62
57
|
|
63
58
|
def host_to_ip(hostname, ip_format)
|
64
|
-
|
59
|
+
begin
|
65
60
|
ip_format == :string ? Socket.getaddrinfo(hostname, nil, :INET).first[IP_FIELD] : Trace::Endpoint.host_to_i32(hostname)
|
66
61
|
rescue
|
67
62
|
ip_format == :string ? LOCALHOST : LOCALHOST_I32
|
@@ -12,7 +12,7 @@ module ZipkinTracer
|
|
12
12
|
REQUEST_METHOD = Rack::REQUEST_METHOD rescue 'REQUEST_METHOD'.freeze
|
13
13
|
|
14
14
|
DEFAULT_SERVER_RECV_TAGS = {
|
15
|
-
Trace::
|
15
|
+
Trace::Span::Tag::PATH => PATH_INFO
|
16
16
|
}.freeze
|
17
17
|
|
18
18
|
def initialize(app, config = nil)
|
@@ -55,12 +55,11 @@ module ZipkinTracer
|
|
55
55
|
|
56
56
|
def trace!(span, zipkin_env, &block)
|
57
57
|
trace_request_information(span, zipkin_env)
|
58
|
-
span.
|
58
|
+
span.kind = Trace::Span::Kind::SERVER
|
59
59
|
span.record('whitelisted') if zipkin_env.force_sample?
|
60
60
|
status, headers, body = yield
|
61
61
|
ensure
|
62
62
|
annotate_plugin(span, zipkin_env.env, status, headers, body)
|
63
|
-
span.record(Trace::Annotation::SERVER_SEND)
|
64
63
|
end
|
65
64
|
|
66
65
|
def trace_request_information(span, zipkin_env)
|
@@ -10,10 +10,10 @@ module ZipkinTracer
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def trace_id(default_flags = Trace::Flags::EMPTY)
|
13
|
-
trace_id, span_id, parent_span_id = retrieve_or_generate_ids
|
13
|
+
trace_id, span_id, parent_span_id, shared = retrieve_or_generate_ids
|
14
14
|
sampled = sampled_header_value(@env['HTTP_X_B3_SAMPLED'])
|
15
15
|
flags = (@env['HTTP_X_B3_FLAGS'] || default_flags).to_i
|
16
|
-
Trace::TraceId.new(trace_id, parent_span_id, span_id, sampled, flags)
|
16
|
+
Trace::TraceId.new(trace_id, parent_span_id, span_id, sampled, flags, shared)
|
17
17
|
end
|
18
18
|
|
19
19
|
def called_with_zipkin_headers?
|
@@ -33,12 +33,14 @@ module ZipkinTracer
|
|
33
33
|
if called_with_zipkin_headers?
|
34
34
|
trace_id, span_id = @env.values_at(*B3_REQUIRED_HEADERS)
|
35
35
|
parent_span_id = @env['HTTP_X_B3_PARENTSPANID']
|
36
|
+
shared = true
|
36
37
|
else
|
37
38
|
span_id = TraceGenerator.new.generate_id
|
38
39
|
trace_id = TraceGenerator.new.generate_id_from_span_id(span_id)
|
39
40
|
parent_span_id = nil
|
41
|
+
shared = false
|
40
42
|
end
|
41
|
-
[trace_id, span_id, parent_span_id]
|
43
|
+
[trace_id, span_id, parent_span_id, shared]
|
42
44
|
end
|
43
45
|
|
44
46
|
def new_sampled_header_value(sampled)
|
data/lib/zipkin-tracer/trace.rb
CHANGED
@@ -48,54 +48,17 @@ module Trace
|
|
48
48
|
# Moved here as a first step, eventually move them out of the Trace module
|
49
49
|
|
50
50
|
class Annotation
|
51
|
-
|
52
|
-
CLIENT_RECV = "cr"
|
53
|
-
SERVER_SEND = "ss"
|
54
|
-
SERVER_RECV = "sr"
|
51
|
+
attr_reader :value, :timestamp
|
55
52
|
|
56
|
-
|
57
|
-
def initialize(value, host)
|
53
|
+
def initialize(value)
|
58
54
|
@timestamp = (Time.now.to_f * 1000 * 1000).to_i # micros
|
59
55
|
@value = value
|
60
|
-
@host = host
|
61
|
-
end
|
62
|
-
|
63
|
-
def to_h
|
64
|
-
{
|
65
|
-
value: @value,
|
66
|
-
timestamp: @timestamp,
|
67
|
-
endpoint: host.to_h
|
68
|
-
}
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
class BinaryAnnotation
|
73
|
-
SERVER_ADDRESS = 'sa'.freeze
|
74
|
-
URI = 'http.url'.freeze
|
75
|
-
METHOD = 'http.method'.freeze
|
76
|
-
PATH = 'http.path'.freeze
|
77
|
-
STATUS = 'http.status'.freeze
|
78
|
-
LOCAL_COMPONENT = 'lc'.freeze
|
79
|
-
ERROR = 'error'.freeze
|
80
|
-
|
81
|
-
module Type
|
82
|
-
BOOL = "BOOL"
|
83
|
-
STRING = "STRING"
|
84
|
-
end
|
85
|
-
attr_reader :key, :value, :host
|
86
|
-
|
87
|
-
def initialize(key, value, annotation_type, host)
|
88
|
-
@key = key
|
89
|
-
@value = value
|
90
|
-
@annotation_type = annotation_type
|
91
|
-
@host = host
|
92
56
|
end
|
93
57
|
|
94
58
|
def to_h
|
95
59
|
{
|
96
|
-
key: @key,
|
97
60
|
value: @value,
|
98
|
-
|
61
|
+
timestamp: @timestamp
|
99
62
|
}
|
100
63
|
end
|
101
64
|
end
|
@@ -138,14 +101,15 @@ module Trace
|
|
138
101
|
|
139
102
|
# A TraceId contains all the information of a given trace id
|
140
103
|
class TraceId
|
141
|
-
attr_reader :trace_id, :parent_id, :span_id, :sampled, :flags
|
104
|
+
attr_reader :trace_id, :parent_id, :span_id, :sampled, :flags, :shared
|
142
105
|
|
143
|
-
def initialize(trace_id, parent_id, span_id, sampled, flags)
|
106
|
+
def initialize(trace_id, parent_id, span_id, sampled, flags, shared = false)
|
144
107
|
@trace_id = Trace.trace_id_128bit ? TraceId128Bit.from_value(trace_id) : SpanId.from_value(trace_id)
|
145
108
|
@parent_id = parent_id.nil? ? nil : SpanId.from_value(parent_id)
|
146
109
|
@span_id = SpanId.from_value(span_id)
|
147
110
|
@sampled = sampled
|
148
111
|
@flags = flags
|
112
|
+
@shared = shared
|
149
113
|
end
|
150
114
|
|
151
115
|
def next_id
|
@@ -162,7 +126,8 @@ module Trace
|
|
162
126
|
end
|
163
127
|
|
164
128
|
def to_s
|
165
|
-
"TraceId(trace_id = #{@trace_id.to_s}, parent_id = #{@parent_id.to_s}, span_id = #{@span_id.to_s},
|
129
|
+
"TraceId(trace_id = #{@trace_id.to_s}, parent_id = #{@parent_id.to_s}, span_id = #{@span_id.to_s}," \
|
130
|
+
" sampled = #{@sampled.to_s}, flags = #{@flags.to_s}, shared = #{@shared.to_s})"
|
166
131
|
end
|
167
132
|
end
|
168
133
|
|
@@ -199,12 +164,29 @@ module Trace
|
|
199
164
|
|
200
165
|
# A span may contain many annotations
|
201
166
|
class Span
|
202
|
-
|
167
|
+
module Tag
|
168
|
+
METHOD = "http.method".freeze
|
169
|
+
PATH = "http.path".freeze
|
170
|
+
STATUS = "http.status_code".freeze
|
171
|
+
LOCAL_COMPONENT = "lc".freeze # TODO: Remove LOCAL_COMPONENT and related methods when no longer needed
|
172
|
+
ERROR = "error".freeze
|
173
|
+
end
|
174
|
+
|
175
|
+
module Kind
|
176
|
+
CLIENT = "CLIENT".freeze
|
177
|
+
SERVER = "SERVER".freeze
|
178
|
+
end
|
179
|
+
|
180
|
+
attr_accessor :name, :kind, :local_endpoint, :remote_endpoint, :annotations, :tags, :debug
|
181
|
+
|
203
182
|
def initialize(name, span_id)
|
204
183
|
@name = name
|
205
184
|
@span_id = span_id
|
185
|
+
@kind = nil
|
186
|
+
@local_endpoint = nil
|
187
|
+
@remote_endpoint = nil
|
206
188
|
@annotations = []
|
207
|
-
@
|
189
|
+
@tags = {}
|
208
190
|
@debug = span_id.debug?
|
209
191
|
@timestamp = to_microseconds(Time.now)
|
210
192
|
@duration = UNKNOWN_DURATION
|
@@ -219,28 +201,31 @@ module Trace
|
|
219
201
|
name: @name,
|
220
202
|
traceId: @span_id.trace_id.to_s,
|
221
203
|
id: @span_id.span_id.to_s,
|
222
|
-
|
223
|
-
binaryAnnotations: @binary_annotations.map(&:to_h),
|
204
|
+
localEndpoint: @local_endpoint.to_h,
|
224
205
|
timestamp: @timestamp,
|
225
206
|
duration: @duration,
|
226
207
|
debug: @debug
|
227
208
|
}
|
228
209
|
h[:parentId] = @span_id.parent_id.to_s unless @span_id.parent_id.nil?
|
210
|
+
h[:kind] = @kind unless @kind.nil?
|
211
|
+
h[:remoteEndpoint] = @remote_endpoint.to_h unless @remote_endpoint.nil?
|
212
|
+
h[:annotations] = @annotations.map(&:to_h) unless @annotations.empty?
|
213
|
+
h[:tags] = @tags unless @tags.empty?
|
214
|
+
h[:shared] = true if @span_id.shared
|
229
215
|
h
|
230
216
|
end
|
231
217
|
|
232
218
|
# We record information into spans, then we send these spans to zipkin
|
233
|
-
def record(value
|
234
|
-
annotations << Trace::Annotation.new(value.to_s
|
219
|
+
def record(value)
|
220
|
+
annotations << Trace::Annotation.new(value.to_s)
|
235
221
|
end
|
236
222
|
|
237
|
-
def record_tag(key, value
|
238
|
-
|
239
|
-
binary_annotations << Trace::BinaryAnnotation.new(key, value, type, endpoint)
|
223
|
+
def record_tag(key, value)
|
224
|
+
@tags[key] = value
|
240
225
|
end
|
241
226
|
|
242
227
|
def record_local_component(value)
|
243
|
-
record_tag(
|
228
|
+
record_tag(Tag::LOCAL_COMPONENT, value)
|
244
229
|
end
|
245
230
|
|
246
231
|
def has_parent_span?
|
@@ -293,6 +278,5 @@ module Trace
|
|
293
278
|
hsh[:port] = port if port
|
294
279
|
hsh
|
295
280
|
end
|
296
|
-
|
297
281
|
end
|
298
282
|
end
|
@@ -5,7 +5,7 @@ require 'zipkin-tracer/hostname_resolver'
|
|
5
5
|
|
6
6
|
class AsyncJsonApiClient
|
7
7
|
include SuckerPunch::Job
|
8
|
-
SPANS_PATH = '/api/
|
8
|
+
SPANS_PATH = '/api/v2/spans'
|
9
9
|
|
10
10
|
def perform(json_api_host, spans)
|
11
11
|
spans_with_ips = ::ZipkinTracer::HostnameResolver.new.spans_with_ips(spans).map(&:to_h)
|
@@ -22,12 +22,10 @@ module Trace
|
|
22
22
|
|
23
23
|
def end_span(span)
|
24
24
|
span.close
|
25
|
-
# If in a thread not handling incoming http requests, it will not have
|
25
|
+
# If in a thread not handling incoming http requests, it will not have Kind::SERVER, so the span
|
26
26
|
# will never be flushed and will cause memory leak.
|
27
|
-
# It will have CLIENT_SEND and CLIENT_RECV if the thread sends out http requests, so use CLIENT_RECV as the sign
|
28
|
-
# to flush the span.
|
29
27
|
# If no parent span, then current span needs to flush when it ends.
|
30
|
-
if !span.has_parent_span? || span.
|
28
|
+
if !span.has_parent_span? || span.kind == Trace::Span::Kind::SERVER
|
31
29
|
flush!
|
32
30
|
reset
|
33
31
|
end
|
@@ -35,6 +33,7 @@ module Trace
|
|
35
33
|
|
36
34
|
def start_span(trace_id, name)
|
37
35
|
span = Span.new(name, trace_id)
|
36
|
+
span.local_endpoint = Trace.default_endpoint
|
38
37
|
store_span(trace_id, span)
|
39
38
|
span
|
40
39
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zipkin-tracer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.33.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Franklin Hu
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2019-03-
|
16
|
+
date: 2019-03-08 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: faraday
|
@@ -206,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
206
|
- !ruby/object:Gem::Version
|
207
207
|
version: 1.3.5
|
208
208
|
requirements: []
|
209
|
-
rubygems_version: 3.0.
|
209
|
+
rubygems_version: 3.0.3
|
210
210
|
signing_key:
|
211
211
|
specification_version: 4
|
212
212
|
summary: Ruby tracing via Zipkin
|