zipkin-tracer 0.11.0 → 0.12.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
- MmU0MDJhYzQxZGM5ODVkZmI0NzliYzI3MGQ0MmRhYjUyNmRhNjE2MQ==
4
+ MDU1NDhkYTRmYTdjMGI5ZDg0M2ZhZDRmZTY3ZWI3MjQ0ZjAyMGQwMQ==
5
5
  data.tar.gz: !binary |-
6
- YWQ3ZDNhMmY4YjhkMmUxZDgwOTY5NzIyZGU0NzJkYjNmNGFkZGM0Zg==
6
+ OTcwOTZmNWYyYmIxNGIxMzY5NWVlYjM4ODVlMzQ2MGE0MTk1NjJiNg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NmRlMTEzYmEzYzM5YmQ4MzllNTViZDdjOWY0ZmU1YzMzYjYxZjZlZWM5MGFl
10
- NWU3OGVmMDA1MGJiZTA0Y2I5M2M4ZTRiOGZkMTJiYWI2ZmU1NTY5NTM4MWU2
11
- NWY3MWFjZDEzNzY0N2UwMmJkZDBiNWM4NTcxNjU5YzhiYzA0YmY=
9
+ ZTE4ZThiOTZjN2Y2MWUxNDBhMDRlMGZjYjI1NGUwZGIyNWQ0YThhNmFiN2I0
10
+ NzJjNzJiYmE0ZWJkNmFhZTI1YzYxNGFiYjk1NjM4NGZjNTZhMjQzZjMxODgx
11
+ ZTM3NmM1M2Y4OGFkNDc4ZTBkNDM3MTc4MjMyMWM5MWIyMjU0OTc=
12
12
  data.tar.gz: !binary |-
13
- NmNjMzA2OWQzYmE5ZGVkNDNjOWM5ODkyZjYxZjZiN2FmMWM5MjljMTdjODdh
14
- ZGQ4YjVlOWFmOWMzODgyMWEyNWZlNzdjODk4YjA5ODk0YTU0ZjM1NjBjNTRh
15
- MzVjZmFmZmY2YmIzMDRhYjU1MWIxOGRlMTRhY2M1NzBjMTBlMzI=
13
+ YTU1YjJkZDU5NTU3MzY3OWFmNzE4Yjk4OTM0MGM5YTE3NjUyMzY1MzJmOGE0
14
+ MDNhYWNmNGI3NjEyMGQ3OGE4NDEyODRjZWQzNjUwYmEyMGIwMWFhNzU4ZDBi
15
+ MGRhMjM0YTRlNjE0ZTdhNjA0NTMzOTA4ZjYyYTNhNjg2Y2MxMWM=
@@ -0,0 +1,30 @@
1
+ module ZipkinTracer
2
+
3
+ # Useful methods on the Application we are instrumenting
4
+ class Application
5
+ # If the request is not valid for this service, we do not what to trace it.
6
+ def self.routable_request?(path_info)
7
+ return true unless defined?(Rails) # If not running on a Rails app, we can't verify if it is invalid
8
+ Rails.application.routes.recognize_path(path_info)
9
+ true
10
+ rescue ActionController::RoutingError
11
+ false
12
+ end
13
+
14
+ def self.logger
15
+ if defined?(Rails) # If we happen to be inside a Rails app, use its logger
16
+ Rails.logger
17
+ else
18
+ Logger.new(STDOUT)
19
+ end
20
+ end
21
+
22
+ def self.config(app)
23
+ if app.respond_to?(:config) && app.config.respond_to?(:zipkin_tracer)
24
+ app.config.zipkin_tracer
25
+ else
26
+ {}
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,13 +1,15 @@
1
1
  require 'logger'
2
- module ZipkinTracer
2
+ require 'zipkin-tracer/application'
3
3
 
4
+ module ZipkinTracer
5
+ # Configuration of this gem. It reads the configuration and provides default values
4
6
  class Config
5
7
  attr_reader :service_name, :service_port, :json_api_host, :traces_buffer,
6
8
  :scribe_server, :zookeeper, :sample_rate, :scribe_max_buffer, :annotate_plugin,
7
9
  :filter_plugin, :whitelist_plugin, :logger
8
10
 
9
11
  def initialize(app, config_hash)
10
- config = config_hash || app_config(app)
12
+ config = config_hash || Application.config(app)
11
13
  @service_name = config[:service_name]
12
14
  @service_port = config[:service_port] || DEFAULTS[:service_port]
13
15
  @json_api_host = config[:json_api_host]
@@ -19,7 +21,7 @@ module ZipkinTracer
19
21
  @annotate_plugin = config[:annotate_plugin] # call for trace annotation
20
22
  @filter_plugin = config[:filter_plugin] # skip tracing if returns false
21
23
  @whitelist_plugin = config[:whitelist_plugin] # force sampling if returns true
22
- @logger = config[:logger] || fallback_logger
24
+ @logger = config[:logger] || Application.logger
23
25
  end
24
26
 
25
27
  def adapter
@@ -36,14 +38,6 @@ module ZipkinTracer
36
38
 
37
39
  private
38
40
 
39
- def fallback_logger
40
- if defined?(Rails) # If we happen to be inside a Rails app, use its logger
41
- Rails.logger
42
- else
43
- Logger.new(STDOUT)
44
- end
45
- end
46
-
47
41
  DEFAULTS = {
48
42
  traces_buffer: 100,
49
43
  scribe_max_buffer: 10,
@@ -51,12 +45,5 @@ module ZipkinTracer
51
45
  service_port: 80
52
46
  }
53
47
 
54
- def app_config(app)
55
- if app.respond_to?(:config) && app.config.respond_to?(:zipkin_tracer)
56
- app.config.zipkin_tracer
57
- else
58
- {}
59
- end
60
- end
61
48
  end
62
49
  end
@@ -4,6 +4,7 @@ require 'finagle-thrift/tracer'
4
4
  require 'uri'
5
5
 
6
6
  module ZipkinTracer
7
+ # Faraday middleware. It will add CR/CS annotations to outgoing connections done by Faraday
7
8
  class FaradayHandler < ::Faraday::Middleware
8
9
  B3_HEADERS = {
9
10
  trace_id: 'X-B3-TraceId',
@@ -34,21 +35,19 @@ module ZipkinTracer
34
35
  end
35
36
 
36
37
  private
37
- SERVER_ADDRESS = 'sa'
38
- SERVER_ADDRESS_SPECIAL_VALUE = '1'
39
- STRING_TYPE = 'STRING'
40
- BOOLEAN_TYPE = 'BOOL'
41
- URI_KEY = 'http.uri'
42
- STATUS_KEY = 'http.status'
43
- UNKNOWN_URL = 'unknown'
44
-
38
+ SERVER_ADDRESS = 'sa'.freeze
39
+ SERVER_ADDRESS_SPECIAL_VALUE = '1'.freeze
40
+ STRING_TYPE = 'STRING'.freeze
41
+ BOOLEAN_TYPE = 'BOOL'.freeze
42
+ URI_KEY = 'http.uri'.freeze
43
+ STATUS_KEY = 'http.status'.freeze
45
44
 
46
45
  def trace!(env, trace_id)
47
46
  response = nil
48
47
  # handle either a URI object (passed by Faraday v0.8.x in testing), or something string-izable
49
48
  url = env[:url].respond_to?(:host) ? env[:url] : URI.parse(env[:url].to_s)
50
49
  local_endpoint = Trace.default_endpoint # The rack middleware set this up for us.
51
- remote_endpoint = callee_endpoint(url, local_endpoint.ip_format) # The endpoint we are calling.
50
+ remote_endpoint = Trace::Endpoint.remote_endpoint(url, @service_name, local_endpoint.ip_format) # The endpoint we are calling.
52
51
  @tracer.with_new_span(trace_id, env[:method].to_s.downcase) do |span|
53
52
  # annotate with method (GET/POST/etc.) and uri path
54
53
  span.record(Trace::BinaryAnnotation.new(URI_KEY, url.path, STRING_TYPE, local_endpoint))
@@ -70,9 +69,5 @@ module ZipkinTracer
70
69
  Trace.pop
71
70
  end
72
71
 
73
- def callee_endpoint(url, ip_format)
74
- service_name = @service_name || url.host.split('.').first || UNKNOWN_URL # default to url-derived service name
75
- Trace::Endpoint.make_endpoint(url.host, url.port, service_name, ip_format)
76
- end
77
72
  end
78
73
  end
@@ -21,8 +21,8 @@ module ZipkinTracer
21
21
  # This middleware reads Zipkin headers from the request and sets/creates a Trace.id usable by the rest of the app
22
22
  # It will also send the trace to the Zipkin service using one of the methods configured.
23
23
  class RackHandler
24
- B3_REQUIRED_HEADERS = %w[HTTP_X_B3_TRACEID HTTP_X_B3_PARENTSPANID HTTP_X_B3_SPANID HTTP_X_B3_SAMPLED]
25
- B3_OPT_HEADERS = %w[HTTP_X_B3_FLAGS]
24
+ B3_REQUIRED_HEADERS = %w[HTTP_X_B3_TRACEID HTTP_X_B3_PARENTSPANID HTTP_X_B3_SPANID HTTP_X_B3_SAMPLED].freeze
25
+ B3_OPT_HEADERS = %w[HTTP_X_B3_FLAGS].freeze
26
26
 
27
27
  def initialize(app, config = nil)
28
28
  @app = app
@@ -35,7 +35,7 @@ module ZipkinTracer
35
35
  zipkin_env = ZipkinEnv.new(env, @config)
36
36
  trace_id = zipkin_env.trace_id
37
37
  with_trace_id(trace_id) do
38
- if !trace_id.sampled? || !routable_request?(env)
38
+ if !trace_id.sampled? || !Application.routable_request?(env['PATH_INFO'])
39
39
  @app.call(env)
40
40
  else
41
41
  @tracer.with_new_span(trace_id, zipkin_env.env['REQUEST_METHOD'].to_s.downcase) do |span|
@@ -54,15 +54,6 @@ module ZipkinTracer
54
54
  Trace.pop
55
55
  end
56
56
 
57
- # If the request is not valid for this service, we do not what to trace it.
58
- def routable_request?(env)
59
- return true unless defined?(Rails) # If not running on a Rails app, we can't verify if it is invalid
60
- Rails.application.routes.recognize_path(env['PATH_INFO'])
61
- true
62
- rescue ActionController::RoutingError
63
- false
64
- end
65
-
66
57
  def annotate_plugin(env, status, response_headers, response_body)
67
58
  @config.annotate_plugin.call(env, status, response_headers, response_body) if @config.annotate_plugin
68
59
  end
@@ -8,8 +8,11 @@ module Trace
8
8
  @tracer
9
9
  end
10
10
 
11
+ # A span may contain many annotations
12
+ # This class is defined in finagle-thrift. We are adding extra methods here
11
13
  class Span
12
14
  attr_reader :size
15
+ attr_accessor :timestamp, :duration
13
16
 
14
17
  # We record information into spans, then we send these spans to zipkin
15
18
  def record(annotation)
@@ -31,11 +34,14 @@ module Trace
31
34
  parentId: @span_id.parent_id.nil? ? nil : @span_id.parent_id.to_s,
32
35
  annotations: @annotations.map!(&:to_h),
33
36
  binaryAnnotations: @binary_annotations.map!(&:to_h),
37
+ timestamp: timestamp,
38
+ duration: duration,
34
39
  debug: @debug
35
40
  }
36
41
  end
37
42
  end
38
43
 
44
+ # This class is defined in finagle-thrift. We are adding extra methods here
39
45
  class Annotation
40
46
  def to_h
41
47
  {
@@ -46,6 +52,7 @@ module Trace
46
52
  end
47
53
  end
48
54
 
55
+ # This class is defined in finagle-thrift. We are adding extra methods here
49
56
  class BinaryAnnotation
50
57
  def to_h
51
58
  {
@@ -56,16 +63,36 @@ module Trace
56
63
  end
57
64
  end
58
65
 
66
+ # This class is defined in finagle-thrift. We are adding extra methods here
59
67
  class Endpoint
60
- LOCALHOST = '127.0.0.1'
61
- LOCALHOST_I32 = 0x7f000001
68
+ LOCALHOST = '127.0.0.1'.freeze
69
+ LOCALHOST_I32 = 0x7f000001.freeze
70
+ UNKNOWN_URL = 'unknown'.freeze
62
71
 
72
+ # we cannot override the initializer to add an extra parameter so use a factory
63
73
  attr_accessor :ip_format
64
74
 
65
- # we cannot override the initializer to add an extra parameter so use a factory
75
+ def self.local_endpoint(service_port, service_name, ip_format)
76
+ hostname = Socket.gethostname
77
+ Endpoint.make_endpoint(hostname, service_port, service_name, ip_format)
78
+ end
79
+
80
+ def self.remote_endpoint(url, remote_service_name, ip_format)
81
+ service_name = remote_service_name || url.host.split('.').first || UNKNOWN_URL # default to url-derived service name
82
+ Endpoint.make_endpoint(url.host, url.port, service_name, ip_format)
83
+ end
84
+
85
+ def to_h
86
+ {
87
+ ipv4: ipv4,
88
+ port: port,
89
+ serviceName: service_name
90
+ }
91
+ end
92
+
93
+ private
66
94
  def self.make_endpoint(hostname, service_port, service_name, ip_format)
67
95
  ipv4 = begin
68
- hostname ||= Socket.gethostname
69
96
  ip_format == :string ? Socket.getaddrinfo(hostname, nil, :INET)[0][3] : host_to_i32(hostname)
70
97
  rescue
71
98
  ip_format == :string ? LOCALHOST : LOCALHOST_I32
@@ -76,12 +103,5 @@ module Trace
76
103
  ep
77
104
  end
78
105
 
79
- def to_h
80
- {
81
- ipv4: ipv4,
82
- port: port,
83
- serviceName: service_name
84
- }
85
- end
86
106
  end
87
107
  end
@@ -0,0 +1,34 @@
1
+ module ZipkinTracer
2
+ class TraceClient
3
+ LOCAL_COMPONENT = 'lc'.freeze
4
+ STRING_TYPE = 'STRING'.freeze
5
+
6
+ def self.local_component_span(local_component_value, &block)
7
+ if block_given?
8
+ client = self.new(LOCAL_COMPONENT, &block)
9
+ client.record_local_component local_component_value
10
+ end
11
+ end
12
+
13
+ def initialize(name, &block)
14
+ @trace_id = Trace.id.next_id
15
+ Trace.tracer.with_new_span(@trace_id, name) do |span|
16
+ @span = span
17
+ block.call(self)
18
+ end
19
+ end
20
+
21
+ def record(key)
22
+ @span.record(Trace::Annotation.new(key, Trace.default_endpoint)) if @trace_id.sampled?
23
+ end
24
+
25
+ def record_tag(key, value)
26
+ @span.record(Trace::BinaryAnnotation.new(key, value, STRING_TYPE, Trace.default_endpoint)) if @trace_id.sampled?
27
+ end
28
+
29
+ def record_local_component(value)
30
+ record_tag(LOCAL_COMPONENT, value)
31
+ end
32
+
33
+ end
34
+ end
@@ -22,8 +22,7 @@ module ZipkinTracer
22
22
 
23
23
  # TODO: move this to the TracerBase and kill scribe tracer
24
24
  ip_format = config.adapter == :json ? :string : :i32
25
- Trace.default_endpoint = Trace::Endpoint.make_endpoint(
26
- nil, # auto detect hostname
25
+ Trace.default_endpoint = Trace::Endpoint.local_endpoint(
27
26
  config.service_port,
28
27
  service_name(config.service_name),
29
28
  ip_format
@@ -12,5 +12,5 @@
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.11.0"
15
+ VERSION = "0.12.0"
16
16
  end
@@ -17,14 +17,17 @@ module Trace
17
17
 
18
18
  def with_new_span(trace_id, name)
19
19
  span = start_span(trace_id, name)
20
+ start_time = Time.now
21
+ span.timestamp = to_microseconds(start_time)
20
22
  result = yield span
23
+ span.duration = to_microseconds(Time.now - start_time)
21
24
  may_flush(span)
22
25
  result
23
26
  end
24
27
 
25
28
  def may_flush(span)
26
29
  size = spans.values.map(&:size).inject(:+) || 0
27
- if size >= @traces_buffer || span.annotations.any?{ |ann| ann == Annotation::SERVER_SEND }
30
+ if size >= @traces_buffer || span.annotations.any?{ |ann| ann.value == Annotation::SERVER_SEND }
28
31
  flush!
29
32
  reset
30
33
  end
@@ -54,5 +57,9 @@ module Trace
54
57
  def reset
55
58
  Thread.current[:zipkin_spans] = {}
56
59
  end
60
+
61
+ def to_microseconds(time)
62
+ (time.to_f * 1_000_000).to_i
63
+ end
57
64
  end
58
65
  end
data/lib/zipkin-tracer.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'base64' #Bug in finagle. They should be requiring this: finagle-thrift-1.4.1/lib/finagle-thrift/tracer.rb:115
2
2
  require 'zipkin-tracer/trace'
3
3
  require 'zipkin-tracer/rack/zipkin-tracer'
4
+ require 'zipkin-tracer/trace_client'
4
5
 
5
6
  begin
6
7
  require 'faraday'
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.11.0
4
+ version: 0.12.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: 2016-01-28 00:00:00.000000000 Z
16
+ date: 2016-02-02 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: faraday
@@ -182,11 +182,13 @@ extensions: []
182
182
  extra_rdoc_files: []
183
183
  files:
184
184
  - lib/zipkin-tracer.rb
185
+ - lib/zipkin-tracer/application.rb
185
186
  - lib/zipkin-tracer/careless_scribe.rb
186
187
  - lib/zipkin-tracer/config.rb
187
188
  - lib/zipkin-tracer/faraday/zipkin-tracer.rb
188
189
  - lib/zipkin-tracer/rack/zipkin-tracer.rb
189
190
  - lib/zipkin-tracer/trace.rb
191
+ - lib/zipkin-tracer/trace_client.rb
190
192
  - lib/zipkin-tracer/tracer_factory.rb
191
193
  - lib/zipkin-tracer/version.rb
192
194
  - lib/zipkin-tracer/zipkin_json_tracer.rb