zipkin-tracer 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZmU3ZjM4OTBmOGM0NWRmMjkwNjkzZWY1MmE1ZWM5MWY4OTQ5OGQ3Yw==
4
+ NGI0MTlmZDJhZWVmMzRjYzA5NjRiZTJiMDljODdiNjg0MjNiZTI4Mg==
5
5
  data.tar.gz: !binary |-
6
- MzI1NmFiNTEzOGYwYTVlMzk4MDljZDIxYzE5ZGQxY2RmZTc3ZjdiMA==
6
+ Mjk4ZTcyZWYzNmRhMTE3MTc2OTk4YTYxMDExNTc5M2ZlMWJlNjZjZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YjNlYTFjZDcyY2IwZDMxMjUwMjNhNzZhZGJmNjk4ODA0ZGIwNWQ2N2NlZDZm
10
- ODViMmM1MmM5OWNhNmFlZjIwNzgxOTY4MDhiNjFkMTkxMGVjN2Q0OTQ1MjAx
11
- YWM1YzY4Zjg0YjRhODI0NTUxZTdhZDdiMDY3YmRlZmE2MmU0MjU=
9
+ YzkzZWUwZjY1N2QwM2E3MGNhMjI5MTE2MTRjYzA5ZGI5MWFmOWQzMzliNjRj
10
+ MmRhMDlhOWFiNTU4ZTVkODI5NmI1ZTU0ZWE4MThmNTA3M2NmNDdjZjgyYTg0
11
+ MTczMWE4N2E1YzYyOTM5ODY0YjQ3NGRhNmQxYjg2NjZiNDVjOGQ=
12
12
  data.tar.gz: !binary |-
13
- NDEzMGRmNTBhZWRmYTc0YTc3NDllODkxMDExMWYzODQzMTgwZjg2MTAyNWQz
14
- ZjFjYjVjMDAyNGI5NDM3NmNmZTQ4YWUyYmZkYTllYWMwZGNjZjBjZjdhYjgw
15
- Nzc1MjM4MjkyY2RmNGFjOGE0OGRhMmFlODhjZmQ4ZGYwNzczYTg=
13
+ NWVjNjJhMzljZDRkODVkNjc5NjU2MDU0ODRhZmQ0Yjg0OTZiZTIzMTFiNGUz
14
+ MTYwNTkwMzhkNzU3N2MwZGExZGI4YzNjYzdiNTdkYzI0NzBlNTUwYzAzY2Nj
15
+ OGFhNzliMGExYWQyZWJhYTFjMzgxODMzMDA3MTNlYWMwMTVhZDk=
data/lib/zipkin-tracer.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require 'base64' #Bug in finagle. They should be requiring this: finagle-thrift-1.4.1/lib/finagle-thrift/tracer.rb:115
2
+ require 'zipkin-tracer/trace'
2
3
  require 'zipkin-tracer/rack/zipkin-tracer'
3
4
 
4
5
  begin
5
6
  require 'faraday'
6
7
  require 'zipkin-tracer/faraday/zipkin-tracer'
7
8
  rescue LoadError #Faraday is not available, we do not load our code.
8
- end
9
+ end
@@ -16,7 +16,7 @@ require 'sucker_punch'
16
16
 
17
17
 
18
18
  module ScribeThrift
19
- # This is here just for the monkey partching
19
+ # This is here just for the monkey patching
20
20
  class Client
21
21
  # This method in the original class was both sending and receiving logs.
22
22
  # The original class: https://github.com/twitter/scribe/blob/master/vendor/gen-rb/scribe.rb
@@ -46,12 +46,10 @@ class AsyncScribe
46
46
  rescue ThriftClient::NoServersAvailable, Thrift::Exception
47
47
  # I couldn't care less
48
48
  end
49
-
50
49
  end
51
50
 
52
51
  # Scribe which rescue thrift errors to avoid them to raise to the client
53
52
  class CarelessScribe
54
-
55
53
  def initialize(scribe_server_address)
56
54
  @server_address = scribe_server_address
57
55
  end
@@ -66,5 +64,4 @@ class CarelessScribe
66
64
  rescue ThriftClient::NoServersAvailable, Thrift::Exception
67
65
  # I couldn't care less
68
66
  end
69
-
70
67
  end
@@ -2,13 +2,16 @@ require 'logger'
2
2
  module ZipkinTracer
3
3
 
4
4
  class Config
5
- attr_reader :service_name, :service_port, :scribe_server, :zookeeper, :sample_rate,
6
- :scribe_max_buffer, :annotate_plugin, :filter_plugin, :whitelist_plugin, :logger
5
+ attr_reader :service_name, :service_port, :json_api_host, :traces_buffer,
6
+ :scribe_server, :zookeeper, :sample_rate, :scribe_max_buffer, :annotate_plugin,
7
+ :filter_plugin, :whitelist_plugin, :logger
7
8
 
8
9
  def initialize(app, config_hash)
9
10
  config = config_hash || app_config(app)
10
11
  @service_name = config[:service_name]
11
12
  @service_port = config[:service_port] || DEFAULTS[:service_port]
13
+ @json_api_host = config[:json_api_host]
14
+ @traces_buffer = config[:traces_buffer] || DEFAULTS[:traces_buffer]
12
15
  @scribe_server = config[:scribe_server]
13
16
  @zookeeper = config[:zookeeper]
14
17
  @sample_rate = config[:sample_rate] || DEFAULTS[:sample_rate]
@@ -19,12 +22,16 @@ module ZipkinTracer
19
22
  @logger = config[:logger] || fallback_logger
20
23
  end
21
24
 
22
- def using_scribe?
23
- !!(@scribe_server && defined?(::Scribe))
24
- end
25
-
26
- def using_kafka?
27
- !!(@zookeeper && RUBY_PLATFORM == 'java' && defined?(::Hermann))
25
+ def adapter
26
+ if !!@json_api_host
27
+ :json
28
+ elsif !!(@scribe_server && defined?(::Scribe))
29
+ :scribe
30
+ elsif !!(@zookeeper && RUBY_PLATFORM == 'java' && defined?(::Hermann))
31
+ :kafka
32
+ else
33
+ nil
34
+ end
28
35
  end
29
36
 
30
37
  private
@@ -38,6 +45,7 @@ module ZipkinTracer
38
45
  end
39
46
 
40
47
  DEFAULTS = {
48
+ traces_buffer: 100,
41
49
  scribe_max_buffer: 10,
42
50
  sample_rate: 0.1,
43
51
  service_port: 80
@@ -6,14 +6,14 @@ require 'uri'
6
6
  module ZipkinTracer
7
7
  class FaradayHandler < ::Faraday::Middleware
8
8
  B3_HEADERS = {
9
- :trace_id => "X-B3-TraceId",
10
- :parent_id => "X-B3-ParentSpanId",
11
- :span_id => "X-B3-SpanId",
12
- :sampled => "X-B3-Sampled",
13
- :flags => "X-B3-Flags"
9
+ trace_id: 'X-B3-TraceId',
10
+ parent_id: 'X-B3-ParentSpanId',
11
+ span_id: 'X-B3-SpanId',
12
+ sampled: 'X-B3-Sampled',
13
+ flags: 'X-B3-Flags'
14
14
  }.freeze
15
15
 
16
- def initialize(app, service_name=nil)
16
+ def initialize(app, service_name = nil)
17
17
  @app = app
18
18
  @service_name = service_name
19
19
  end
@@ -22,7 +22,7 @@ module ZipkinTracer
22
22
  # handle either a URI object (passed by Faraday v0.8.x in testing), or something string-izable
23
23
  url = env[:url].respond_to?(:host) ? env[:url] : URI.parse(env[:url].to_s)
24
24
  local_endpoint = ::Trace.default_endpoint # The rack middleware set this up for us.
25
- remote_endpoint = callee_endpoint(url) # The endpoint we are calling.
25
+ remote_endpoint = callee_endpoint(url, local_endpoint.ip_format) # The endpoint we are calling.
26
26
 
27
27
  response = nil
28
28
  begin
@@ -33,12 +33,12 @@ module ZipkinTracer
33
33
  end
34
34
  # annotate with method (GET/POST/etc.) and uri path
35
35
  ::Trace.set_rpc_name(env[:method].to_s.downcase)
36
- record(::Trace::BinaryAnnotation.new("http.uri", url.path, "STRING", local_endpoint))
37
- record(::Trace::BinaryAnnotation.new("sa", "1", "BOOL", remote_endpoint))
36
+ record(::Trace::BinaryAnnotation.new('http.uri', url.path, 'STRING', local_endpoint))
37
+ record(::Trace::BinaryAnnotation.new('sa', '1', 'BOOL', remote_endpoint))
38
38
  record(::Trace::Annotation.new(::Trace::Annotation::CLIENT_SEND, local_endpoint))
39
39
  response = @app.call(env).on_complete do |renv|
40
40
  # record HTTP status code on response
41
- record(::Trace::BinaryAnnotation.new("http.status", renv[:status].to_s, "STRING", local_endpoint))
41
+ record(::Trace::BinaryAnnotation.new('http.status', renv[:status].to_s, 'STRING', local_endpoint))
42
42
  end
43
43
  record(::Trace::Annotation.new(::Trace::Annotation::CLIENT_RECV, local_endpoint))
44
44
  ensure
@@ -55,18 +55,9 @@ module ZipkinTracer
55
55
  #TODO: if this class some day accepts a config hash, add a logger
56
56
  end
57
57
 
58
- def callee_endpoint(url)
58
+ def callee_endpoint(url, ip_format)
59
59
  service_name = @service_name || url.host.split('.').first || 'unknown' # default to url-derived service name
60
- ::Trace::Endpoint.new(host_ip_for(url.host), url.port, service_name)
60
+ ::Trace::Endpoint.make_endpoint(url.host, url.port, service_name, ip_format)
61
61
  end
62
-
63
- # get host IP for specified hostname, catching exceptions
64
- def host_ip_for(hostname)
65
- ::Trace::Endpoint.host_to_i32(hostname)
66
- rescue
67
- # default to 0.0.0.0 if lookup fails
68
- 0x00000000
69
- end
70
-
71
62
  end
72
63
  end
@@ -17,35 +17,49 @@ require 'scribe'
17
17
 
18
18
  require 'zipkin-tracer/config'
19
19
  require 'zipkin-tracer/careless_scribe'
20
+ require 'zipkin-tracer/zipkin_json_tracer'
20
21
 
21
22
  if RUBY_PLATFORM == 'java'
22
23
  require 'hermann/producer'
23
24
  require 'zipkin-tracer/zipkin_kafka_tracer'
24
25
  end
25
26
 
27
+
26
28
  module ZipkinTracer extend self
27
29
 
28
30
  class RackHandler
29
31
  B3_REQUIRED_HEADERS = %w[HTTP_X_B3_TRACEID HTTP_X_B3_PARENTSPANID HTTP_X_B3_SPANID HTTP_X_B3_SAMPLED]
30
32
  B3_OPT_HEADERS = %w[HTTP_X_B3_FLAGS]
31
33
 
32
- def initialize(app, config=nil)
34
+ def initialize(app, config = nil)
33
35
  @app = app
34
36
  @lock = Mutex.new
35
37
 
36
38
  config = Config.new(app, config)
37
-
38
- ::Trace.tracer = if config.using_scribe?
39
- ::Trace::ZipkinTracer.new(CarelessScribe.new(config.scribe_server), config.scribe_max_buffer)
40
- elsif config.using_kafka?
41
- kafkaTracer = ::Trace::ZipkinKafkaTracer.new
42
- kafkaTracer.connect(config.zookeeper)
43
- kafkaTracer
44
- else
45
- ::Trace::NullTracer.new
39
+ SuckerPunch.logger = config.logger
40
+ adapter = config.adapter
41
+
42
+ ::Trace.tracer = case adapter
43
+ when :json
44
+ ::Trace::ZipkinJsonTracer.new(config.json_api_host, config.traces_buffer)
45
+ when :scribe
46
+ ::Trace::ZipkinTracer.new(CarelessScribe.new(config.scribe_server), config.scribe_max_buffer)
47
+ when :kafka
48
+ kafkaTracer = ::Trace::ZipkinKafkaTracer.new
49
+ kafkaTracer.connect(config.zookeeper)
50
+ kafkaTracer
51
+ else
52
+ ::Trace::NullTracer.new
46
53
  end
47
- ::Trace.default_endpoint = ::Trace::Endpoint.new( local_ip, config.service_port , config.service_name)
48
- ::Trace.sample_rate=(config.sample_rate)
54
+
55
+ ip_format = config.adapter == :json ? :string : :i32
56
+ ::Trace.default_endpoint = ::Trace::Endpoint.make_endpoint(
57
+ nil, # auto detect hostname
58
+ config.service_port,
59
+ service_name(config.service_name),
60
+ ip_format
61
+ )
62
+ ::Trace.sample_rate = config.sample_rate
49
63
 
50
64
  @config = config
51
65
  end
@@ -53,6 +67,7 @@ module ZipkinTracer extend self
53
67
  def call(env)
54
68
  # skip certain requests
55
69
  return @app.call(env) if filtered?(env) || !routable_request?(env)
70
+
56
71
  whitelisted = force_sample?(env)
57
72
  id = get_or_create_trace_id(env, whitelisted) # note that this depends on the sample rate being set
58
73
  tracing_filter(id, env, whitelisted) { @app.call(env) }
@@ -60,10 +75,15 @@ module ZipkinTracer extend self
60
75
 
61
76
  private
62
77
 
78
+ # Use the Domain environment variable to extract the service name, otherwise use the default config name
79
+ def service_name(default_name)
80
+ ENV["DOMAIN"].to_s.empty? ? default_name : ENV["DOMAIN"].split('.').first
81
+ end
82
+
63
83
  # If the request is not valid for this service, we do not what to trace it.
64
84
  def routable_request?(env)
65
- return true unless defined?(Rails) #If not running on a Rails app, we can't verify if it is invalid
66
- Rails.application.routes.recognize_path(env["PATH_INFO"])
85
+ return true unless defined?(Rails) # If not running on a Rails app, we can't verify if it is invalid
86
+ Rails.application.routes.recognize_path(env['PATH_INFO'])
67
87
  true
68
88
  rescue ActionController::RoutingError
69
89
  false
@@ -81,7 +101,7 @@ module ZipkinTracer extend self
81
101
  @config.whitelist_plugin && @config.whitelist_plugin.call(env)
82
102
  end
83
103
 
84
- def tracing_filter(trace_id, env, whitelisted=false)
104
+ def tracing_filter(trace_id, env, whitelisted = false)
85
105
  synchronize do
86
106
  ::Trace.push(trace_id)
87
107
  #if called by a service, the caller already added the information
@@ -99,11 +119,9 @@ module ZipkinTracer extend self
99
119
  [status, headers, body]
100
120
  end
101
121
 
102
- private
103
-
104
122
  def add_request_information(env)
105
- ::Trace.set_rpc_name(env["REQUEST_METHOD"].to_s.downcase) # get/post and all that jazz
106
- ::Trace.record(::Trace::BinaryAnnotation.new("http.uri", env["PATH_INFO"], "STRING", ::Trace.default_endpoint))
123
+ ::Trace.set_rpc_name(env['REQUEST_METHOD'].to_s.downcase) # get/post and all that jazz
124
+ ::Trace.record(::Trace::BinaryAnnotation.new('http.uri', env['PATH_INFO'], 'STRING', ::Trace.default_endpoint))
107
125
  end
108
126
 
109
127
  def called_with_zipkin_headers?(env)
@@ -114,8 +132,8 @@ module ZipkinTracer extend self
114
132
  @lock.synchronize do
115
133
  yield
116
134
  end
117
- # Nothing wonky that the tracer does should stop us from using the app!!!
118
- # Usually is better to rescue StandardError but the socket layer can launch Errno kind of exceptions
135
+ # Nothing wonky that the tracer does should stop us from using the app!!!
136
+ # Usually is better to rescue StandardError but the socket layer can launch Errno kind of exceptions
119
137
  rescue Exception => e
120
138
  @config.logger.error("Exception #{e.message} while sending Zipkin traces. #{e.backtrace}")
121
139
  end
@@ -125,23 +143,14 @@ module ZipkinTracer extend self
125
143
  env.values_at(*B3_REQUIRED_HEADERS)
126
144
  else
127
145
  new_id = Trace.generate_id
128
- [new_id, nil, new_id, ("true" if whitelisted || Trace.should_sample?)]
146
+ [new_id, nil, new_id, ('true' if whitelisted || Trace.should_sample?)]
129
147
  end
130
- trace_parameters[3] = (trace_parameters[3] == "true")
148
+ trace_parameters[3] = (trace_parameters[3] == 'true')
131
149
 
132
150
  trace_parameters += env.values_at(*B3_OPT_HEADERS) # always check flags
133
151
  trace_parameters[4] = (trace_parameters[4] || default_flags).to_i
134
152
 
135
153
  Trace::TraceId.new(*trace_parameters)
136
154
  end
137
-
138
- def local_ip
139
- ::Trace::Endpoint.host_to_i32(Socket.gethostname)
140
- rescue
141
- # Default to local if lockup fails
142
- ::Trace::Endpoint.host_to_i32('127.0.0.1')
143
- end
144
-
145
155
  end
146
-
147
156
  end
@@ -0,0 +1,67 @@
1
+ require 'finagle-thrift'
2
+ require 'finagle-thrift/trace'
3
+
4
+ module Trace
5
+ class Span
6
+ def to_h
7
+ {
8
+ name: @name,
9
+ traceId: @span_id.trace_id.to_s,
10
+ id: @span_id.span_id.to_s,
11
+ parentId: @span_id.parent_id.nil? ? nil : @span_id.parent_id.to_s,
12
+ annotations: @annotations.map!(&:to_h),
13
+ binaryAnnotations: @binary_annotations.map!(&:to_h),
14
+ debug: @debug
15
+ }
16
+ end
17
+ end
18
+
19
+ class Annotation
20
+ def to_h
21
+ {
22
+ value: @value,
23
+ timestamp: @timestamp,
24
+ endpoint: host.to_h
25
+ }
26
+ end
27
+ end
28
+
29
+ class BinaryAnnotation
30
+ def to_h
31
+ {
32
+ key: @key,
33
+ value: @value,
34
+ endpoint: host.to_h
35
+ }
36
+ end
37
+ end
38
+
39
+ class Endpoint
40
+ LOCALHOST = '127.0.0.1'
41
+ LOCALHOST_I32 = 0x7f000001
42
+
43
+ attr_accessor :ip_format
44
+
45
+ # we cannot override the initializer to add an extra parameter so use a factory
46
+ def self.make_endpoint(hostname, service_port, service_name, ip_format)
47
+ ipv4 = begin
48
+ hostname ||= Socket.gethostname
49
+ ip_format == :string ? Socket.getaddrinfo(hostname, nil, :INET)[0][3] : host_to_i32(hostname)
50
+ rescue
51
+ ip_format == :string ? LOCALHOST : LOCALHOST_I32
52
+ end
53
+
54
+ ep = Endpoint.new(ipv4, service_port, service_name)
55
+ ep.ip_format = ip_format
56
+ ep
57
+ end
58
+
59
+ def to_h
60
+ {
61
+ ipv4: ipv4,
62
+ port: port,
63
+ serviceName: service_name
64
+ }
65
+ end
66
+ end
67
+ end
@@ -12,6 +12,6 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  module ZipkinTracer
15
- VERSION = "0.8.0"
15
+ VERSION = "0.9.0"
16
16
  end
17
17
 
@@ -0,0 +1,73 @@
1
+ require 'json'
2
+ require 'faraday'
3
+ require 'finagle-thrift'
4
+ require 'finagle-thrift/tracer'
5
+
6
+ class AsyncJsonApiClient
7
+ include SuckerPunch::Job
8
+ SPANS_PATH = '/api/v1/spans'
9
+
10
+ def perform(json_api_host, spans)
11
+ resp = Faraday.new(json_api_host).post do |req|
12
+ req.url SPANS_PATH
13
+ req.headers['Content-Type'] = 'application/json'
14
+ req.body = JSON.generate(spans.map!(&:to_h))
15
+ end
16
+ rescue => e
17
+ SuckerPunch.logger.error(e)
18
+ end
19
+ end
20
+
21
+ module Trace
22
+ class ZipkinJsonTracer < Tracer
23
+ TRACER_CATEGORY = "zipkin".freeze
24
+
25
+ def initialize(json_api_host, traces_buffer)
26
+ @json_api_host = json_api_host
27
+ @traces_buffer = traces_buffer
28
+ reset
29
+ end
30
+
31
+ def record(id, annotation)
32
+ return unless id.sampled?
33
+ span = get_span_for_id(id)
34
+
35
+ case annotation
36
+ when BinaryAnnotation
37
+ span.binary_annotations << annotation
38
+ when Annotation
39
+ span.annotations << annotation
40
+ end
41
+
42
+ @count += 1
43
+ if @count >= @traces_buffer || (annotation.is_a?(Annotation) && annotation.value == Annotation::SERVER_SEND)
44
+ flush!
45
+ end
46
+ end
47
+
48
+ def set_rpc_name(id, name)
49
+ return unless id.sampled?
50
+ span = get_span_for_id(id)
51
+ span.name = name.to_s
52
+ end
53
+
54
+ private
55
+
56
+ def get_span_for_id(id)
57
+ key = id.span_id.to_s
58
+ @spans[key] ||= begin
59
+ Span.new("", id)
60
+ end
61
+ end
62
+
63
+ def reset
64
+ @count = 0
65
+ @spans = {}
66
+ end
67
+
68
+ def flush!
69
+ AsyncJsonApiClient.new.async.perform(@json_api_host, @spans.values.dup)
70
+ reset
71
+ end
72
+ end
73
+ end
metadata CHANGED
@@ -1,16 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zipkin-tracer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franklin Hu
8
8
  - R Tyler Croy
9
9
  - James Way
10
+ - Jordi Polo
11
+ - Julien Feltesse
12
+ - Scott Steeg
10
13
  autorequire:
11
14
  bindir: bin
12
15
  cert_chain: []
13
- date: 2015-11-22 00:00:00.000000000 Z
16
+ date: 2015-12-14 00:00:00.000000000 Z
14
17
  dependencies:
15
18
  - !ruby/object:Gem::Dependency
16
19
  name: finagle-thrift
@@ -124,6 +127,34 @@ dependencies:
124
127
  - - ~>
125
128
  - !ruby/object:Gem::Version
126
129
  version: '0.8'
130
+ - !ruby/object:Gem::Dependency
131
+ name: timecop
132
+ requirement: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ~>
135
+ - !ruby/object:Gem::Version
136
+ version: '0.8'
137
+ type: :development
138
+ prerelease: false
139
+ version_requirements: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ~>
142
+ - !ruby/object:Gem::Version
143
+ version: '0.8'
144
+ - !ruby/object:Gem::Dependency
145
+ name: webmock
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ~>
149
+ - !ruby/object:Gem::Version
150
+ version: '1.22'
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: '1.22'
127
158
  - !ruby/object:Gem::Dependency
128
159
  name: hermann
129
160
  requirement: !ruby/object:Gem::Requirement
@@ -157,6 +188,9 @@ email:
157
188
  - franklin@twitter.com
158
189
  - tyler@monkeypox.org
159
190
  - jamescway@gmail.com
191
+ - jcarres@mdsol.com
192
+ - jfeltesse@mdsol.com
193
+ - ssteeg@mdsol.com
160
194
  executables: []
161
195
  extensions: []
162
196
  extra_rdoc_files: []
@@ -166,7 +200,9 @@ files:
166
200
  - lib/zipkin-tracer/config.rb
167
201
  - lib/zipkin-tracer/faraday/zipkin-tracer.rb
168
202
  - lib/zipkin-tracer/rack/zipkin-tracer.rb
203
+ - lib/zipkin-tracer/trace.rb
169
204
  - lib/zipkin-tracer/version.rb
205
+ - lib/zipkin-tracer/zipkin_json_tracer.rb
170
206
  - lib/zipkin-tracer/zipkin_kafka_tracer.rb
171
207
  homepage: https://github.com/openzipkin/zipkin-tracer
172
208
  licenses: []