aws-xray 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 44943f3ac93283072875bfa94985b9aa76828628
4
- data.tar.gz: 7c58541a4ba68f4b7968505029229b1f2abb0c76
3
+ metadata.gz: 7205283919522f3fa51c16bc8e5f11136ba04a9c
4
+ data.tar.gz: 0fa4f411671929e4c436939d190afa7fd48e181e
5
5
  SHA512:
6
- metadata.gz: e266ce6f924d71c447e1ca64775efbf55de67523965b3c805eb8fac5e9c99f936590857765156a8a8333ccf4d32a6cbcd0a04519220fcd5a7cd67315ff06f0b4
7
- data.tar.gz: 1988b22141c57f19b2bb3963b2f691dbbcd8ecb6a08bdeb3037e4dfee0a20193d28c8f6899a82f7257d762eeb5a89113b382dbf1d97e9b7ab976a2c4a24221d4
6
+ metadata.gz: 9c4aea978c59e664b39d10ca7df5c57c8537069fff4df2196b7e3213fa71c990a66e05cd6e0c816a95311d03e9ace2614ecddcad036e5b04c892f78ca51b1e1e
7
+ data.tar.gz: 6519acd350a5c0a6ceddad31bdd54db472466cf35bc4d5e044404e4290475607296e9b820c64e40d1099307b715fb927ccf53c5a029b249f69531ee2cacf9a4d
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Aws::Xray
1
+ # aws-xray
2
2
  [![Build Status](https://travis-ci.org/taiki45/aws-xray.svg?branch=master)](https://travis-ci.org/taiki45/aws-xray)
3
3
  [![Gem Version](https://badge.fury.io/rb/aws-xray.svg)](https://badge.fury.io/rb/aws-xray)
4
4
 
@@ -7,18 +7,13 @@ It enables you to capture in-coming HTTP requests and out-going HTTP requests an
7
7
 
8
8
  AWS X-Ray is a ditributed tracing system. See more detail about AWS X-Ray at [official document](http://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html).
9
9
 
10
- ## Current status
11
- Implemented:
12
-
10
+ ## Features
13
11
  - Rack middleware.
14
12
  - Faraday middleware.
15
13
  - Propagatin support limited in single thread environment.
16
-
17
- Not yet:
18
-
19
14
  - Tracing HTTP request/response.
20
- - Multi thread support.
21
15
  - Tracing errors.
16
+ - Annotation and metadata support.
22
17
 
23
18
  ## Installation
24
19
 
@@ -33,10 +28,32 @@ And then execute:
33
28
  $ bundle
34
29
 
35
30
  ## Usage
31
+ ### Rails app
32
+ Insert Rack middleware by yourself:
33
+
34
+ ```
35
+ # config/initializers/aws_xray.rb
36
+ Aws::Xray.config.name = 'my-app'
37
+ Rails.application.config.middleware.use Aws::Xray::Rack
38
+ ```
39
+
40
+ Or just require `aws/xray/rails`:
41
+
42
+ ```ruby
43
+ # Gemfile
44
+ gem 'aws-xray', require: 'aws/xray/rails'
45
+
46
+ # config/initializers/aws_xray.rb
47
+ Aws::Xray.config.name = 'my-app'
48
+ ```
49
+
50
+ To trace out-going HTTP requests, see below.
51
+
36
52
  ### Rack app
37
53
  ```ruby
38
54
  # config.ru
39
55
  require 'aws-xray'
56
+ Aws::Xray.config.name = 'my-app'
40
57
  use Aws::Xray::Rack
41
58
  ```
42
59
 
@@ -62,6 +79,9 @@ end
62
79
 
63
80
  ### non-Rack app (like background jobs)
64
81
  ```ruby
82
+ require 'aws-xray'
83
+ Aws::Xray.config.name = 'my-app'
84
+
65
85
  # Build HTTP client with Faraday builder.
66
86
  # You can set the down stream app id to Host header as well.
67
87
  client = Faraday.new('...') do |builder|
@@ -81,6 +101,35 @@ Aws::Xray::Context.with_new_context('test-app', xray_client, trace_header) do
81
101
  end
82
102
  ```
83
103
 
104
+ ## Configurations
105
+ ### Recording pplication version
106
+ aws-xray automatically tries to set application version by reading `app_root/REVISION` file.
107
+ If you want to set another version, set it with:
108
+
109
+ ```ruby
110
+ # In initialization phase.
111
+ Aws::Xray.config.version = 'deadbeef'
112
+ ```
113
+
114
+ ### Default annotation and metadata
115
+ aws-xray records hostname by default.
116
+
117
+ If you want to record specific annotation in all of your segments, configure like:
118
+
119
+ ```ruby
120
+ Aws::Xray.config.default_annotation = Aws::Xray.config.default_annotation.merge(key: 'value')
121
+ ```
122
+
123
+ Keys must be alphanumeric characters with underscore and values must be one of String or Integer or Boolean values.
124
+
125
+ For meta data:
126
+
127
+ ```ruby
128
+ Aws::Xray.config.default_metadata = Aws::Xray.config.default_metadata.merge(key: ['some', 'meaningful', 'value'])
129
+ ```
130
+
131
+ Note: See official document to know what annotation and metadata are in AWS X-Ray.
132
+
84
133
  ## Development
85
134
 
86
135
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/TODO.md ADDED
@@ -0,0 +1,25 @@
1
+ Enbed user information to segment:
2
+
3
+ ```ruby
4
+ # In configuration phase
5
+ use Aws::Xray::Rack, capture_user_data: ->(env) { env['X-User-Id'] }
6
+
7
+ # Implementation image:
8
+ class Rack
9
+ def call(env)
10
+ @app.call(env)
11
+ capture_user_data.call(env)
12
+ end
13
+ ```
14
+
15
+ ---
16
+
17
+ `aws` field. Especially EC2 and ECS field.
18
+
19
+ ---
20
+
21
+ Send in_progress segment.
22
+
23
+ ---
24
+
25
+ `precursor_ids`.
data/example/Gemfile CHANGED
@@ -5,3 +5,4 @@ gem 'rack'
5
5
  gem 'aws-xray', path: File.expand_path('../', __dir__)
6
6
 
7
7
  gem 'foreman'
8
+ gem 'pry-byebug'
data/example/REVISION ADDED
@@ -0,0 +1 @@
1
+ deadbeef
@@ -1,7 +1,18 @@
1
+ require 'pry'
1
2
  require 'aws-xray'
2
3
 
3
4
  use Aws::Xray::Rack, name: 'campain-app'
4
5
 
6
+ class DbConnectionError < StandardError
7
+ def initialize
8
+ super('Could not connect to DB')
9
+ end
10
+ end
11
+
5
12
  run Proc.new {|env|
6
- ['200', {'Content-Type' => 'text/plain'}, ['0']]
13
+ if rand(0..1) == 0
14
+ raise DbConnectionError
15
+ else
16
+ ['200', {'Content-Type' => 'text/plain'}, ['0']]
17
+ end
7
18
  }
@@ -1,3 +1,4 @@
1
+ require 'pry'
1
2
  require 'faraday'
2
3
  require 'aws-xray'
3
4
 
@@ -1,3 +1,4 @@
1
+ require 'pry'
1
2
  require 'faraday'
2
3
  require 'aws-xray'
3
4
 
@@ -1,3 +1,4 @@
1
+ require 'pry'
1
2
  require 'aws-xray'
2
3
 
3
4
  use Aws::Xray::Rack, name: 'user-app'
@@ -0,0 +1,16 @@
1
+ module Aws
2
+ module Xray
3
+ module AnnotationValidator
4
+ extend self
5
+
6
+ # @param [Hash] h annotation hash.
7
+ # @raise RuntimeError
8
+ def call(h)
9
+ invalid_keys = h.keys.reject {|k| k.to_s.match(/\A[A-Za-z0-9_]+\z/) }
10
+ raise 'Keys must be alphanumeric and underscore string' unless invalid_keys.empty?
11
+ invalid_values = h.values.reject {|v| v.is_a?(String) || v.is_a?(Integer) || (v == true || v == false) }
12
+ raise 'Values must be one of String or Integer or Boolean values' unless invalid_values.empty?
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ module Aws
2
+ module Xray
3
+ class Cause
4
+ MAX_BACKTRACE_SIZE = 10
5
+
6
+ def initialize(stack: [], message: nil, type: nil)
7
+ @id = SecureRandom.hex(8)
8
+ @working_directory = Dir.pwd
9
+ @stack = stack
10
+ @message = message
11
+ @type = type
12
+ end
13
+
14
+ def to_h(remote: false)
15
+ truncated, stack = build_stack(@stack, @working_directory)
16
+ {
17
+ working_directory: @working_directory,
18
+ paths: [],
19
+ exceptions: [
20
+ {
21
+ id: @id,
22
+ message: @message,
23
+ type: @type,
24
+ remote: remote,
25
+ truncated: truncated,
26
+ stack: stack,
27
+ },
28
+ ],
29
+ }
30
+ end
31
+
32
+ def build_stack(stack, dir)
33
+ truncated = [stack.size - MAX_BACKTRACE_SIZE, 0].max
34
+ stack = stack[0..MAX_BACKTRACE_SIZE - 1].map do |s|
35
+ file, line, method_name = s.split(':')
36
+ {
37
+ path: file.sub(dir, ''),
38
+ line: line,
39
+ label: method_name,
40
+ }
41
+ end
42
+ return truncated, stack
43
+ end
44
+ end
45
+ end
46
+ end
@@ -7,15 +7,15 @@ module Aws
7
7
  #
8
8
  # XXX: keep options for implmenting copying later.
9
9
  def initialize(host: '127.0.0.1', port: 2000, sock: nil)
10
- @options = { host: host, port: port }
11
- @sock = sock || Addrinfo.udp(host, port).connect
10
+ @host, @port = host, port
11
+ @sock = sock || UDPSocket.new
12
12
  end
13
13
 
14
14
  # @param [Aws::Xray::Segment] segment
15
15
  def send_segment(segment)
16
16
  segment.finish
17
17
  payload = %!{"format": "json", "version": 1}\n#{segment.to_json}\n!
18
- len = @sock.send(payload, 0)
18
+ len = @sock.send(payload, 0, @host, @port)
19
19
  # TODO: retry
20
20
  if payload.size != len
21
21
  $stderr.puts("Can not send all bytes: #{len} sent")
@@ -0,0 +1,57 @@
1
+ require 'socket'
2
+ require 'aws/xray/annotation_validator'
3
+
4
+ module Aws
5
+ module Xray
6
+ # thread-unsafe, suppose to be used only in initialization phase.
7
+ class Configuration
8
+ # @return [String] name Logical service name for this application.
9
+ attr_accessor :name
10
+
11
+ # @return [Hash] client_options For xray-agent client.
12
+ # - host: e.g. '127.0.0.1'
13
+ # - port: e.g. 2000
14
+ # - sock: test purpose.
15
+ def client_options
16
+ @client_options ||= { host: '127.0.0.1', port: 2000 }
17
+ end
18
+ attr_writer :client_options
19
+
20
+ # @return [String]
21
+ def version
22
+ @version ||= VersionDetector.new.call
23
+ end
24
+ # @param [String,Proc] version A String or callable object which returns application version.
25
+ # Default version detection tries to solve with `app_root/REVISION` file.
26
+ def version=(v)
27
+ @version = v.respond_to?(:call) ? v.call : v
28
+ end
29
+
30
+ DEFAULT_ANNOTATION = {
31
+ hostname: Socket.gethostname,
32
+ }.freeze
33
+ # @return [Hash] default annotation with key-value format.
34
+ def default_annotation
35
+ @default_annotation ||= DEFAULT_ANNOTATION
36
+ end
37
+ # @param [Hash] h default annotation Hash.
38
+ def default_annotation=(annotation)
39
+ AnnotationValidator.call(annotation)
40
+ @default_annotation = annotation
41
+ end
42
+
43
+ DEFAULT_METADATA = {
44
+ tracing_sdk: {
45
+ name: 'aws-xray',
46
+ version: Aws::Xray::VERSION,
47
+ }
48
+ }.freeze
49
+ # @return [Hash] Default metadata.
50
+ def default_metadata
51
+ @default_metadata ||= DEFAULT_METADATA
52
+ end
53
+ # @param [Hash] metadata Default metadata.
54
+ attr_writer :default_metadata
55
+ end
56
+ end
57
+ end
@@ -14,7 +14,7 @@ module Aws
14
14
  end
15
15
 
16
16
  def current
17
- Thread.current[VAR_NAME] || raise(NotSetError)
17
+ Thread.current.thread_variable_get(VAR_NAME) || raise(NotSetError)
18
18
  end
19
19
 
20
20
  def with_new_context(name, client, trace_header)
@@ -27,12 +27,11 @@ module Aws
27
27
  private
28
28
 
29
29
  def build_current(name, client, trace_header)
30
- Thread.current[VAR_NAME] = Context.new(name, client, trace_header)
30
+ Thread.current.thread_variable_set(VAR_NAME, Context.new(name, client, trace_header))
31
31
  end
32
32
 
33
- # XXX: Use delete API if exists
34
33
  def remove_current
35
- Thread.current[VAR_NAME] = nil
34
+ Thread.current.thread_variable_set(VAR_NAME, nil)
36
35
  end
37
36
  end
38
37
 
@@ -45,25 +44,35 @@ module Aws
45
44
  @base_segment = Segment.build(@name, trace_header)
46
45
  end
47
46
 
47
+ # Rescue standard errors and record the error to the segment.
48
+ # Then re-raise the error.
49
+ #
50
+ # @yield [Aws::Xray::Segment]
51
+ # @return [Object] A value which given block returns.
48
52
  def base_trace
49
- res = yield
53
+ res = yield @base_segment
50
54
  @client.send_segment(@base_segment)
51
55
  res
52
56
  rescue => e
53
- @base_segment.set_error(e)
57
+ @base_segment.set_error(fault: true, e: e)
54
58
  @client.send_segment(@base_segment)
55
59
  raise e
56
60
  end
57
61
 
62
+ # Rescue standard errors and record the error to the sub segment.
63
+ # Then re-raise the error.
64
+ #
58
65
  # @param [Boolean] remote
66
+ # @param [String] name Arbitrary name of the sub segment. e.g. "funccall_f".
59
67
  # @yield [Aws::Xray::SubSegment]
68
+ # @return [Object] A value which given block returns.
60
69
  def child_trace(remote:, name:)
61
70
  sub = SubSegment.build(@trace_header, @base_segment, remote: remote, name: name)
62
71
  res = yield sub
63
72
  @client.send_segment(sub)
64
73
  res
65
74
  rescue => e
66
- sub.set_error(e)
75
+ sub.set_error(fault: true, e: e)
67
76
  @client.send_segment(sub)
68
77
  raise e
69
78
  end
@@ -0,0 +1,60 @@
1
+ require 'aws/xray/cause'
2
+
3
+ module Aws
4
+ module Xray
5
+ class Error < Struct.new(:error, :throttle, :fault, :e, :remote, :cause)
6
+ MAX_BACKTRACE_SIZE = 10
7
+
8
+ def to_h
9
+ h = {
10
+ error: error,
11
+ throttle: throttle,
12
+ fault: fault
13
+ }
14
+ if cause
15
+ h[:cause] = cause.to_h(remote: remote)
16
+ end
17
+ # Overwrite cause because recording exception is more important.
18
+ if e
19
+ h[:cause] = build_cause_from_exception(e, remote)
20
+ end
21
+ h
22
+ end
23
+
24
+ private
25
+
26
+ # TODO: Setting cause API. Downstream API's exception?
27
+ # TODO: paths.
28
+ def build_cause_from_exception(e, remote)
29
+ truncated, stack = build_stack(e, Dir.pwd + '/')
30
+ {
31
+ working_directory: Dir.pwd,
32
+ paths: [],
33
+ exceptions: [
34
+ id: SecureRandom.hex(8),
35
+ message: e.message,
36
+ type: e.class.to_s,
37
+ remote: remote,
38
+ truncated: truncated,
39
+ skipped: 0,
40
+ cause: nil,
41
+ stack: stack,
42
+ ],
43
+ }
44
+ end
45
+
46
+ def build_stack(e, dir)
47
+ truncated = [e.backtrace.size - MAX_BACKTRACE_SIZE, 0].max
48
+ stack = e.backtrace[0..MAX_BACKTRACE_SIZE - 1].map do |b|
49
+ file, line, method_name = b.split(':')
50
+ {
51
+ path: file.sub(dir, ''),
52
+ line: line,
53
+ label: method_name,
54
+ }
55
+ end
56
+ return truncated, stack
57
+ end
58
+ end
59
+ end
60
+ end
@@ -3,22 +3,36 @@ require 'faraday'
3
3
  module Aws
4
4
  module Xray
5
5
  class Faraday < ::Faraday::Middleware
6
+ # @param [Object] app Faraday app.
7
+ # @param [String] name Logical service name for downstream API.
6
8
  def initialize(app, name = nil)
7
9
  super(app)
8
10
  @name = name
9
11
  end
10
12
 
11
- # XXX: use host header?
12
13
  def call(req_env)
13
14
  name = @name || req_env.request_headers['Host'] || "unknown-request-from-#{Context.current.name}"
14
15
 
15
16
  Context.current.child_trace(remote: true, name: name) do |sub|
16
17
  propagate_trace_header = sub.generate_trace_header
17
18
  req_env.request_headers[TRACE_HEADER] = propagate_trace_header.to_header_value
18
- sub.set_http_request(req_env)
19
+ sub.set_http_request(Request.build_from_faraday_env(req_env))
19
20
 
20
21
  @app.call(req_env).on_complete do |res_env|
21
- sub.set_http_response(res_env)
22
+ sub.set_http_response(res_env.status, res_env.response_headers['Content-Length'])
23
+ case res_env.status
24
+ when 499
25
+ cause = Cause.new(stack: caller, message: 'Got 499', type: 'http_request_error')
26
+ sub.set_error(error: true, throttle: true, cause: cause)
27
+ when 400..498
28
+ cause = Cause.new(stack: caller, message: 'Got 4xx', type: 'http_request_error')
29
+ sub.set_error(error: true, cause: cause)
30
+ when 500..599
31
+ cause = Cause.new(stack: caller, message: 'Got 5xx', type: 'http_request_error')
32
+ sub.set_error(fault: true, remote: true, cause: cause)
33
+ else
34
+ # pass
35
+ end
22
36
  end
23
37
  end
24
38
  end
data/lib/aws/xray/rack.rb CHANGED
@@ -1,18 +1,29 @@
1
1
  require 'aws/xray/trace_header'
2
2
  require 'aws/xray/client'
3
3
  require 'aws/xray/context'
4
+ require 'aws/xray/version_detector'
4
5
 
5
6
  module Aws
6
7
  module Xray
7
8
  class Rack
8
9
  TRACE_ENV = 'HTTP_X_AMZN_TRACE_ID'.freeze
9
10
 
10
- # XXX: excluded_paths, included_paths
11
- # XXX: document about client_options
12
- def initialize(app, name:, client_options: {})
11
+ class MissingNameError < ::StandardError
12
+ def initialize
13
+ super("`name` is empty. Configure this with `Aws::Xray.config.name = 'my-app'`.")
14
+ end
15
+ end
16
+
17
+ # TODO: excluded_paths, included_paths
18
+ #
19
+ # @param [Hash] client_options For xray-agent client.
20
+ # - host: e.g. '127.0.0.1'
21
+ # - port: e.g. 2000
22
+ # - sock: test purpose.
23
+ def initialize(app, client_options: {})
13
24
  @app = app
14
- @name = name
15
- @client = Client.new(client_options)
25
+ @name = Aws::Xray.config.name || raise(MissingNameError)
26
+ @client = Client.new(Aws::Xray.config.client_options.merge(client_options))
16
27
  end
17
28
 
18
29
  def call(env)
@@ -24,8 +35,10 @@ module Aws
24
35
  end
25
36
 
26
37
  Context.with_new_context(@name, @client, trace_header) do
27
- Context.current.base_trace do
38
+ Context.current.base_trace do |seg|
39
+ seg.set_http_request(Request.build_from_rack_env(env))
28
40
  status, headers, body = @app.call(env)
41
+ seg.set_http_response(status, headers['Content-Length'])
29
42
  headers[TRACE_HEADER] = trace_header.to_header_value
30
43
  [status, headers, body]
31
44
  end
@@ -0,0 +1,11 @@
1
+ require 'aws/xray'
2
+
3
+ module Aws
4
+ module Xray
5
+ class Railtie < ::Rails::Railtie
6
+ initializer 'aws-xray.rack_middleware' do |app|
7
+ app.middleware.use Aws::Xray::Rack
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ module Aws
2
+ module Xray
3
+ attrs = [:method, :url, :user_agent, :client_ip, :x_forwarded_for, :traced]
4
+ class Request < Struct.new(*attrs)
5
+ def self.build_from_rack_env(env)
6
+ new(
7
+ env['REQUEST_METHOD'], # method
8
+ env['REQUEST_URI'], # url
9
+ env['HTTP_USER_AGENT'], # user_agent
10
+ env['X-Forwarded-For'], # client_ip
11
+ !!env['X-Forwarded-For'], # x_forwarded_for
12
+ false, # traced
13
+ )
14
+ end
15
+
16
+ def self.build_from_faraday_env(env)
17
+ new(
18
+ env.method.to_s.upcase, # method
19
+ env.url.to_s, # url
20
+ env.request_headers['User-Agent'], # user_agent
21
+ nil, # client_ip
22
+ false, # x_forwarded_for
23
+ false, # traced
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,6 @@
1
+ module Aws
2
+ module Xray
3
+ class Response < Struct.new(:status, :length)
4
+ end
5
+ end
6
+ end
@@ -1,5 +1,9 @@
1
1
  require 'json'
2
2
  require 'securerandom'
3
+ require 'aws/xray/request'
4
+ require 'aws/xray/response'
5
+ require 'aws/xray/error'
6
+ require 'aws/xray/annotation_validator'
3
7
 
4
8
  module Aws
5
9
  module Xray
@@ -19,23 +23,45 @@ module Aws
19
23
  @id = SecureRandom.hex(8)
20
24
  @trace_id = trace_id
21
25
  @parent_id = parent_id
26
+ @version = Aws::Xray.config.version
22
27
  start
23
28
  @end_time = nil
24
29
  @http_request = nil
25
30
  @http_response = nil
26
31
  @error = nil
32
+ @annotation = Aws::Xray.config.default_annotation
33
+ @metadata = Aws::Xray.config.default_metadata
27
34
  end
28
35
 
29
- # @param [Hash] env A Rack env
30
- def set_http_request(env)
36
+ # @param [Aws::Xray::Request] request
37
+ def set_http_request(request)
38
+ @http_request = request
31
39
  end
32
40
 
33
- # @param [Array] res A Rack response
34
- def set_http_response(res)
41
+ # @param [Integer] status HTTP status
42
+ # @param [Integer] length Size of HTTP response body
43
+ def set_http_response(status, length)
44
+ @http_response = Response.new(status, length)
35
45
  end
36
46
 
37
- def set_error(e)
38
- # TODO: Set error object
47
+ # @param [Boolean] error Indicating that a client error occurred (response status code was 4XX Client Error).
48
+ # @param [Boolean] throttle Indicating that a request was throttled (response status code was 429 Too Many Requests).
49
+ # @param [Boolean] fault Indicating that a server error occurred (response status code was 5XX Server Error).
50
+ # @param [Exception] e An Exception object
51
+ def set_error(error: false, throttle: false, fault: false, e: nil, remote: false, cause: nil)
52
+ @error = Error.new(error, throttle, fault, e, remote, cause)
53
+ end
54
+
55
+ # @param [Hash] annotation Keys must consist of only alphabets and underscore.
56
+ # Values must be one of String or Integer or Boolean values.
57
+ def set_annotation(annotation)
58
+ AnnotationValidator.call(h)
59
+ @annotation = @annotation.merge(annotation)
60
+ end
61
+
62
+ # @param [Hash] metadata
63
+ def set_metadata(metadata)
64
+ @metadata = @metadata.merge(metadata)
39
65
  end
40
66
 
41
67
  def finish(now = Time.now)
@@ -52,12 +78,30 @@ module Aws
52
78
  id: @id,
53
79
  trace_id: @trace_id,
54
80
  start_time: @start_time,
81
+ annotation: @annotation,
82
+ metadata: @metadata,
55
83
  }
84
+ if @version
85
+ h[:service] = { version: @version }
86
+ end
87
+ if @http_request
88
+ request_hash = @http_request.to_h
89
+ # traced is SubSegment only
90
+ request_hash.delete(:traced)
91
+ h[:http] = { request: request_hash }
92
+ end
93
+ if @http_response
94
+ h[:http] ||= {}
95
+ h[:http][:response] = @http_response.to_h
96
+ end
56
97
  if @end_time.nil?
57
98
  h[:in_progress] = true
58
99
  else
59
100
  h[:end_time] = @end_time
60
101
  end
102
+ if @error
103
+ h.merge!(@error.to_h)
104
+ end
61
105
  h[:parent_id] = @parent_id if @parent_id
62
106
  h
63
107
  end
@@ -17,8 +17,21 @@ module Aws
17
17
  @remote = !!remote
18
18
  end
19
19
 
20
+ # Set traced=false if the downstream call is not traced app.
21
+ # e.g. Third-party Web API call.
22
+ # http://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html
23
+ def set_http_request(env, traced: false)
24
+ super(env)
25
+ @http_request.traced = traced
26
+ end
27
+
20
28
  def to_h
21
29
  h = super
30
+ # x_forwarded_for is Segment only.
31
+ if h[:http] && h[:http][:request]
32
+ h[:http][:request].delete(:x_forwarded_for)
33
+ h[:http][:request][:traced] = @http_request.traced
34
+ end
22
35
  h[:type] = TYPE_NAME
23
36
  h[:namespace] = 'remote' if @remote
24
37
  h
@@ -45,8 +45,7 @@ module Aws
45
45
  !!@parent
46
46
  end
47
47
 
48
- def copy(parent: nil)
49
- parent = parent.nil? ? @parent : parent
48
+ def copy(parent:)
50
49
  self.class.new(root: @root, sampled: @sampled, parent: parent)
51
50
  end
52
51
  end
@@ -1,5 +1,5 @@
1
1
  module Aws
2
2
  module Xray
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
@@ -0,0 +1,13 @@
1
+ module Aws
2
+ module Xray
3
+ class VersionDetector
4
+ REVISION_PATH = 'REVISION'
5
+
6
+ def call
7
+ if File.exist?(REVISION_PATH)
8
+ File.read(REVISION_PATH)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/aws/xray.rb CHANGED
@@ -1,9 +1,15 @@
1
1
  require 'aws/xray/version'
2
2
  require 'aws/xray/rack'
3
3
  require 'aws/xray/faraday'
4
+ require 'aws/xray/configuration'
4
5
 
5
6
  module Aws
6
7
  module Xray
7
8
  TRACE_HEADER = 'X-Amzn-Trace-Id'.freeze
9
+
10
+ @config = Configuration.new
11
+ class << self
12
+ attr_reader :config
13
+ end
8
14
  end
9
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws-xray
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taiki Ono
@@ -94,27 +94,37 @@ files:
94
94
  - LICENSE.txt
95
95
  - README.md
96
96
  - Rakefile
97
+ - TODO.md
97
98
  - aws-xray.gemspec
98
99
  - bin/console
99
100
  - bin/setup
100
101
  - example/Gemfile
101
102
  - example/Procfile
102
103
  - example/README.md
104
+ - example/REVISION
103
105
  - example/campain_app_config.ru
104
106
  - example/fron_app_config.ru
105
107
  - example/recipe_app_config.ru
106
108
  - example/user_app_config.ru
107
109
  - lib/aws-xray.rb
108
110
  - lib/aws/xray.rb
111
+ - lib/aws/xray/annotation_validator.rb
112
+ - lib/aws/xray/cause.rb
109
113
  - lib/aws/xray/client.rb
114
+ - lib/aws/xray/configuration.rb
110
115
  - lib/aws/xray/context.rb
116
+ - lib/aws/xray/error.rb
111
117
  - lib/aws/xray/faraday.rb
112
118
  - lib/aws/xray/header_parser.rb
113
119
  - lib/aws/xray/rack.rb
120
+ - lib/aws/xray/rails.rb
121
+ - lib/aws/xray/request.rb
122
+ - lib/aws/xray/response.rb
114
123
  - lib/aws/xray/segment.rb
115
124
  - lib/aws/xray/sub_segment.rb
116
125
  - lib/aws/xray/trace_header.rb
117
126
  - lib/aws/xray/version.rb
127
+ - lib/aws/xray/version_detector.rb
118
128
  homepage: https://github.com/taiki45/aws-xray
119
129
  licenses:
120
130
  - MIT