aws-xray-sdk 0.9.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 +7 -0
- data/lib/aws-xray-sdk.rb +10 -0
- data/lib/aws-xray-sdk/configuration.rb +158 -0
- data/lib/aws-xray-sdk/context/context.rb +26 -0
- data/lib/aws-xray-sdk/context/default_context.rb +81 -0
- data/lib/aws-xray-sdk/emitter/default_emitter.rb +53 -0
- data/lib/aws-xray-sdk/emitter/emitter.rb +24 -0
- data/lib/aws-xray-sdk/exceptions.rb +31 -0
- data/lib/aws-xray-sdk/facets/aws_sdk.rb +127 -0
- data/lib/aws-xray-sdk/facets/helper.rb +61 -0
- data/lib/aws-xray-sdk/facets/net_http.rb +61 -0
- data/lib/aws-xray-sdk/facets/rack.rb +87 -0
- data/lib/aws-xray-sdk/facets/rails/active_record.rb +66 -0
- data/lib/aws-xray-sdk/facets/rails/ex_middleware.rb +24 -0
- data/lib/aws-xray-sdk/facets/rails/railtie.rb +23 -0
- data/lib/aws-xray-sdk/facets/resources/aws_params_whitelist.rb +340 -0
- data/lib/aws-xray-sdk/facets/resources/aws_services_whitelist.rb +147 -0
- data/lib/aws-xray-sdk/logger.rb +19 -0
- data/lib/aws-xray-sdk/model/annotations.rb +97 -0
- data/lib/aws-xray-sdk/model/cause.rb +70 -0
- data/lib/aws-xray-sdk/model/dummy_entities.rb +72 -0
- data/lib/aws-xray-sdk/model/entity.rb +187 -0
- data/lib/aws-xray-sdk/model/metadata.rb +77 -0
- data/lib/aws-xray-sdk/model/segment.rb +63 -0
- data/lib/aws-xray-sdk/model/subsegment.rb +67 -0
- data/lib/aws-xray-sdk/model/trace_header.rb +54 -0
- data/lib/aws-xray-sdk/patcher.rb +21 -0
- data/lib/aws-xray-sdk/plugins/ec2.rb +39 -0
- data/lib/aws-xray-sdk/plugins/ecs.rb +23 -0
- data/lib/aws-xray-sdk/plugins/elastic_beanstalk.rb +25 -0
- data/lib/aws-xray-sdk/recorder.rb +209 -0
- data/lib/aws-xray-sdk/sampling/default_sampler.rb +105 -0
- data/lib/aws-xray-sdk/sampling/reservoir.rb +35 -0
- data/lib/aws-xray-sdk/sampling/sampler.rb +27 -0
- data/lib/aws-xray-sdk/sampling/sampling_rule.rb +57 -0
- data/lib/aws-xray-sdk/search_pattern.rb +82 -0
- data/lib/aws-xray-sdk/segment_naming/dynamic_naming.rb +26 -0
- data/lib/aws-xray-sdk/segment_naming/segment_naming.rb +10 -0
- data/lib/aws-xray-sdk/streaming/default_streamer.rb +53 -0
- data/lib/aws-xray-sdk/streaming/streamer.rb +17 -0
- data/lib/aws-xray-sdk/version.rb +3 -0
- metadata +224 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 78007efa0d29f0f16fa12ee0437cb6214a64c7d43d6cd1bde7ca9286d44d110b
|
4
|
+
data.tar.gz: e9fe587611d3f346b98e632ab88772769246d351b06ce46cc42f015fb15899e2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bb2ed43b514b1b50278c370c32b159f8f58bed0cd3e105b91f9ff0afb74a6ba66f184f515a294c2520cca7ad9b102506534f58fd4f3a778daeec02688900b437
|
7
|
+
data.tar.gz: 5ce0c0474f40d316dfa1ec0eddc13d156886c93b211bebd7963ae795c7b1eeca72fbc696d3a0bb948d3ad8ad106eab60d1b0774602217a794c2f92f42bac2938
|
data/lib/aws-xray-sdk.rb
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'aws-xray-sdk/exceptions'
|
2
|
+
require 'aws-xray-sdk/patcher'
|
3
|
+
require 'aws-xray-sdk/emitter/default_emitter'
|
4
|
+
require 'aws-xray-sdk/context/default_context'
|
5
|
+
require 'aws-xray-sdk/sampling/default_sampler'
|
6
|
+
require 'aws-xray-sdk/streaming/default_streamer'
|
7
|
+
require 'aws-xray-sdk/segment_naming/dynamic_naming'
|
8
|
+
require 'aws-xray-sdk/plugins/ec2'
|
9
|
+
require 'aws-xray-sdk/plugins/ecs'
|
10
|
+
require 'aws-xray-sdk/plugins/elastic_beanstalk'
|
11
|
+
require 'aws-xray-sdk/logger'
|
12
|
+
|
13
|
+
module XRay
|
14
|
+
# This class stores all configurations for X-Ray recorder
|
15
|
+
# and should be initialized only once.
|
16
|
+
class Configuration
|
17
|
+
include Patcher
|
18
|
+
|
19
|
+
SEGMENT_NAME_KEY = 'AWS_XRAY_TRACING_NAME'.freeze
|
20
|
+
CONFIG_KEY = %I[logger name sampling plugins daemon_address segment_naming
|
21
|
+
naming_pattern emitter streamer context context_missing
|
22
|
+
sampling_rules stream_threshold patch].freeze
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@name = ENV[SEGMENT_NAME_KEY]
|
26
|
+
@sampling = true
|
27
|
+
@emitter = DefaultEmitter.new
|
28
|
+
@context = DefaultContext.new
|
29
|
+
@sampler = DefaultSampler.new
|
30
|
+
@streamer = DefaultStreamer.new
|
31
|
+
@segment_naming = DynamicNaming.new fallback: @name
|
32
|
+
@plugins = []
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param [String] v The default segment name.
|
36
|
+
# Environment vairable takes higher precedence.
|
37
|
+
def name=(v)
|
38
|
+
@name = ENV[SEGMENT_NAME_KEY] || v
|
39
|
+
end
|
40
|
+
|
41
|
+
# proxy method to the emitter's daemon_address config.
|
42
|
+
def daemon_address=(v)
|
43
|
+
emitter.daemon_address = v
|
44
|
+
end
|
45
|
+
|
46
|
+
# proxy method to the context's context_missing config.
|
47
|
+
def context_missing=(v)
|
48
|
+
context.context_missing = v
|
49
|
+
end
|
50
|
+
|
51
|
+
# proxy method to the sampler's sampling rule config.
|
52
|
+
def sampling_rules=(v)
|
53
|
+
sampler.sampling_rules = v
|
54
|
+
end
|
55
|
+
|
56
|
+
# proxy method to the streamer's stream threshold config.
|
57
|
+
def stream_threshold=(v)
|
58
|
+
streamer.stream_threshold = v
|
59
|
+
end
|
60
|
+
|
61
|
+
# proxy method to the dynamic naming's pattern config.
|
62
|
+
def naming_pattern=(v)
|
63
|
+
segment_naming.pattern = v
|
64
|
+
end
|
65
|
+
|
66
|
+
# makes a sampling decision based on internal configure, e.g.
|
67
|
+
# if sampling enabled and the default sampling rule.
|
68
|
+
def sample?
|
69
|
+
return true unless sampling
|
70
|
+
sampler.sample?
|
71
|
+
end
|
72
|
+
|
73
|
+
# @param [Hash] user_config The user configuration overrides.
|
74
|
+
def configure(user_config)
|
75
|
+
raise InvalidConfigurationError.new('User config must be a Hash.') unless user_config.is_a?(Hash)
|
76
|
+
return if user_config.empty?
|
77
|
+
|
78
|
+
user_config.each_key do |key|
|
79
|
+
case key
|
80
|
+
when :logger
|
81
|
+
XRay::Logging.logger = user_config[key]
|
82
|
+
when :name
|
83
|
+
self.name = user_config[key]
|
84
|
+
when :context
|
85
|
+
self.context = user_config[key]
|
86
|
+
when :context_missing
|
87
|
+
self.context_missing = user_config[key]
|
88
|
+
when :sampler
|
89
|
+
self.sampler = user_config[key]
|
90
|
+
when :sampling_rules
|
91
|
+
self.sampling_rules = user_config[key]
|
92
|
+
when :sampling
|
93
|
+
self.sampling = user_config[key]
|
94
|
+
when :emitter
|
95
|
+
self.emitter = user_config[key]
|
96
|
+
when :daemon_address
|
97
|
+
self.daemon_address = user_config[key]
|
98
|
+
when :segment_naming
|
99
|
+
self.segment_naming = user_config[key]
|
100
|
+
when :naming_pattern
|
101
|
+
self.naming_pattern = user_config[key]
|
102
|
+
when :streamer
|
103
|
+
self.streamer = user_config[key]
|
104
|
+
when :stream_threshold
|
105
|
+
self.stream_threshold = user_config[key]
|
106
|
+
when :plugins
|
107
|
+
self.plugins = load_plugins(user_config[key])
|
108
|
+
when :patch
|
109
|
+
patch(user_config[key])
|
110
|
+
else
|
111
|
+
raise InvalidConfigurationError.new(%(Invalid config key #{key}.))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
attr_accessor :emitter
|
117
|
+
|
118
|
+
attr_accessor :context
|
119
|
+
|
120
|
+
attr_accessor :sampler
|
121
|
+
|
122
|
+
attr_accessor :streamer
|
123
|
+
|
124
|
+
attr_accessor :segment_naming
|
125
|
+
|
126
|
+
attr_accessor :plugins
|
127
|
+
|
128
|
+
attr_accessor :sampling
|
129
|
+
|
130
|
+
# @return [String] The default segment name.
|
131
|
+
attr_reader :name
|
132
|
+
|
133
|
+
# The global logger used across the X-Ray SDK.
|
134
|
+
# @return [Logger]
|
135
|
+
attr_reader :logger
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def load_plugins(symbols)
|
140
|
+
plugins = []
|
141
|
+
symbols.each do |symbol|
|
142
|
+
case symbol
|
143
|
+
when :ec2
|
144
|
+
plugins << XRay::Plugins::EC2
|
145
|
+
when :ecs
|
146
|
+
plugins << XRay::Plugins::ECS
|
147
|
+
when :elastic_beanstalk
|
148
|
+
plugins << XRay::Plugins::ElasticBeanstalk
|
149
|
+
else
|
150
|
+
raise InvalidConfigurationError.new(%(Unsupported plugin #{symbol}.))
|
151
|
+
end
|
152
|
+
end
|
153
|
+
# eager loads aws metadata to eliminate impact on first incoming request
|
154
|
+
plugins.each(&:aws)
|
155
|
+
plugins
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module XRay
|
2
|
+
# The interface of context management for the X-Ray recorder.
|
3
|
+
module Context
|
4
|
+
# @param [Entity] entity The entity to be stored in the context.
|
5
|
+
def store_entity(entity:)
|
6
|
+
raise 'Not implemented'
|
7
|
+
end
|
8
|
+
|
9
|
+
def current_entity
|
10
|
+
raise 'Not implemented'
|
11
|
+
end
|
12
|
+
|
13
|
+
def clear!
|
14
|
+
raise 'Not implemented'
|
15
|
+
end
|
16
|
+
|
17
|
+
# Put current active entity to the new context storage.
|
18
|
+
def inject_context(entity, target_ctx: nil)
|
19
|
+
raise 'Not implemented'
|
20
|
+
end
|
21
|
+
|
22
|
+
def handle_context_missing
|
23
|
+
raise 'Not implemented'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'aws-xray-sdk/logger'
|
2
|
+
require 'aws-xray-sdk/context/context'
|
3
|
+
require 'aws-xray-sdk/exceptions'
|
4
|
+
|
5
|
+
module XRay
|
6
|
+
# The default context storage management used by
|
7
|
+
# the X-Ray recorder. It uses thread local to store
|
8
|
+
# segments and subsegments.
|
9
|
+
class DefaultContext
|
10
|
+
include Context
|
11
|
+
include Logging
|
12
|
+
|
13
|
+
LOCAL_KEY = '_aws_xray_entity'.freeze
|
14
|
+
CONTEXT_MISSING_KEY = 'AWS_XRAY_CONTEXT_MISSING'.freeze
|
15
|
+
SUPPORTED_STRATEGY = %w[RUNTIME_ERROR LOG_ERROR].freeze
|
16
|
+
DEFAULT_STRATEGY = SUPPORTED_STRATEGY[0]
|
17
|
+
|
18
|
+
attr_reader :context_missing
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
strategy = ENV[CONTEXT_MISSING_KEY] || DEFAULT_STRATEGY
|
22
|
+
@context_missing = sanitize_strategy(strategy)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [Entity] entity The entity to be stored in the context.
|
26
|
+
def store_entity(entity:)
|
27
|
+
Thread.current[LOCAL_KEY] = entity
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Entity] The current active entity(could be segment or subsegment).
|
31
|
+
def current_entity
|
32
|
+
if entity = Thread.current[LOCAL_KEY]
|
33
|
+
entity
|
34
|
+
else
|
35
|
+
handle_context_missing
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Clear the current thread local storage on X-Ray related entities.
|
40
|
+
def clear!
|
41
|
+
Thread.current[LOCAL_KEY] = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [Entity] entity The entity to inject.
|
45
|
+
# @param [Thread] target_ctx Put the provided entity to the new thread.
|
46
|
+
def inject_context(entity, target_ctx: nil)
|
47
|
+
target_ctx ||= Thread.current
|
48
|
+
target_ctx[LOCAL_KEY] = entity if entity
|
49
|
+
end
|
50
|
+
|
51
|
+
# When the current entity needs to be accessed but there is none,
|
52
|
+
# it handles the missing context based on the configuration.
|
53
|
+
# On `RUNTIME_ERROR` it raises `ContextMissingError`.
|
54
|
+
# On 'LOG_ERROR' it logs an error message and return `nil`.
|
55
|
+
def handle_context_missing
|
56
|
+
case context_missing
|
57
|
+
when 'RUNTIME_ERROR'
|
58
|
+
raise ContextMissingError
|
59
|
+
when 'LOG_ERROR'
|
60
|
+
logger.error %(can not find the current context.)
|
61
|
+
end
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def context_missing=(v)
|
66
|
+
strategy = ENV[CONTEXT_MISSING_KEY] || v
|
67
|
+
@context_missing = sanitize_strategy(strategy)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def sanitize_strategy(v)
|
73
|
+
if SUPPORTED_STRATEGY.include?(v)
|
74
|
+
v
|
75
|
+
else
|
76
|
+
logger.warn %(context missing #{v} is not supported, switch to default #{DEFAULT_STRATEGY}.)
|
77
|
+
DEFAULT_STRATEGY
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'aws-xray-sdk/logger'
|
3
|
+
require 'aws-xray-sdk/emitter/emitter'
|
4
|
+
require 'aws-xray-sdk/exceptions'
|
5
|
+
|
6
|
+
module XRay
|
7
|
+
# The default emitter the X-Ray recorder uses to send segments/subsegments
|
8
|
+
# to the X-Ray daemon over UDP using a non-blocking socket.
|
9
|
+
class DefaultEmitter
|
10
|
+
include Emitter
|
11
|
+
include Logging
|
12
|
+
|
13
|
+
attr_reader :address
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@socket = UDPSocket.new
|
17
|
+
@address = ENV[DAEMON_ADDRESS_KEY] || '127.0.0.1:2000'
|
18
|
+
configure_socket(@address)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Serializes a segment/subsegment and sends it to the X-Ray daemon
|
22
|
+
# over UDP. It is no-op for non-sampled entity.
|
23
|
+
# @param [Entity] entity The entity to send
|
24
|
+
def send_entity(entity:)
|
25
|
+
return nil unless entity.sampled
|
26
|
+
begin
|
27
|
+
payload = %(#{@@protocol_header}#{@@protocol_delimiter}#{entity.to_json})
|
28
|
+
logger.debug %(sending payload #{payload} to daemon at #{address}.)
|
29
|
+
@socket.send payload, 0
|
30
|
+
rescue StandardError => e
|
31
|
+
logger.warn %(failed to send payload due to #{e.message})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def daemon_address=(v)
|
36
|
+
v = ENV[DAEMON_ADDRESS_KEY] || v
|
37
|
+
@address = v
|
38
|
+
configure_socket(v)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def configure_socket(v)
|
44
|
+
begin
|
45
|
+
addr = v.split(':')
|
46
|
+
host, ip = addr[0], addr[1].to_i
|
47
|
+
@socket.connect(host, ip)
|
48
|
+
rescue StandardError
|
49
|
+
raise InvalidDaemonAddressError, %(Invalid X-Ray daemon address specified: #{v}.)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# The emitter interface the X-Ray recorder uses to send segments/subsegments
|
5
|
+
# to the X-Ray daemon over UDP.
|
6
|
+
module Emitter
|
7
|
+
DAEMON_ADDRESS_KEY = 'AWS_XRAY_DAEMON_ADDRESS'.freeze
|
8
|
+
|
9
|
+
@@protocol_header = {
|
10
|
+
format: 'json',
|
11
|
+
version: 1
|
12
|
+
}.to_json
|
13
|
+
@@protocol_delimiter = "\n"
|
14
|
+
|
15
|
+
# @param [Entity] entity Entity to send.
|
16
|
+
def send_entity(entity:)
|
17
|
+
raise 'Not implemented'
|
18
|
+
end
|
19
|
+
|
20
|
+
def daemon_address=(v)
|
21
|
+
raise 'Not implemented'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module XRay
|
2
|
+
# All custom exception thrown by the SDK should subclass AwsXRayError.
|
3
|
+
class AwsXRaySdkError < ::StandardError; end
|
4
|
+
|
5
|
+
class EntityClosedError < AwsXRaySdkError
|
6
|
+
def initialize
|
7
|
+
super('Segment or subsegment already ended.')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class ContextMissingError < AwsXRaySdkError
|
12
|
+
def initialize
|
13
|
+
super('Can not find any active segment or subsegment.')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class SegmentNameMissingError < AwsXRaySdkError
|
18
|
+
end
|
19
|
+
|
20
|
+
class InvalidDaemonAddressError < AwsXRaySdkError
|
21
|
+
end
|
22
|
+
|
23
|
+
class InvalidSamplingConfigError < AwsXRaySdkError
|
24
|
+
end
|
25
|
+
|
26
|
+
class InvalidConfigurationError < AwsXRaySdkError
|
27
|
+
end
|
28
|
+
|
29
|
+
class UnsupportedPatchingTargetError < AwsXRaySdkError
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'aws-sdk-core'
|
2
|
+
require 'aws-xray-sdk/facets/helper'
|
3
|
+
require 'aws-xray-sdk/facets/resources/aws_params_whitelist'
|
4
|
+
require 'aws-xray-sdk/facets/resources/aws_services_whitelist'
|
5
|
+
|
6
|
+
module XRay
|
7
|
+
class AwsSDKPlugin < Seahorse::Client::Plugin
|
8
|
+
option :xray_recorder, default: XRay.recorder
|
9
|
+
|
10
|
+
def add_handlers(handlers, config)
|
11
|
+
# run before Seahorse::Client::Plugin::ParamValidator (priority 50)
|
12
|
+
handlers.add Handler, step: :validate, priority: 49
|
13
|
+
end
|
14
|
+
|
15
|
+
# Handler to capture AWS API calls as subsegments
|
16
|
+
class Handler < Seahorse::Client::Handler
|
17
|
+
include XRay::Facets::Helper
|
18
|
+
|
19
|
+
def call(context)
|
20
|
+
recorder = Aws.config[:xray_recorder]
|
21
|
+
operation = context.operation_name
|
22
|
+
service_name = context.client.class.api.metadata['serviceAbbreviation'] ||
|
23
|
+
context.client.class.to_s.split('::')[1]
|
24
|
+
recorder.capture service_name, namespace: 'aws' do |subsegment|
|
25
|
+
# inject header string before calling downstream AWS services
|
26
|
+
context.http_request.headers[TRACE_HEADER] = prep_header_str entity: subsegment
|
27
|
+
response = @handler.call(context)
|
28
|
+
http_response = context.http_response
|
29
|
+
resp_meta = {
|
30
|
+
status: http_response.status_code,
|
31
|
+
content_length: http_response.headers['content-length'].to_i
|
32
|
+
}
|
33
|
+
aws = {
|
34
|
+
# XRay back-end right now has strict operation name matching
|
35
|
+
operation: sanitize_op_name(operation),
|
36
|
+
region: context.client.config.region,
|
37
|
+
retries: context.retries,
|
38
|
+
request_id: http_response.headers['x-amzn-requestid']
|
39
|
+
}
|
40
|
+
# S3 returns special request id in response headers
|
41
|
+
if service_name == 'S3'
|
42
|
+
aws[:id_2] = http_response.headers['x-amz-id-2']
|
43
|
+
end
|
44
|
+
|
45
|
+
operation_h = AwsParams.whitelist[:services]
|
46
|
+
.fetch(service_name.to_sym, {})
|
47
|
+
.fetch(:operations, {})[operation]
|
48
|
+
unless operation_h.nil?
|
49
|
+
params_capture req_params: context.params, resp_params: response.to_h,
|
50
|
+
capture: operation_h, meta: aws
|
51
|
+
end
|
52
|
+
subsegment.aws = aws
|
53
|
+
if err = response.error
|
54
|
+
subsegment.add_exception exception: err, remote: true
|
55
|
+
end
|
56
|
+
subsegment.merge_http_response response: resp_meta
|
57
|
+
response
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def inject_headers(request:, entity:)
|
64
|
+
request.headers[TRACE_HEADER] = prep_header_str entity: entity
|
65
|
+
end
|
66
|
+
|
67
|
+
def sanitize_op_name(opname)
|
68
|
+
opname.to_s.split('_').collect(&:capitalize).join if opname
|
69
|
+
end
|
70
|
+
|
71
|
+
def params_capture(req_params:, resp_params:, capture:, meta:)
|
72
|
+
if norm = capture[:request_parameters]
|
73
|
+
capture_normal params: req_params, capture: norm, meta: meta
|
74
|
+
end
|
75
|
+
|
76
|
+
if norm = capture[:response_parameters]
|
77
|
+
capture_normal params: resp_params, capture: norm, meta: meta
|
78
|
+
end
|
79
|
+
|
80
|
+
if spec = capture[:request_descriptors]
|
81
|
+
capture_special params: req_params, capture: spec, meta: meta
|
82
|
+
end
|
83
|
+
|
84
|
+
if spec = capture[:response_descriptors]
|
85
|
+
capture_special params: resp_params, capture: spec, meta: meta
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def capture_normal(params:, capture:, meta:)
|
90
|
+
params.each_key do |key|
|
91
|
+
meta[key] = params[key] if capture.include?(key)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def capture_special(params:, capture:, meta:)
|
96
|
+
params.each_key do |key|
|
97
|
+
process_descriptor(target: params[key], descriptor: capture[key], meta: meta) if capture.include?(key)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def process_descriptor(target:, descriptor:, meta:)
|
102
|
+
# "get_count" = true
|
103
|
+
v = target.length if descriptor[:get_count]
|
104
|
+
# "get_keys" = true
|
105
|
+
v = target.keys if descriptor[:get_keys]
|
106
|
+
meta[descriptor[:rename_to]] = v
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Add X-Ray plugin to AWS SDK clients
|
112
|
+
module AwsSDKPatcher
|
113
|
+
def self.patch(services: nil, recorder: XRay.recorder)
|
114
|
+
force = services.nil?
|
115
|
+
services ||= AwsServices.whitelist
|
116
|
+
services.each do |s|
|
117
|
+
begin
|
118
|
+
Aws.const_get(%(#{s}::Client)).add_plugin XRay::AwsSDKPlugin
|
119
|
+
Aws.config.update xray_recorder: recorder
|
120
|
+
rescue NameError
|
121
|
+
# swallow the error if no explicit user config
|
122
|
+
raise unless force
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|