zipkin 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8361e78533130479672a85ad8d5273035cdd261d
4
- data.tar.gz: 21ec14ab24345d5f4a320efa33570df8bee51b4a
3
+ metadata.gz: 504536eebfe1f9f6ce03dd1c9bb1ef0d2c0d870f
4
+ data.tar.gz: 9e7638f5c9b6cfc0a1061955f3475ad1c5f352d8
5
5
  SHA512:
6
- metadata.gz: b63f0b37631dea5cd999f24c83ce688946244bd6b5e5aebf1201d75ea3e3d050a3f1daa0d46d8253ed2c4e314c9c1aa98707e32b03b26bf0a17cf4fe903c477f
7
- data.tar.gz: ca8ae8cfff2d1b302967652e57c7c1d0039d035c3e006a8e004e30eef3505c4409407c224af3c9f992567106b147570eea2a7b092e0ef8855edf8817a1ee6198
6
+ metadata.gz: 0fff4fc9878ad37a878968c8805a755f110ac98418dcd88f4229fca5ceb41642c3f66df02a2aad9a0d1903e9dfbd824a359dff77d870a33b5de936b53fe04bfe
7
+ data.tar.gz: 31b4d916668c882181a08aeb1026557e42051a5ea6b7c91074085ff83ade66153ea3df616ca001ef67a48e804f114cedc45faacffa02441621c58fe477b36135
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Zipkin
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/zipkin`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ OpenTracing Tracer implementation for Zipkin in Ruby
6
4
 
7
5
  ## Installation
8
6
 
@@ -12,17 +10,15 @@ Add this line to your application's Gemfile:
12
10
  gem 'zipkin'
13
11
  ```
14
12
 
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install zipkin
22
-
23
13
  ## Usage
24
14
 
25
- TODO: Write usage instructions here
15
+ ```ruby
16
+ require 'zipkin/tracer'
17
+ OpenTracing.global_tracer = Zipkin::Tracer.build(url: 'http://localhost:9411', service_name: 'echo')
18
+
19
+ span = OpenTracing.start_span('span name')
20
+ span.finish
21
+ ```
26
22
 
27
23
  ## Development
28
24
 
@@ -32,7 +28,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
28
 
33
29
  ## Contributing
34
30
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/Indrek Juhkam/zipkin.
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/salemove/zipkin-ruby-opentracing
36
32
 
37
33
 
38
34
  ## License
@@ -0,0 +1,12 @@
1
+ module Zipkin
2
+ class Endpoint
3
+ LOCAL_IP = Socket.ip_address_list.detect(&:ipv4_private?).ip_address
4
+
5
+ def self.local_endpoint(service_name)
6
+ {
7
+ serviceName: service_name,
8
+ ipv4: LOCAL_IP
9
+ }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'sucker_punch'
4
+
5
+ module Zipkin
6
+ class JsonClient
7
+ def initialize(url)
8
+ @faraday = Faraday.new(url: url) do |faraday|
9
+ faraday.request :json
10
+ faraday.request :retry, max: 3, interval: 10, backoff_factor: 2
11
+ faraday.adapter Faraday.default_adapter
12
+ end
13
+ end
14
+
15
+ def send_span(payload)
16
+ SpanSender.perform_async(payload: payload, faraday: @faraday)
17
+ end
18
+
19
+ class SpanSender
20
+ include SuckerPunch::Job
21
+ workers 4
22
+
23
+ def perform(payload:, faraday:)
24
+ response = faraday.post '/api/v1/spans' do |req|
25
+ req.body = [payload]
26
+ end
27
+
28
+ if response.status != 202
29
+ STDERR.puts(response.body)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/zipkin/span.rb CHANGED
@@ -6,13 +6,18 @@ module Zipkin
6
6
 
7
7
  # Creates a new {Span}
8
8
  #
9
- # @param tracer [Tracer] the tracer that created this span
10
9
  # @param context [SpanContext] the context of the span
10
+ # @param context [String] the operation name
11
+ # @param client [Faraday] faraday instace for making http requests
11
12
  #
12
13
  # @return [Span] a new Span
13
- def initialize(tracer, context)
14
- @tracer = tracer
14
+ def initialize(context, operation_name, client, start_time: Time.now, tags: {}, local_endpoint:)
15
15
  @context = context
16
+ @operation_name = operation_name
17
+ @client = client
18
+ @start_time = start_time
19
+ @tags = tags
20
+ @local_endpoint = local_endpoint
16
21
  end
17
22
 
18
23
  # Set a tag value on this span
@@ -21,7 +26,7 @@ module Zipkin
21
26
  # @param value [String, Numeric, Boolean] the value of the tag. If it's not
22
27
  # a String, Numeric, or Boolean it will be encoded with to_s
23
28
  def set_tag(key, value)
24
- self
29
+ @tags = @tags.merge(key => value)
25
30
  end
26
31
 
27
32
  # Set a baggage item on the span
@@ -54,7 +59,40 @@ module Zipkin
54
59
  #
55
60
  # @param end_time [Time] custom end time, if not now
56
61
  def finish(end_time: Time.now)
57
- nil
62
+ finish_ts = (end_time.to_f * 1_000_000).to_i
63
+ start_ts = (@start_time.to_f * 1_000_000).to_i
64
+ duration = finish_ts - start_ts
65
+ is_server = ['server', 'consumer'].include?(@tags['span.kind'] || 'server')
66
+
67
+ @client.send_span(
68
+ traceId: @context.trace_id,
69
+ id: @context.span_id,
70
+ parentId: @context.parent_id,
71
+ name: @operation_name,
72
+ timestamp: start_ts,
73
+ duration: duration,
74
+ annotations: [
75
+ {
76
+ timestamp: start_ts,
77
+ value: is_server ? 'sr' : 'cs',
78
+ endpoint: @local_endpoint
79
+ },
80
+ {
81
+ timestamp: finish_ts,
82
+ value: is_server ? 'ss': 'cr',
83
+ endpoint: @local_endpoint
84
+ }
85
+ ],
86
+ binaryAnnotations: build_binary_annotations
87
+ )
88
+ end
89
+
90
+ private
91
+
92
+ def build_binary_annotations
93
+ @tags.map do |name, value|
94
+ {key: name, value: value.to_s}
95
+ end
58
96
  end
59
97
  end
60
98
  end
@@ -2,14 +2,14 @@ module Zipkin
2
2
  # SpanContext holds the data for a span that gets inherited to child spans
3
3
  class SpanContext
4
4
  def self.create_parent_context
5
+ trace_id = TraceId.generate
5
6
  span_id = TraceId.generate
6
- trace_id = span_id
7
- new(span_id: span_id, trace_id: trace_id)
7
+ new(trace_id: trace_id, span_id: span_id)
8
8
  end
9
9
 
10
- def self.create_from_parent(parent_span)
11
- trace_id = parent_span.context.trace_id
12
- parent_id = parent_span.context.span_id
10
+ def self.create_from_parent_context(span_context)
11
+ trace_id = span_context.trace_id
12
+ parent_id = span_context.span_id
13
13
  span_id = TraceId.generate
14
14
  new(span_id: span_id, parent_id: parent_id, trace_id: trace_id)
15
15
  end
@@ -3,7 +3,7 @@ module Zipkin
3
3
  TRACE_ID_UPPER_BOUND = 2 ** 64
4
4
 
5
5
  def self.generate
6
- rand(TRACE_ID_UPPER_BOUND)
6
+ rand(TRACE_ID_UPPER_BOUND).to_s(16)
7
7
  end
8
8
  end
9
9
  end
data/lib/zipkin/tracer.rb CHANGED
@@ -1,71 +1,96 @@
1
+ require 'opentracing'
2
+
3
+ require_relative 'span'
4
+ require_relative 'span_context'
5
+ require_relative 'carrier'
6
+ require_relative 'trace_id'
7
+ require_relative 'json_client'
8
+ require_relative 'endpoint'
9
+
1
10
  module Zipkin
2
11
  class Tracer
3
- def self.build(host:, port:, service_name:)
12
+ def self.build(url:, service_name:)
13
+ client = JsonClient.new(url)
14
+ new(client, service_name)
4
15
  end
5
16
 
6
- def initialize(client)
17
+ def initialize(client, service_name)
7
18
  @client = client
19
+ @local_endpoint = Endpoint.local_endpoint(service_name)
8
20
  end
9
21
 
10
- # Start a new span
22
+ # Starts a new span.
11
23
  #
12
- # @param operation_name [String]
13
- # The operation name for the Span
14
- # @param child_of [SpanContext]
15
- # SpanContext that acts as a parent to the newly-started Span. If a Span
16
- # instance is provided, its #context is automatically substituted.
17
- # @param start_time [Time]
18
- # The time when the Span started, if not now
19
- # @param tags [Hash]
20
- # Tags to assign to the Span at start time
24
+ # @param operation_name [String] The operation name for the Span
25
+ # @param child_of [SpanContext, Span] SpanContext that acts as a parent to
26
+ # the newly-started Span. If a Span instance is provided, its
27
+ # context is automatically substituted.
28
+ # @param start_time [Time] When the Span started, if not now
29
+ # @param tags [Hash] Tags to assign to the Span at start time
21
30
  #
22
- # @return [Span]
23
- # The newly-started Span
24
- def start_span(operation_name, child_of: nil, start_time: Time.now, tags: nil)
31
+ # @return [Span] The newly-started Span
32
+ def start_span(operation_name, child_of: nil, start_time: Time.now, tags: {}, **)
25
33
  context =
26
34
  if child_of
27
- SpanContext.create_from_parent(child_of)
35
+ parent_context = child_of.respond_to?(:context) ? child_of.context : child_of
36
+ SpanContext.create_from_parent_context(parent_context)
28
37
  else
29
38
  SpanContext.create_parent_context
30
39
  end
31
- span = Span.new(self, context)
32
- span.operation_name = operation_name
33
- span
40
+ Span.new(context, operation_name, @client, start_time: start_time, tags: tags, local_endpoint: @local_endpoint)
34
41
  end
35
42
 
36
43
  # Inject a SpanContext into the given carrier
37
44
  #
38
45
  # @param span_context [SpanContext]
39
46
  # @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
40
- #
41
- # @param carrier [Carrier]
42
- # A carrier object of the type dictated by the specified `format`
47
+ # @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
43
48
  def inject(span_context, format, carrier)
44
49
  case format
45
- when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK
46
- return nil
50
+ when OpenTracing::FORMAT_TEXT_MAP
51
+ carrier['trace-id'] = span_context.trace_id
52
+ carrier['parent-id'] = span_context.parent_id
53
+ carrier['span-id'] = span_context.span_id
54
+ when OpenTracing::FORMAT_RACK
55
+ carrier['X-Trace-Id'] = span_context.trace_id
56
+ carrier['X-Trace-Parent-Id'] = span_context.parent_id
57
+ carrier['X-Trace-Span-Id'] = span_context.span_id
47
58
  else
48
- warn 'Unknown inject format'
59
+ STDERR.puts "Logasm::Tracer with format #{format} is not supported yet"
49
60
  end
50
61
  end
51
62
 
52
63
  # Extract a SpanContext in the given format from the given carrier.
53
64
  #
54
65
  # @param format [OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK]
55
- # @param carrier [Carrier]
56
- # A carrier object of the type dictated by the specified `format`
57
- #
58
- # @return [SpanContext]
59
- # the extracted SpanContext or nil if none could be found
66
+ # @param carrier [Carrier] A carrier object of the type dictated by the specified `format`
67
+ # @return [SpanContext] the extracted SpanContext or nil if none could be found
60
68
  def extract(format, carrier)
61
69
  case format
62
- when OpenTracing::FORMAT_TEXT_MAP, OpenTracing::FORMAT_BINARY, OpenTracing::FORMAT_RACK
63
- return SpanContext::NOOP_INSTANCE
70
+ when OpenTracing::FORMAT_TEXT_MAP
71
+ trace_id = carrier['trace-id']
72
+ parent_id = carrier['parent-id']
73
+ span_id = carrier['span-id']
74
+
75
+ if trace_id && span_id
76
+ SpanContext.new(trace_id: trace_id, parent_id: parent_id, span_id: span_id)
77
+ else
78
+ nil
79
+ end
80
+ when OpenTracing::FORMAT_RACK
81
+ trace_id = carrier['HTTP_X_TRACE_ID']
82
+ parent_id = carrier['HTTP_X_TRACE_PARENT_ID']
83
+ span_id = carrier['HTTP_X_TRACE_SPAN_ID']
84
+
85
+ if trace_id && span_id
86
+ SpanContext.new(trace_id: trace_id, parent_id: parent_id, span_id: span_id)
87
+ else
88
+ nil
89
+ end
64
90
  else
65
- warn 'Unknown extract format'
91
+ STDERR.puts "Logasm::Tracer with format #{format} is not supported yet"
66
92
  nil
67
93
  end
68
94
  end
69
-
70
95
  end
71
96
  end
data/lib/zipkin.rb CHANGED
@@ -1,8 +1,4 @@
1
1
  require_relative './zipkin/tracer'
2
- require_relative './zipkin/span'
3
- require_relative './zipkin/span_context'
4
- require_relative './zipkin/carrier'
5
- require_relative './zipkin/trace_id'
6
2
 
7
3
  module Zipkin
8
4
  end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler'
4
+ Bundler.setup
5
+
6
+ require 'zipkin/tracer'
7
+
8
+ url = ENV['ZIPKIN_URL'] || 'http://localhost:9411'
9
+
10
+ tracer1 = Zipkin::Tracer.build(url: url, service_name: 'test-service')
11
+ tracer2 = Zipkin::Tracer.build(url: url, service_name: 'downstream-service')
12
+
13
+ outer_span = tracer1.start_span('receive request', tags: {
14
+ 'span.kind' => 'server'
15
+ })
16
+ sleep 1
17
+
18
+ inner_span = tracer1.start_span('fetch info from downstream', child_of: outer_span, tags: {
19
+ 'span.kind' => 'client',
20
+ 'peer.service' => 'downstream-service',
21
+ 'peer.ipv4' => '6.6.6.6',
22
+ 'peer.port' => 443
23
+ })
24
+ sleep 0.3 # emulate network delay
25
+
26
+ downstream_span = tracer2.start_span('downstream operation', child_of: inner_span, tags: {
27
+ 'span.kind' => 'server'
28
+ })
29
+ sleep 0.5
30
+ downstream_span.finish
31
+
32
+ sleep 0.2 # emulate network delay
33
+
34
+ inner_span.finish
35
+
36
+ sleep 0.1 # doing something with fetched info
37
+ outer_span.finish
38
+
39
+ puts "Finishing..."
40
+ sleep 3
data/zipkin.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'zipkin'
7
- spec.version = '0.1.0'
7
+ spec.version = '0.2.0'
8
8
  spec.authors = ['SaleMove TechMovers']
9
9
  spec.email = ['techmovers@salemove.com']
10
10
 
@@ -24,4 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency 'rspec', '~> 3.0'
25
25
 
26
26
  spec.add_dependency 'opentracing', '~> 0.3'
27
+ spec.add_dependency 'faraday'
28
+ spec.add_dependency 'faraday_middleware'
29
+ spec.add_dependency 'sucker_punch', '~> 2.0'
27
30
  end
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: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SaleMove TechMovers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-04 00:00:00.000000000 Z
11
+ date: 2017-04-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,48 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: faraday
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: faraday_middleware
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sucker_punch
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
69
111
  description: ''
70
112
  email:
71
113
  - techmovers@salemove.com
@@ -84,10 +126,13 @@ files:
84
126
  - bin/setup
85
127
  - lib/zipkin.rb
86
128
  - lib/zipkin/carrier.rb
129
+ - lib/zipkin/endpoint.rb
130
+ - lib/zipkin/json_client.rb
87
131
  - lib/zipkin/span.rb
88
132
  - lib/zipkin/span_context.rb
89
133
  - lib/zipkin/trace_id.rb
90
134
  - lib/zipkin/tracer.rb
135
+ - script/create_trace
91
136
  - zipkin.gemspec
92
137
  homepage: ''
93
138
  licenses: