zipkin-tracer 0.9.1 → 0.10.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 +8 -8
- data/lib/zipkin-tracer/faraday/zipkin-tracer.rb +17 -19
- data/lib/zipkin-tracer/rack/zipkin-tracer.rb +81 -80
- data/lib/zipkin-tracer/trace.rb +7 -0
- data/lib/zipkin-tracer/tracer_factory.rb +40 -0
- data/lib/zipkin-tracer/version.rb +1 -1
- data/lib/zipkin-tracer/zipkin_json_tracer.rb +11 -48
- data/lib/zipkin-tracer/zipkin_kafka_tracer.rb +19 -51
- data/lib/zipkin-tracer/zipkin_tracer_base.rb +71 -0
- metadata +4 -16
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzUzN2QzOWMyMzczNmIxNGRhMzU0YWIzNzU4NWNkZWU3NjY0YTcxOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MDBkMTNiNmU5N2E0NGIwY2ZiZmI1MTYzMTFiYTU5ODkxNmI5NDMxYQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjY1NmFkODBiYzgyZWE4MTA5ZjQwOWU2MDRlZDIyYmZmYmMyZjA0MGNiOWE2
|
10
|
+
ZWQ4MTBiOGU4N2RmNGRhYmE0MjI3MGIyMjg0MjE1OWE4NzM5NWY1MDBlYmQ2
|
11
|
+
NzhlZTc1NGZiNjM3ZGQzYTg2ZDU5NmY1M2Q3YmZkNWNmZjgwODQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NmRjYmYyZWM4OGEzYmMyMTUzYzE5MzNjOGQxZDkyZTRiYTgxYzkyYzg3MTIy
|
14
|
+
YWRiYzkwYmIxYmM3MmIzZmFkZmJlMmZmOTBiM2FjZWFjNjA0ZGMwY2ZhNmI4
|
15
|
+
ZjVmNzU4ZGUwYzczZmNkM2U0M2ZmNjQxZDRkZDI2YTY3MmVlOTU=
|
@@ -16,48 +16,46 @@ module ZipkinTracer
|
|
16
16
|
def initialize(app, service_name = nil)
|
17
17
|
@app = app
|
18
18
|
@service_name = service_name
|
19
|
+
@tracer = Trace.tracer
|
19
20
|
end
|
20
21
|
|
21
22
|
def call(env)
|
22
23
|
# handle either a URI object (passed by Faraday v0.8.x in testing), or something string-izable
|
23
24
|
url = env[:url].respond_to?(:host) ? env[:url] : URI.parse(env[:url].to_s)
|
24
|
-
local_endpoint =
|
25
|
+
local_endpoint = Trace.default_endpoint # The rack middleware set this up for us.
|
25
26
|
remote_endpoint = callee_endpoint(url, local_endpoint.ip_format) # The endpoint we are calling.
|
26
|
-
|
27
27
|
response = nil
|
28
|
-
|
29
|
-
|
30
|
-
::Trace.push(trace_id.next_id)
|
28
|
+
trace_id = Trace.id.next_id
|
29
|
+
with_trace_id(trace_id) do
|
31
30
|
B3_HEADERS.each do |method, header|
|
32
|
-
env[:request_headers][header] =
|
31
|
+
env[:request_headers][header] = trace_id.send(method).to_s
|
33
32
|
end
|
34
33
|
# annotate with method (GET/POST/etc.) and uri path
|
35
|
-
|
36
|
-
record(
|
37
|
-
record(
|
38
|
-
record(
|
34
|
+
@tracer.set_rpc_name(trace_id, env[:method].to_s.downcase)
|
35
|
+
@tracer.record(trace_id, Trace::BinaryAnnotation.new('http.uri', url.path, 'STRING', local_endpoint))
|
36
|
+
@tracer.record(trace_id, Trace::BinaryAnnotation.new('sa', '1', 'BOOL', remote_endpoint))
|
37
|
+
@tracer.record(trace_id, Trace::Annotation.new(Trace::Annotation::CLIENT_SEND, local_endpoint))
|
39
38
|
response = @app.call(env).on_complete do |renv|
|
40
39
|
# record HTTP status code on response
|
41
|
-
record(
|
40
|
+
@tracer.record(trace_id, Trace::BinaryAnnotation.new('http.status', renv[:status].to_s, 'STRING', local_endpoint))
|
42
41
|
end
|
43
|
-
record(
|
44
|
-
ensure
|
45
|
-
::Trace.pop
|
42
|
+
@tracer.record(trace_id, Trace::Annotation.new(Trace::Annotation::CLIENT_RECV, local_endpoint))
|
46
43
|
end
|
47
44
|
response
|
48
45
|
end
|
49
46
|
|
50
47
|
private
|
51
48
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
def with_trace_id(trace_id, &block)
|
50
|
+
Trace.push(trace_id)
|
51
|
+
yield
|
52
|
+
ensure
|
53
|
+
Trace.pop
|
56
54
|
end
|
57
55
|
|
58
56
|
def callee_endpoint(url, ip_format)
|
59
57
|
service_name = @service_name || url.host.split('.').first || 'unknown' # default to url-derived service name
|
60
|
-
|
58
|
+
Trace::Endpoint.make_endpoint(url.host, url.port, service_name, ip_format)
|
61
59
|
end
|
62
60
|
end
|
63
61
|
end
|
@@ -13,11 +13,13 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
require 'finagle-thrift'
|
15
15
|
require 'finagle-thrift/trace'
|
16
|
-
require 'sucker_punch'
|
17
16
|
require 'zipkin-tracer/config'
|
17
|
+
require 'zipkin-tracer/tracer_factory'
|
18
18
|
|
19
19
|
module ZipkinTracer
|
20
20
|
|
21
|
+
# This middleware reads Zipkin headers from the request and sets/creates a Trace.id usable by the rest of the app
|
22
|
+
# It will also send the trace to the Zipkin service using one of the methods configured.
|
21
23
|
class RackHandler
|
22
24
|
B3_REQUIRED_HEADERS = %w[HTTP_X_B3_TRACEID HTTP_X_B3_PARENTSPANID HTTP_X_B3_SPANID HTTP_X_B3_SAMPLED]
|
23
25
|
B3_OPT_HEADERS = %w[HTTP_X_B3_FLAGS]
|
@@ -25,53 +27,33 @@ module ZipkinTracer
|
|
25
27
|
def initialize(app, config = nil)
|
26
28
|
@app = app
|
27
29
|
@lock = Mutex.new
|
30
|
+
@config = Config.new(app, config).freeze
|
31
|
+
@tracer = TracerFactory.new.tracer(@config)
|
32
|
+
end
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
require 'zipkin-tracer/zipkin_json_tracer'
|
36
|
-
::Trace::ZipkinJsonTracer.new(config.json_api_host, config.traces_buffer)
|
37
|
-
when :scribe
|
38
|
-
require 'zipkin-tracer/careless_scribe'
|
39
|
-
::Trace::ZipkinTracer.new(CarelessScribe.new(config.scribe_server), config.scribe_max_buffer)
|
40
|
-
when :kafka
|
41
|
-
require 'zipkin-tracer/zipkin_kafka_tracer'
|
42
|
-
kafkaTracer = ::Trace::ZipkinKafkaTracer.new
|
43
|
-
kafkaTracer.connect(config.zookeeper)
|
44
|
-
kafkaTracer
|
34
|
+
def call(env)
|
35
|
+
zipkin_env = ZipkinEnv.new(env, @config)
|
36
|
+
trace_id = zipkin_env.trace_id
|
37
|
+
with_trace_id(trace_id) do
|
38
|
+
if !trace_id.sampled? || !routable_request?(env)
|
39
|
+
@app.call(env)
|
45
40
|
else
|
46
|
-
|
41
|
+
trace!(trace_id, zipkin_env) { @app.call(env) }
|
42
|
+
end
|
47
43
|
end
|
48
|
-
|
49
|
-
ip_format = config.adapter == :json ? :string : :i32
|
50
|
-
::Trace.default_endpoint = ::Trace::Endpoint.make_endpoint(
|
51
|
-
nil, # auto detect hostname
|
52
|
-
config.service_port,
|
53
|
-
service_name(config.service_name),
|
54
|
-
ip_format
|
55
|
-
)
|
56
|
-
::Trace.sample_rate = config.sample_rate
|
57
|
-
|
58
|
-
@config = config
|
59
44
|
end
|
60
45
|
|
61
|
-
|
62
|
-
# skip certain requests
|
63
|
-
return @app.call(env) if filtered?(env) || !routable_request?(env)
|
46
|
+
private
|
64
47
|
|
65
|
-
|
66
|
-
|
67
|
-
|
48
|
+
def with_trace_id(trace_id, &block)
|
49
|
+
Trace.push(trace_id)
|
50
|
+
yield
|
51
|
+
ensure
|
52
|
+
Trace.pop
|
68
53
|
end
|
69
54
|
|
70
|
-
|
71
|
-
|
72
|
-
# Use the Domain environment variable to extract the service name, otherwise use the default config name
|
73
|
-
def service_name(default_name)
|
74
|
-
ENV["DOMAIN"].to_s.empty? ? default_name : ENV["DOMAIN"].split('.').first
|
55
|
+
def record(annotation)
|
56
|
+
@tracer.record(@trace_id, annotation)
|
75
57
|
end
|
76
58
|
|
77
59
|
# If the request is not valid for this service, we do not what to trace it.
|
@@ -83,68 +65,87 @@ module ZipkinTracer
|
|
83
65
|
false
|
84
66
|
end
|
85
67
|
|
86
|
-
def
|
68
|
+
def annotate_plugin(env, status, response_headers, response_body)
|
87
69
|
@config.annotate_plugin.call(env, status, response_headers, response_body) if @config.annotate_plugin
|
88
70
|
end
|
89
71
|
|
90
|
-
def
|
91
|
-
@config.filter_plugin && !@config.filter_plugin.call(env)
|
92
|
-
end
|
93
|
-
|
94
|
-
def force_sample?(env)
|
95
|
-
@config.whitelist_plugin && @config.whitelist_plugin.call(env)
|
96
|
-
end
|
97
|
-
|
98
|
-
def tracing_filter(trace_id, env, whitelisted = false)
|
72
|
+
def trace!(trace_id, zipkin_env, &block)
|
99
73
|
synchronize do
|
100
|
-
::Trace.push(trace_id)
|
101
74
|
#if called by a service, the caller already added the information
|
102
|
-
|
103
|
-
|
104
|
-
|
75
|
+
trace_request_information(trace_id, zipkin_env.env) unless zipkin_env.called_with_zipkin_headers?
|
76
|
+
@tracer.record(trace_id, Trace::Annotation.new(Trace::Annotation::SERVER_RECV, Trace.default_endpoint))
|
77
|
+
@tracer.record(trace_id, Trace::Annotation.new('whitelisted', Trace.default_endpoint)) if zipkin_env.force_sample?
|
105
78
|
end
|
106
|
-
status, headers, body = yield
|
79
|
+
status, headers, body = yield
|
107
80
|
ensure
|
108
81
|
synchronize do
|
109
|
-
|
110
|
-
|
111
|
-
::Trace.pop
|
82
|
+
annotate_plugin(zipkin_env.env, status, headers, body)
|
83
|
+
@tracer.record(trace_id, Trace::Annotation.new(Trace::Annotation::SERVER_SEND, Trace.default_endpoint))
|
112
84
|
end
|
113
|
-
[status, headers, body]
|
114
|
-
end
|
115
|
-
|
116
|
-
def add_request_information(env)
|
117
|
-
::Trace.set_rpc_name(env['REQUEST_METHOD'].to_s.downcase) # get/post and all that jazz
|
118
|
-
::Trace.record(::Trace::BinaryAnnotation.new('http.uri', env['PATH_INFO'], 'STRING', ::Trace.default_endpoint))
|
119
85
|
end
|
120
86
|
|
121
|
-
def
|
122
|
-
|
87
|
+
def trace_request_information(trace_id, env)
|
88
|
+
@tracer.set_rpc_name(trace_id, env['REQUEST_METHOD'].to_s.downcase) # get/post and all that jazz
|
89
|
+
@tracer.record(trace_id, Trace::BinaryAnnotation.new('http.uri', env['PATH_INFO'], 'STRING', Trace.default_endpoint))
|
123
90
|
end
|
124
91
|
|
125
92
|
def synchronize(&block)
|
126
93
|
@lock.synchronize do
|
127
94
|
yield
|
128
95
|
end
|
129
|
-
|
130
|
-
# Usually is better to rescue StandardError but the socket layer can launch Errno kind of exceptions
|
131
|
-
rescue Exception => e
|
96
|
+
rescue => e
|
132
97
|
@config.logger.error("Exception #{e.message} while sending Zipkin traces. #{e.backtrace}")
|
133
98
|
end
|
134
99
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
else
|
139
|
-
new_id = Trace.generate_id
|
140
|
-
[new_id, nil, new_id, ('true' if whitelisted || Trace.should_sample?)]
|
141
|
-
end
|
142
|
-
trace_parameters[3] = (trace_parameters[3] == 'true')
|
100
|
+
# Environment with Zipkin information in it
|
101
|
+
class ZipkinEnv
|
102
|
+
attr_reader :env
|
143
103
|
|
144
|
-
|
145
|
-
|
104
|
+
def initialize(env, config)
|
105
|
+
@env = env
|
106
|
+
@config = config
|
107
|
+
end
|
108
|
+
|
109
|
+
def trace_id(default_flags = Trace::Flags::EMPTY)
|
110
|
+
trace_parameters = if called_with_zipkin_headers?
|
111
|
+
@env.values_at(*B3_REQUIRED_HEADERS)
|
112
|
+
else
|
113
|
+
new_id = Trace.generate_id
|
114
|
+
[new_id, nil, new_id]
|
115
|
+
end
|
116
|
+
trace_parameters[3] = should_trace?(trace_parameters[3])
|
117
|
+
trace_parameters += @env.values_at(*B3_OPT_HEADERS) # always check flags
|
118
|
+
trace_parameters[4] = (trace_parameters[4] || default_flags).to_i
|
119
|
+
|
120
|
+
Trace::TraceId.new(*trace_parameters)
|
121
|
+
end
|
122
|
+
|
123
|
+
def called_with_zipkin_headers?
|
124
|
+
@called_with_zipkin_headers ||= B3_REQUIRED_HEADERS.all? { |key| @env.has_key?(key) }
|
125
|
+
end
|
126
|
+
|
127
|
+
def force_sample?
|
128
|
+
@force_sample ||= @config.whitelist_plugin && @config.whitelist_plugin.call(@env)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
146
132
|
|
147
|
-
|
133
|
+
def current_trace_sampled?
|
134
|
+
rand < @config.sample_rate
|
135
|
+
end
|
136
|
+
|
137
|
+
def should_trace?(parent_trace_sampled)
|
138
|
+
if parent_trace_sampled # A service upstream decided this goes in all the way
|
139
|
+
parent_trace_sampled == 'true'
|
140
|
+
else
|
141
|
+
force_sample? || current_trace_sampled? && !filtered?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def filtered?
|
146
|
+
@config.filter_plugin && !@config.filter_plugin.call(@env)
|
147
|
+
end
|
148
148
|
end
|
149
|
+
|
149
150
|
end
|
150
151
|
end
|
data/lib/zipkin-tracer/trace.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
require 'finagle-thrift'
|
2
2
|
require 'finagle-thrift/trace'
|
3
|
+
require 'zipkin-tracer/zipkin_tracer_base'
|
3
4
|
|
4
5
|
module Trace
|
6
|
+
|
7
|
+
# We need this to access the tracer from the Faraday middleware.
|
8
|
+
def self.tracer
|
9
|
+
@tracer
|
10
|
+
end
|
11
|
+
|
5
12
|
class Span
|
6
13
|
def to_h
|
7
14
|
{
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module ZipkinTracer
|
3
|
+
class TracerFactory
|
4
|
+
def tracer(config)
|
5
|
+
adapter = config.adapter
|
6
|
+
|
7
|
+
tracer = case adapter
|
8
|
+
when :json
|
9
|
+
require 'zipkin-tracer/zipkin_json_tracer'
|
10
|
+
options = { json_api_host: config.json_api_host, traces_buffer: config.traces_buffer, logger: config.logger }
|
11
|
+
Trace::ZipkinJsonTracer.new(options)
|
12
|
+
when :scribe
|
13
|
+
require 'zipkin-tracer/careless_scribe'
|
14
|
+
Trace::ZipkinTracer.new(CarelessScribe.new(config.scribe_server), config.scribe_max_buffer)
|
15
|
+
when :kafka
|
16
|
+
require 'zipkin-tracer/zipkin_kafka_tracer'
|
17
|
+
Trace::ZipkinKafkaTracer.new(zookeepers: config.zookeeper)
|
18
|
+
else
|
19
|
+
Trace::NullTracer.new
|
20
|
+
end
|
21
|
+
Trace.tracer = tracer
|
22
|
+
|
23
|
+
# TODO: move this to the TracerBase and kill scribe tracer
|
24
|
+
ip_format = config.adapter == :json ? :string : :i32
|
25
|
+
Trace.default_endpoint = Trace::Endpoint.make_endpoint(
|
26
|
+
nil, # auto detect hostname
|
27
|
+
config.service_port,
|
28
|
+
service_name(config.service_name),
|
29
|
+
ip_format
|
30
|
+
)
|
31
|
+
tracer
|
32
|
+
end
|
33
|
+
|
34
|
+
# Use the Domain environment variable to extract the service name, otherwise use the default config name
|
35
|
+
# TODO: move to the config object
|
36
|
+
def service_name(default_name)
|
37
|
+
ENV["DOMAIN"].to_s.empty? ? default_name : ENV["DOMAIN"].split('.').first
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'json'
|
2
|
-
require 'faraday'
|
3
2
|
require 'sucker_punch'
|
4
|
-
require '
|
3
|
+
require 'zipkin-tracer/zipkin_tracer_base'
|
4
|
+
|
5
5
|
|
6
6
|
class AsyncJsonApiClient
|
7
7
|
include SuckerPunch::Job
|
@@ -19,55 +19,18 @@ class AsyncJsonApiClient
|
|
19
19
|
end
|
20
20
|
|
21
21
|
module Trace
|
22
|
-
class
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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 = {}
|
22
|
+
# This class sends information to the Zipkin API.
|
23
|
+
# The API accepts a JSON representation of a list of spans
|
24
|
+
class ZipkinJsonTracer < ZipkinTracerBase
|
25
|
+
|
26
|
+
def initialize(options)
|
27
|
+
SuckerPunch.logger = options[:logger]
|
28
|
+
@json_api_host = options[:json_api_host]
|
29
|
+
super(options)
|
66
30
|
end
|
67
31
|
|
68
32
|
def flush!
|
69
|
-
AsyncJsonApiClient.new.async.perform(@json_api_host,
|
70
|
-
reset
|
33
|
+
AsyncJsonApiClient.new.async.perform(@json_api_host, spans.values.dup)
|
71
34
|
end
|
72
35
|
end
|
73
36
|
end
|
@@ -2,64 +2,32 @@ require 'finagle-thrift'
|
|
2
2
|
require 'finagle-thrift/tracer'
|
3
3
|
require 'hermann/producer'
|
4
4
|
require 'hermann/discovery/zookeeper'
|
5
|
+
require 'zipkin-tracer/zipkin_tracer_base'
|
5
6
|
|
6
7
|
module Trace
|
7
|
-
class
|
8
|
-
|
8
|
+
# This class sends information to Zipkin through Kafka.
|
9
|
+
# Spans are encoded using Thrift
|
10
|
+
class ZipkinKafkaTracer < ZipkinTracerBase
|
9
11
|
DEFAULT_KAFKA_TOPIC = "zipkin_kafka".freeze
|
10
12
|
|
11
|
-
def initialize(
|
12
|
-
@
|
13
|
-
|
14
|
-
reset
|
15
|
-
end
|
16
|
-
|
17
|
-
# need to connect after initialization
|
18
|
-
def connect(zookeepers)
|
19
|
-
broker_ids = Hermann::Discovery::Zookeeper.new(zookeepers).get_brokers
|
13
|
+
def initialize(options = {})
|
14
|
+
@topic = options[:topic] || DEFAULT_KAFKA_TOPIC
|
15
|
+
broker_ids = Hermann::Discovery::Zookeeper.new(options[:zookeepers]).get_brokers
|
20
16
|
@producer = Hermann::Producer.new(nil, broker_ids)
|
17
|
+
options[:traces_buffer] ||= 1 # Default in Kafka is sending as soon as possible. No buffer.
|
18
|
+
super(options)
|
21
19
|
end
|
22
20
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
when Annotation
|
31
|
-
span.annotations << annotation
|
21
|
+
def flush!
|
22
|
+
messages = spans.values.map do |span|
|
23
|
+
buf = ''
|
24
|
+
trans = Thrift::MemoryBufferTransport.new(buf)
|
25
|
+
oprot = Thrift::BinaryProtocol.new(trans)
|
26
|
+
span.to_thrift.write(oprot)
|
27
|
+
@producer.push(buf, topic: @topic).value!
|
32
28
|
end
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
def set_rpc_name(id, name)
|
38
|
-
return unless id.sampled?
|
39
|
-
span = get_span_for_id(id)
|
40
|
-
span.name = name.to_s
|
29
|
+
rescue Exception
|
30
|
+
# Ignore socket errors, etc
|
41
31
|
end
|
42
|
-
|
43
|
-
private
|
44
|
-
def reset
|
45
|
-
@spans = {}
|
46
|
-
end
|
47
|
-
|
48
|
-
def get_span_for_id(id)
|
49
|
-
key = id.span_id.to_s
|
50
|
-
@spans[key] ||= begin
|
51
|
-
Span.new("", id)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def flush!
|
56
|
-
messages = @spans.values.map do |span|
|
57
|
-
buf = ''
|
58
|
-
trans = Thrift::MemoryBufferTransport.new(buf)
|
59
|
-
oprot = Thrift::BinaryProtocol.new(trans)
|
60
|
-
span.to_thrift.write(oprot)
|
61
|
-
@producer.push(buf, :topic => @topic).value!
|
62
|
-
end
|
63
|
-
end
|
64
32
|
end
|
65
|
-
end
|
33
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'finagle-thrift'
|
3
|
+
require 'finagle-thrift/tracer'
|
4
|
+
|
5
|
+
module Trace
|
6
|
+
# This class is a base for tracers sending information to Zipkin.
|
7
|
+
# It knows about zipkin types of annotations and send traces when the server
|
8
|
+
# is done with its request
|
9
|
+
# Traces dealing with zipkin should inherit from this class and implement the
|
10
|
+
# flush! method which actually sends the information
|
11
|
+
class ZipkinTracerBase < Tracer
|
12
|
+
TRACER_CATEGORY = "zipkin".freeze
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
@options = options
|
16
|
+
@traces_buffer = options[:traces_buffer] || raise(ArgumentError, 'A proper buffer must be setup for the Zipkin tracer')
|
17
|
+
reset
|
18
|
+
end
|
19
|
+
|
20
|
+
def record(id, annotation)
|
21
|
+
span = get_span_for_id(id)
|
22
|
+
|
23
|
+
case annotation
|
24
|
+
when BinaryAnnotation
|
25
|
+
span.binary_annotations << annotation
|
26
|
+
when Annotation
|
27
|
+
span.annotations << annotation
|
28
|
+
end
|
29
|
+
count = current_count
|
30
|
+
set_current_count(count + 1)
|
31
|
+
|
32
|
+
if current_count >= @traces_buffer || (annotation.is_a?(Annotation) && annotation.value == Annotation::SERVER_SEND)
|
33
|
+
flush!
|
34
|
+
reset
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_rpc_name(id, name)
|
39
|
+
span = get_span_for_id(id)
|
40
|
+
span.name = name.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def flush!
|
44
|
+
raise "not implemented"
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def spans
|
50
|
+
Thread.current[:zipkin_spans] ||= {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def current_count
|
54
|
+
Thread.current[:zipkin_spans_count] ||= 0
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_current_count(count)
|
58
|
+
Thread.current[:zipkin_spans_count] = count
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_span_for_id(id)
|
62
|
+
key = id.span_id.to_s
|
63
|
+
spans[key] ||= Span.new("", id)
|
64
|
+
end
|
65
|
+
|
66
|
+
def reset
|
67
|
+
Thread.current[:zipkin_spans] = {}
|
68
|
+
set_current_count(0)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
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.10.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: 2015-12-
|
16
|
+
date: 2015-12-29 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: finagle-thrift
|
@@ -99,20 +99,6 @@ dependencies:
|
|
99
99
|
- - ~>
|
100
100
|
- !ruby/object:Gem::Version
|
101
101
|
version: '10.0'
|
102
|
-
- !ruby/object:Gem::Dependency
|
103
|
-
name: pry
|
104
|
-
requirement: !ruby/object:Gem::Requirement
|
105
|
-
requirements:
|
106
|
-
- - ~>
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: '0.10'
|
109
|
-
type: :development
|
110
|
-
prerelease: false
|
111
|
-
version_requirements: !ruby/object:Gem::Requirement
|
112
|
-
requirements:
|
113
|
-
- - ~>
|
114
|
-
- !ruby/object:Gem::Version
|
115
|
-
version: '0.10'
|
116
102
|
- !ruby/object:Gem::Dependency
|
117
103
|
name: faraday
|
118
104
|
requirement: !ruby/object:Gem::Requirement
|
@@ -201,9 +187,11 @@ files:
|
|
201
187
|
- lib/zipkin-tracer/faraday/zipkin-tracer.rb
|
202
188
|
- lib/zipkin-tracer/rack/zipkin-tracer.rb
|
203
189
|
- lib/zipkin-tracer/trace.rb
|
190
|
+
- lib/zipkin-tracer/tracer_factory.rb
|
204
191
|
- lib/zipkin-tracer/version.rb
|
205
192
|
- lib/zipkin-tracer/zipkin_json_tracer.rb
|
206
193
|
- lib/zipkin-tracer/zipkin_kafka_tracer.rb
|
194
|
+
- lib/zipkin-tracer/zipkin_tracer_base.rb
|
207
195
|
homepage: https://github.com/openzipkin/zipkin-tracer
|
208
196
|
licenses: []
|
209
197
|
metadata: {}
|