aws-xray 0.19.0 → 0.20.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 +4 -4
- data/lib/aws/xray.rb +1 -2
- data/lib/aws/xray/client.rb +37 -44
- data/lib/aws/xray/configuration.rb +45 -53
- data/lib/aws/xray/context.rb +18 -21
- data/lib/aws/xray/rack.rb +2 -7
- data/lib/aws/xray/segment.rb +1 -1
- data/lib/aws/xray/{sub_segment.rb → subsegment.rb} +1 -1
- data/lib/aws/xray/version.rb +1 -1
- data/lib/aws/xray/worker.rb +5 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7791521140cd959a8955511da8c84bc1adcbc3a4
|
4
|
+
data.tar.gz: dad29f16af29cc23eb0f5e156d7a58e8a4fd8154
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7b21c857fc027e6aa601cf7de7179771e04d8e5d412feda876ebffec9a38c97f4082381272b7ed77795554f512adf1ef9eb1338345662d088631e8d28c0f5aa
|
7
|
+
data.tar.gz: 75b452f39bd6d993b86d2bb3c25b26a3ae7e6bf1590dcfe58d5a2b2b825a8b0eb02099f7d50c4892bd2fdc4c111cb24e2f9b7d2e11a63491a3092036fb60be39
|
data/lib/aws/xray.rb
CHANGED
@@ -26,8 +26,7 @@ module Aws
|
|
26
26
|
# @param [String] name a logical name of this tracing context.
|
27
27
|
def self.trace(name: nil)
|
28
28
|
name = name || config.name || raise(MissingNameError)
|
29
|
-
|
30
|
-
Context.with_new_context(name, client, Trace.generate) do
|
29
|
+
Context.with_new_context(name, Trace.generate) do
|
31
30
|
Context.current.base_trace do |seg|
|
32
31
|
yield seg
|
33
32
|
end
|
data/lib/aws/xray/client.rb
CHANGED
@@ -5,58 +5,51 @@ module Aws
|
|
5
5
|
# Own the responsibility of holding destination address and sending
|
6
6
|
# segments.
|
7
7
|
class Client
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def copy
|
15
|
-
self.class.new(host: @host ? @host.dup : nil, port: @port, sock: @sock)
|
16
|
-
end
|
8
|
+
class << self
|
9
|
+
# @param [Aws::Xray::Segment] segment
|
10
|
+
def send_segment(segment)
|
11
|
+
Aws::Xray.config.logger.debug("#{Thread.current}: Client.send_segment started")
|
12
|
+
payload = %!{"format": "json", "version": 1}\n#{segment.to_json}\n!
|
17
13
|
|
18
|
-
# When UDPSocket#send can not send all bytes, just give up it.
|
19
|
-
# @param [Aws::Xray::Segment] segment
|
20
|
-
def send_segment(segment)
|
21
|
-
Aws::Xray.config.logger.debug("#{Thread.current}: Client#send_segment started")
|
22
|
-
payload = %!{"format": "json", "version": 1}\n#{segment.to_json}\n!
|
23
|
-
|
24
|
-
begin
|
25
|
-
if @sock # test env or not aws-xray is not enabled
|
26
|
-
send_payload(payload)
|
27
|
-
Aws::Xray.config.logger.debug("#{Thread.current}: Client#send_segment called #send_payload in the same thread")
|
28
|
-
else # production env
|
29
|
-
Worker.post(payload, self.copy)
|
30
|
-
Aws::Xray.config.logger.debug("#{Thread.current}: Client#send_segment posted a job to worker")
|
31
|
-
end
|
32
|
-
rescue QueueIsFullError => e
|
33
14
|
begin
|
34
|
-
Aws::Xray.config.
|
35
|
-
|
36
|
-
|
15
|
+
if Aws::Xray.config.client_options[:sock] # test env or not aws-xray is not enabled
|
16
|
+
send_payload(payload)
|
17
|
+
Aws::Xray.config.logger.debug("#{Thread.current}: Client.send_segment called #send_payload in the same thread")
|
18
|
+
else # production env
|
19
|
+
Worker.post(payload)
|
20
|
+
Aws::Xray.config.logger.debug("#{Thread.current}: Client.send_segment posted a job to worker")
|
21
|
+
end
|
22
|
+
rescue QueueIsFullError => e
|
23
|
+
begin
|
24
|
+
host, port = Aws::Xray.config.client_options[:host], Aws::Xray.config.client_options[:port]
|
25
|
+
Aws::Xray.config.segment_sending_error_handler.call(e, payload, host: host, port: port)
|
26
|
+
rescue Exception => e
|
27
|
+
$stderr.puts("Error handler `#{Aws::Xray.config.segment_sending_error_handler}` raised an error: #{e}\n#{e.backtrace.join("\n")}")
|
28
|
+
end
|
37
29
|
end
|
38
30
|
end
|
39
|
-
end
|
40
31
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
32
|
+
# Will be called in other threads.
|
33
|
+
# @param [String] payload
|
34
|
+
def send_payload(payload)
|
35
|
+
Aws::Xray.config.logger.debug("#{Thread.current}: Client#send_payload")
|
36
|
+
sock = Aws::Xray.config.client_options[:sock] || UDPSocket.new
|
37
|
+
host, port = Aws::Xray.config.client_options[:host], Aws::Xray.config.client_options[:port]
|
46
38
|
|
47
|
-
begin
|
48
|
-
len = sock.send(payload, Socket::MSG_DONTWAIT, @host, @port)
|
49
|
-
raise CanNotSendAllByteError.new(payload.size, len) if payload.size != len
|
50
|
-
Aws::Xray.config.logger.debug("#{Thread.current}: Client#send_payload successfully sent payload, len=#{len}")
|
51
|
-
len
|
52
|
-
rescue SystemCallError, SocketError, CanNotSendAllByteError => e
|
53
39
|
begin
|
54
|
-
|
55
|
-
|
56
|
-
|
40
|
+
len = sock.send(payload, Socket::MSG_DONTWAIT, host, port)
|
41
|
+
raise CanNotSendAllByteError.new(payload.size, len) if payload.size != len
|
42
|
+
Aws::Xray.config.logger.debug("#{Thread.current}: Client#send_payload successfully sent payload, len=#{len}")
|
43
|
+
len
|
44
|
+
rescue SystemCallError, SocketError, CanNotSendAllByteError => e
|
45
|
+
begin
|
46
|
+
Aws::Xray.config.segment_sending_error_handler.call(e, payload, host: host, port: port)
|
47
|
+
rescue Exception => e
|
48
|
+
$stderr.puts("Error handler `#{Aws::Xray.config.segment_sending_error_handler}` raised an error: #{e}\n#{e.backtrace.join("\n")}")
|
49
|
+
end
|
50
|
+
ensure
|
51
|
+
sock.close
|
57
52
|
end
|
58
|
-
ensure
|
59
|
-
sock.close
|
60
53
|
end
|
61
54
|
end
|
62
55
|
end
|
@@ -7,21 +7,22 @@ module Aws
|
|
7
7
|
module Xray
|
8
8
|
# thread-unsafe, suppose to be used only in initialization phase.
|
9
9
|
class Configuration
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
# Freeze to force users to set default annotation with writer method.
|
11
|
+
DEFAULT_ANNOTATION = {
|
12
|
+
hostname: Socket.gethostname,
|
13
|
+
}.freeze
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
DEFAULT_METADATA = {
|
16
|
+
tracing_sdk: {
|
17
|
+
name: 'aws-xray',
|
18
|
+
version: Aws::Xray::VERSION,
|
19
|
+
}
|
20
|
+
}.freeze
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@client_options ||=
|
22
|
+
def initialize
|
23
|
+
@logger = ::Logger.new($stdout).tap {|l| l.level = Logger::INFO }
|
24
|
+
@name = ENV['AWS_XRAY_NAME']
|
25
|
+
@client_options =
|
25
26
|
begin
|
26
27
|
option = (ENV['AWS_XRAY_LOCATION'] || '').split(':')
|
27
28
|
host = option[0]
|
@@ -32,60 +33,54 @@ module Aws
|
|
32
33
|
{ sock: NullSocket.new }
|
33
34
|
end
|
34
35
|
end
|
36
|
+
@excluded_paths = (ENV['AWS_XRAY_EXCLUDED_PATHS'] || '').split(',')
|
37
|
+
@version = VersionDetector.new.call
|
38
|
+
@default_annotation = DEFAULT_ANNOTATION
|
39
|
+
@default_metadata = DEFAULT_METADATA
|
40
|
+
@segment_sending_error_handler = DefaultErrorHandler.new($stderr)
|
41
|
+
@worker = Aws::Xray::Worker::Configuration.new
|
42
|
+
@sampling_rate = Float(ENV['AWS_XRAY_SAMPLING_RATE'] || 0.001)
|
35
43
|
end
|
36
|
-
attr_writer :client_options
|
37
44
|
|
45
|
+
# @param [String] name Logical service name for this application.
|
46
|
+
# @return [String]
|
47
|
+
attr_accessor :name
|
48
|
+
|
49
|
+
# @param [Hash] client_options For xray-agent client.
|
50
|
+
# - host: e.g. '127.0.0.1'
|
51
|
+
# - port: e.g. 2000
|
52
|
+
# @return [Hash]
|
53
|
+
attr_accessor :client_options
|
54
|
+
|
55
|
+
# @param [Array<String>] excluded_paths
|
38
56
|
# @return [Array<String>]
|
39
|
-
|
40
|
-
@excluded_paths ||= (ENV['AWS_XRAY_EXCLUDED_PATHS'] || '').split(',')
|
41
|
-
end
|
42
|
-
attr_writer :excluded_paths
|
57
|
+
attr_accessor :excluded_paths
|
43
58
|
|
44
59
|
# @return [String]
|
45
|
-
|
46
|
-
@version ||= VersionDetector.new.call
|
47
|
-
end
|
60
|
+
attr_reader :version
|
48
61
|
# @param [String,Proc] version A String or callable object which returns application version.
|
49
62
|
# Default version detection tries to solve with `app_root/REVISION` file.
|
50
63
|
def version=(v)
|
51
64
|
@version = v.respond_to?(:call) ? v.call : v
|
52
65
|
end
|
53
66
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
#
|
58
|
-
def default_annotation
|
59
|
-
@default_annotation ||= DEFAULT_ANNOTATION
|
60
|
-
end
|
61
|
-
# @param [Hash] h default annotation Hash.
|
67
|
+
# @return [Hash]
|
68
|
+
attr_reader :default_annotation
|
69
|
+
# @param [Hash] annotation annotation with key-value format. keys and
|
70
|
+
# values are automatically normalized according to X-Ray's format spec.
|
62
71
|
def default_annotation=(annotation)
|
63
72
|
@default_annotation = AnnotationNormalizer.call(annotation)
|
64
73
|
end
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
version: Aws::Xray::VERSION,
|
70
|
-
}
|
71
|
-
}.freeze
|
72
|
-
# @return [Hash] Default metadata.
|
73
|
-
def default_metadata
|
74
|
-
@default_metadata ||= DEFAULT_METADATA
|
75
|
-
end
|
76
|
-
# @param [Hash] metadata Default metadata.
|
77
|
-
attr_writer :default_metadata
|
75
|
+
# @param [Hash] default_metadatametadata Default metadata.
|
76
|
+
# @return [Hash]
|
77
|
+
attr_accessor :default_metadata
|
78
78
|
|
79
|
-
def segment_sending_error_handler
|
80
|
-
@segment_sending_error_handler ||= DefaultErrorHandler.new($stderr)
|
81
|
-
end
|
82
79
|
# @param [Proc] segment_sending_error_handler Callable object
|
83
|
-
|
80
|
+
attr_accessor :segment_sending_error_handler
|
84
81
|
|
85
82
|
# @return [Aws::Xray::Worker::Configuration]
|
86
|
-
|
87
|
-
@worker ||= Aws::Xray::Worker::Configuration.new
|
88
|
-
end
|
83
|
+
attr_reader :worker
|
89
84
|
# Set given configuration and reset workers according to the given
|
90
85
|
# configuration.
|
91
86
|
# @param [Aws::Xray::Worker::Configuration] conf
|
@@ -96,12 +91,9 @@ module Aws
|
|
96
91
|
end
|
97
92
|
|
98
93
|
# Default is 0.1%.
|
99
|
-
# @return [Float]
|
100
|
-
def sampling_rate
|
101
|
-
@sampling_rate ||= Float(ENV['AWS_XRAY_SAMPLING_RATE'] || 0.001)
|
102
|
-
end
|
103
94
|
# @param [Float] sampling_rate
|
104
|
-
|
95
|
+
# @return [Float]
|
96
|
+
attr_accessor :sampling_rate
|
105
97
|
|
106
98
|
# @param [Logger] logger
|
107
99
|
# @return [Logger]
|
data/lib/aws/xray/context.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'aws/xray/segment'
|
2
|
-
require 'aws/xray/
|
2
|
+
require 'aws/xray/subsegment'
|
3
3
|
|
4
4
|
module Aws
|
5
5
|
module Xray
|
@@ -26,12 +26,11 @@ module Aws
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# @param [String] name logical name of this tracing context.
|
29
|
-
# @param [Aws::Xray::Client] client
|
30
29
|
# @param [Aws::Xray::Trace] trace newly generated trace or created with
|
31
30
|
# HTTP request header.
|
32
31
|
# @yield [Aws::Xray::Context] newly created context.
|
33
|
-
def with_new_context(name,
|
34
|
-
build_current(name,
|
32
|
+
def with_new_context(name, trace)
|
33
|
+
build_current(name, trace)
|
35
34
|
yield
|
36
35
|
ensure
|
37
36
|
remove_current
|
@@ -39,8 +38,8 @@ module Aws
|
|
39
38
|
|
40
39
|
private
|
41
40
|
|
42
|
-
def build_current(name,
|
43
|
-
Thread.current.thread_variable_set(VAR_NAME, Context.new(name,
|
41
|
+
def build_current(name, trace)
|
42
|
+
Thread.current.thread_variable_set(VAR_NAME, Context.new(name, trace))
|
44
43
|
end
|
45
44
|
|
46
45
|
def remove_current
|
@@ -50,26 +49,24 @@ module Aws
|
|
50
49
|
|
51
50
|
attr_reader :name
|
52
51
|
|
53
|
-
|
54
|
-
def initialize(name, client, trace, base_segment_id = nil)
|
52
|
+
def initialize(name, trace, base_segment_id = nil)
|
55
53
|
raise 'name is required' unless name
|
56
54
|
@name = name
|
57
|
-
@client = client
|
58
55
|
@trace = trace
|
59
56
|
@base_segment_id = base_segment_id
|
60
57
|
@disabled_ids = []
|
61
|
-
@
|
58
|
+
@subsegment_name = nil
|
62
59
|
end
|
63
60
|
|
64
61
|
# Curretly context object is thread safe, so copying is not necessary,
|
65
62
|
# but in case we need this, offer copy interface for multi threaded
|
66
63
|
# environment.
|
67
64
|
#
|
68
|
-
#
|
65
|
+
# Trace should be imutable and thread-safe.
|
69
66
|
#
|
70
67
|
# See README for example.
|
71
68
|
def copy
|
72
|
-
self.class.new(@name.dup, @
|
69
|
+
self.class.new(@name.dup, @trace.copy, @base_segment_id ? @base_segment_id.dup : nil)
|
73
70
|
end
|
74
71
|
|
75
72
|
# Rescue all exceptions and record the exception to the segment.
|
@@ -88,17 +85,17 @@ module Aws
|
|
88
85
|
raise e
|
89
86
|
ensure
|
90
87
|
base_segment.finish
|
91
|
-
|
88
|
+
Client.send_segment(base_segment) if @trace.sampled?
|
92
89
|
end
|
93
90
|
end
|
94
91
|
|
95
92
|
# @param [Boolean] remote
|
96
93
|
# @param [String] name Arbitrary name of the sub segment. e.g. "funccall_f".
|
97
|
-
# @yield [Aws::Xray::
|
94
|
+
# @yield [Aws::Xray::Subsegment]
|
98
95
|
# @return [Object] A value which given block returns.
|
99
96
|
def child_trace(remote:, name:)
|
100
97
|
raise SegmentDidNotStartError unless @base_segment_id
|
101
|
-
sub =
|
98
|
+
sub = Subsegment.build(@trace, @base_segment_id, remote: remote, name: overwrite_name(name))
|
102
99
|
|
103
100
|
begin
|
104
101
|
yield sub
|
@@ -107,7 +104,7 @@ module Aws
|
|
107
104
|
raise e
|
108
105
|
ensure
|
109
106
|
sub.finish
|
110
|
-
|
107
|
+
Client.send_segment(sub) if @trace.sampled?
|
111
108
|
end
|
112
109
|
end
|
113
110
|
|
@@ -135,22 +132,22 @@ module Aws
|
|
135
132
|
#
|
136
133
|
# @param [String] name
|
137
134
|
def overwrite(name:)
|
138
|
-
@
|
135
|
+
@subsegment_name = name.to_s
|
139
136
|
|
140
137
|
begin
|
141
138
|
yield
|
142
139
|
ensure
|
143
|
-
@
|
140
|
+
@subsegment_name = nil
|
144
141
|
end
|
145
142
|
end
|
146
143
|
|
147
144
|
private
|
148
145
|
|
149
146
|
def overwrite_name(name)
|
150
|
-
return name unless @
|
147
|
+
return name unless @subsegment_name
|
151
148
|
|
152
|
-
name = @
|
153
|
-
@
|
149
|
+
name = @subsegment_name
|
150
|
+
@subsegment_name = nil
|
154
151
|
name
|
155
152
|
end
|
156
153
|
end
|
data/lib/aws/xray/rack.rb
CHANGED
@@ -4,15 +4,10 @@ module Aws
|
|
4
4
|
TRACE_ENV = 'HTTP_X_AMZN_TRACE_ID'.freeze
|
5
5
|
ORIGINAL_TRACE_ENV = 'HTTP_X_AMZN_TRACE_ID_ORIGINAL'.freeze
|
6
6
|
|
7
|
-
# @param [Hash] client_options For xray-agent client.
|
8
|
-
# - host: e.g. '127.0.0.1'
|
9
|
-
# - port: e.g. 2000
|
10
|
-
# - sock: test purpose.
|
11
7
|
# @param [Array<String,Regexp>] excluded_paths for health-check endpoints etc...
|
12
|
-
def initialize(app,
|
8
|
+
def initialize(app, excluded_paths: [])
|
13
9
|
@app = app
|
14
10
|
@name = Aws::Xray.config.name || raise(MissingNameError)
|
15
|
-
@client = Client.new(Aws::Xray.config.client_options.merge(client_options))
|
16
11
|
@excluded_paths = excluded_paths + Aws::Xray.config.excluded_paths
|
17
12
|
end
|
18
13
|
|
@@ -31,7 +26,7 @@ module Aws
|
|
31
26
|
env[ORIGINAL_TRACE_ENV] = env[TRACE_ENV] if env[TRACE_ENV] # just for the record
|
32
27
|
env[TRACE_ENV] = trace.to_header_value
|
33
28
|
|
34
|
-
Context.with_new_context(@name,
|
29
|
+
Context.with_new_context(@name, trace) do
|
35
30
|
Context.current.base_trace do |seg|
|
36
31
|
seg.set_http_request(Request.build_from_rack_env(env))
|
37
32
|
status, headers, body = @app.call(env)
|
data/lib/aws/xray/segment.rb
CHANGED
@@ -3,7 +3,7 @@ require 'aws/xray/segment'
|
|
3
3
|
module Aws
|
4
4
|
module Xray
|
5
5
|
# http://docs.aws.amazon.com/xray/latest/devguide/xray-api-segmentdocuments.html
|
6
|
-
class
|
6
|
+
class Subsegment < Segment
|
7
7
|
# @param [Boolean] remote
|
8
8
|
def self.build(trace, parent_id, remote:, name:)
|
9
9
|
new(name: name, trace: trace, parent_id: parent_id, remote: remote)
|
data/lib/aws/xray/version.rb
CHANGED
data/lib/aws/xray/worker.rb
CHANGED
@@ -10,19 +10,16 @@ module Aws
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
class Item < Struct.new(:payload, :client)
|
14
|
-
end
|
15
|
-
|
16
13
|
@post_lock = ::Mutex.new
|
17
14
|
@pid = $$
|
18
15
|
class << self
|
19
16
|
# @param [String] payload to send
|
20
17
|
# @param [Aws::Xray::Client] client
|
21
|
-
def post(payload
|
18
|
+
def post(payload)
|
22
19
|
Aws::Xray.config.logger.debug("#{Thread.current}: Worker.post received a job")
|
23
20
|
@post_lock.synchronize do
|
24
21
|
refresh_if_forked
|
25
|
-
@queue.push(
|
22
|
+
@queue.push(payload)
|
26
23
|
end
|
27
24
|
Aws::Xray.config.logger.debug("#{Thread.current}: Worker.post pushed a job")
|
28
25
|
rescue ThreadError => e
|
@@ -54,10 +51,10 @@ module Aws
|
|
54
51
|
th = Thread.new(@queue) do |queue|
|
55
52
|
loop do
|
56
53
|
Aws::Xray.config.logger.debug("#{Thread.current}: Worker#run waits a job")
|
57
|
-
|
54
|
+
payload = queue.pop
|
58
55
|
Aws::Xray.config.logger.debug("#{Thread.current}: Worker#run received a job")
|
59
|
-
if
|
60
|
-
|
56
|
+
if payload
|
57
|
+
Client.send_payload(payload.to_s)
|
61
58
|
Aws::Xray.config.logger.debug("#{Thread.current}: Worker#run sent a payload")
|
62
59
|
else
|
63
60
|
Aws::Xray.config.logger.debug("#{Thread.current}: Worker#run received invalid item, ignored it")
|
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.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taiki Ono
|
@@ -196,7 +196,7 @@ files:
|
|
196
196
|
- lib/aws/xray/response.rb
|
197
197
|
- lib/aws/xray/segment.rb
|
198
198
|
- lib/aws/xray/sockets.rb
|
199
|
-
- lib/aws/xray/
|
199
|
+
- lib/aws/xray/subsegment.rb
|
200
200
|
- lib/aws/xray/trace.rb
|
201
201
|
- lib/aws/xray/version.rb
|
202
202
|
- lib/aws/xray/version_detector.rb
|