aws-xray-sdk 0.10.2 → 0.11.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-sdk/configuration.rb +10 -7
- data/lib/aws-xray-sdk/daemon_config.rb +59 -0
- data/lib/aws-xray-sdk/emitter/default_emitter.rb +10 -21
- data/lib/aws-xray-sdk/emitter/emitter.rb +1 -3
- data/lib/aws-xray-sdk/facets/aws_sdk.rb +14 -6
- data/lib/aws-xray-sdk/facets/helper.rb +4 -11
- data/lib/aws-xray-sdk/facets/net_http.rb +4 -0
- data/lib/aws-xray-sdk/facets/rack.rb +8 -6
- data/lib/aws-xray-sdk/facets/rails/railtie.rb +1 -1
- data/lib/aws-xray-sdk/model/cause.rb +2 -2
- data/lib/aws-xray-sdk/model/dummy_entities.rb +4 -0
- data/lib/aws-xray-sdk/model/entity.rb +2 -2
- data/lib/aws-xray-sdk/model/metadata.rb +2 -2
- data/lib/aws-xray-sdk/model/segment.rb +8 -1
- data/lib/aws-xray-sdk/plugins/elastic_beanstalk.rb +2 -2
- data/lib/aws-xray-sdk/recorder.rb +7 -4
- data/lib/aws-xray-sdk/sampling/connector.rb +72 -0
- data/lib/aws-xray-sdk/sampling/default_sampler.rb +72 -78
- data/lib/aws-xray-sdk/sampling/lead_poller.rb +72 -0
- data/lib/aws-xray-sdk/sampling/local/reservoir.rb +35 -0
- data/lib/aws-xray-sdk/sampling/local/sampler.rb +110 -0
- data/lib/aws-xray-sdk/sampling/local/sampling_rule.rb +63 -0
- data/lib/aws-xray-sdk/sampling/reservoir.rb +68 -24
- data/lib/aws-xray-sdk/sampling/rule_cache.rb +86 -0
- data/lib/aws-xray-sdk/sampling/rule_poller.rb +39 -0
- data/lib/aws-xray-sdk/sampling/sampler.rb +3 -3
- data/lib/aws-xray-sdk/sampling/sampling_decision.rb +8 -0
- data/lib/aws-xray-sdk/sampling/sampling_rule.rb +102 -35
- data/lib/aws-xray-sdk/version.rb +1 -1
- metadata +34 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91c311c0f94185bc3f4a17afbfde8f7a4f881503feeb7eb116a43631c6649efc
|
4
|
+
data.tar.gz: 4a2791948dc071dfa2e57f410eb60311ff812aa276f0968dfc85db28632a2565
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c9caa633a61621f6c17a281c416855aef63033f8c8119589c0c1bff70218c80f7b84234251f97be5a7cf5b3d39a1d0dc8c54fb8c619ec46c9ab37aabb323bf8
|
7
|
+
data.tar.gz: 42cce4783e4dfa257317a1c3b6bca7fd52e2b4b1521b313048b1c8e1037a9bb85596e2b70a15fca54b15777fc941b380114bf5deec452062a1ea5bc73ac4b4ef
|
@@ -2,6 +2,7 @@ require 'aws-xray-sdk/exceptions'
|
|
2
2
|
require 'aws-xray-sdk/patcher'
|
3
3
|
require 'aws-xray-sdk/emitter/default_emitter'
|
4
4
|
require 'aws-xray-sdk/context/default_context'
|
5
|
+
require 'aws-xray-sdk/daemon_config'
|
5
6
|
require 'aws-xray-sdk/sampling/default_sampler'
|
6
7
|
require 'aws-xray-sdk/streaming/default_streamer'
|
7
8
|
require 'aws-xray-sdk/segment_naming/dynamic_naming'
|
@@ -17,9 +18,9 @@ module XRay
|
|
17
18
|
include Patcher
|
18
19
|
|
19
20
|
SEGMENT_NAME_KEY = 'AWS_XRAY_TRACING_NAME'.freeze
|
20
|
-
CONFIG_KEY = %I[logger name sampling plugins daemon_address
|
21
|
-
naming_pattern emitter streamer context
|
22
|
-
sampling_rules stream_threshold patch].freeze
|
21
|
+
CONFIG_KEY = %I[logger name sampling plugins daemon_address
|
22
|
+
segment_naming naming_pattern emitter streamer context
|
23
|
+
context_missing sampling_rules stream_threshold patch].freeze
|
23
24
|
|
24
25
|
def initialize
|
25
26
|
@name = ENV[SEGMENT_NAME_KEY]
|
@@ -38,9 +39,12 @@ module XRay
|
|
38
39
|
@name = ENV[SEGMENT_NAME_KEY] || v
|
39
40
|
end
|
40
41
|
|
41
|
-
#
|
42
|
+
# setting daemon address for components communicate with X-Ray daemon.
|
42
43
|
def daemon_address=(v)
|
43
|
-
|
44
|
+
v = ENV[DaemonConfig::DAEMON_ADDRESS_KEY] || v
|
45
|
+
config = DaemonConfig.new(v)
|
46
|
+
emitter.daemon_config = config
|
47
|
+
sampler.daemon_config = config if sampler.respond_to?(:daemon_config=)
|
44
48
|
end
|
45
49
|
|
46
50
|
# proxy method to the context's context_missing config.
|
@@ -63,8 +67,7 @@ module XRay
|
|
63
67
|
segment_naming.pattern = v
|
64
68
|
end
|
65
69
|
|
66
|
-
# makes a sampling decision
|
67
|
-
# if sampling enabled and the default sampling rule.
|
70
|
+
# makes a sampling decision without incoming filters.
|
68
71
|
def sample?
|
69
72
|
return true unless sampling
|
70
73
|
sampler.sample?
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'aws-xray-sdk/exceptions'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# The class that stores X-Ray daemon configuration about
|
5
|
+
# the ip address and port for UDP and TCP port. It gets the address
|
6
|
+
# string from `AWS_XRAY_DAEMON_ADDRESS` and then from recorder's
|
7
|
+
# configuration for `daemon_address`.
|
8
|
+
# A notation of `127.0.0.1:2000` or `tcp:127.0.0.1:2000 udp:127.0.0.2:2001`
|
9
|
+
# are both acceptable. The former one means UDP and TCP are running at
|
10
|
+
# the same address. By default it assumes a X-Ray daemon
|
11
|
+
# running at `127.0.0.1:2000` listening to both UDP and TCP traffic.
|
12
|
+
class DaemonConfig
|
13
|
+
DAEMON_ADDRESS_KEY = 'AWS_XRAY_DAEMON_ADDRESS'.freeze
|
14
|
+
attr_reader :tcp_ip, :tcp_port, :udp_ip, :udp_port
|
15
|
+
@@dafault_addr = '127.0.0.1:2000'
|
16
|
+
|
17
|
+
def initialize(addr: @@dafault_addr)
|
18
|
+
update_address(addr)
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_address(v)
|
22
|
+
v = ENV[DAEMON_ADDRESS_KEY] || v
|
23
|
+
update_addr(v)
|
24
|
+
rescue StandardError
|
25
|
+
raise InvalidDaemonAddressError, %(Invalid X-Ray daemon address specified: #{v}.)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def update_addr(v)
|
31
|
+
parts = v.split(' ')
|
32
|
+
if parts.length == 1 # format of '127.0.0.1:2000'
|
33
|
+
addr = parts[0].split(':')
|
34
|
+
raise InvalidDaemonAddressError unless addr.length == 2
|
35
|
+
@tcp_ip = addr[0]
|
36
|
+
@tcp_port = addr[1].to_i
|
37
|
+
@udp_ip = addr[0]
|
38
|
+
@udp_port = addr[1].to_i
|
39
|
+
else
|
40
|
+
set_tcp_udp(parts) # format of 'tcp:127.0.0.1:2000 udp:127.0.0.2:2001'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_tcp_udp(parts)
|
45
|
+
part1 = parts[0]
|
46
|
+
part2 = parts[1]
|
47
|
+
key1 = part1.split(':')[0]
|
48
|
+
key2 = part2.split(':')[0]
|
49
|
+
addr_h = {}
|
50
|
+
addr_h[key1] = part1.split(':')
|
51
|
+
addr_h[key2] = part2.split(':')
|
52
|
+
|
53
|
+
@tcp_ip = addr_h['tcp'][1]
|
54
|
+
@tcp_port = addr_h['tcp'][2].to_i
|
55
|
+
@udp_ip = addr_h['udp'][1]
|
56
|
+
@udp_port = addr_h['udp'][2].to_i
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -2,6 +2,7 @@ require 'socket'
|
|
2
2
|
require 'aws-xray-sdk/logger'
|
3
3
|
require 'aws-xray-sdk/emitter/emitter'
|
4
4
|
require 'aws-xray-sdk/exceptions'
|
5
|
+
require 'aws-xray-sdk/daemon_config'
|
5
6
|
|
6
7
|
module XRay
|
7
8
|
# The default emitter the X-Ray recorder uses to send segments/subsegments
|
@@ -10,12 +11,11 @@ module XRay
|
|
10
11
|
include Emitter
|
11
12
|
include Logging
|
12
13
|
|
13
|
-
attr_reader :
|
14
|
+
attr_reader :daemon_config
|
14
15
|
|
15
|
-
def initialize
|
16
|
+
def initialize(daemon_config: DaemonConfig.new)
|
16
17
|
@socket = UDPSocket.new
|
17
|
-
|
18
|
-
configure_socket(@address)
|
18
|
+
self.daemon_config = daemon_config
|
19
19
|
end
|
20
20
|
|
21
21
|
# Serializes a segment/subsegment and sends it to the X-Ray daemon
|
@@ -25,29 +25,18 @@ module XRay
|
|
25
25
|
return nil unless entity.sampled
|
26
26
|
begin
|
27
27
|
payload = %(#{@@protocol_header}#{@@protocol_delimiter}#{entity.to_json})
|
28
|
-
logger.debug %(sending payload #{payload} to daemon at #{address}.)
|
28
|
+
logger.debug %(sending payload #{payload} to daemon at #{@address}.)
|
29
29
|
@socket.send payload, 0
|
30
30
|
rescue StandardError => e
|
31
31
|
logger.warn %(failed to send payload due to #{e.message})
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
|
37
|
-
@
|
38
|
-
|
39
|
-
|
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
|
35
|
+
def daemon_config=(v)
|
36
|
+
@address = %(#{v.udp_ip}:#{v.udp_port})
|
37
|
+
@socket.connect(v.udp_ip, v.udp_port)
|
38
|
+
rescue StandardError
|
39
|
+
raise InvalidDaemonAddressError, %(Invalid X-Ray daemon address specified: #{v}.)
|
51
40
|
end
|
52
41
|
end
|
53
42
|
end
|
@@ -4,8 +4,6 @@ module XRay
|
|
4
4
|
# The emitter interface the X-Ray recorder uses to send segments/subsegments
|
5
5
|
# to the X-Ray daemon over UDP.
|
6
6
|
module Emitter
|
7
|
-
DAEMON_ADDRESS_KEY = 'AWS_XRAY_DAEMON_ADDRESS'.freeze
|
8
|
-
|
9
7
|
@@protocol_header = {
|
10
8
|
format: 'json',
|
11
9
|
version: 1
|
@@ -17,7 +15,7 @@ module XRay
|
|
17
15
|
raise 'Not implemented'
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
18
|
+
def daemon_config=(v)
|
21
19
|
raise 'Not implemented'
|
22
20
|
end
|
23
21
|
end
|
@@ -17,15 +17,19 @@ module XRay
|
|
17
17
|
include XRay::Facets::Helper
|
18
18
|
|
19
19
|
def call(context)
|
20
|
-
recorder = Aws.config[:xray_recorder]
|
21
|
-
if recorder.current_entity.nil?
|
22
|
-
super
|
23
|
-
end
|
24
|
-
|
25
20
|
operation = context.operation_name
|
26
21
|
service_name = context.client.class.api.metadata['serviceAbbreviation'] ||
|
27
22
|
context.client.class.to_s.split('::')[1]
|
28
|
-
|
23
|
+
if skip?(service_name, operation)
|
24
|
+
return super
|
25
|
+
end
|
26
|
+
|
27
|
+
recorder = Aws.config[:xray_recorder]
|
28
|
+
if recorder.nil? || recorder.current_entity.nil?
|
29
|
+
return super
|
30
|
+
end
|
31
|
+
|
32
|
+
recorder.capture(service_name, namespace: 'aws') do |subsegment|
|
29
33
|
# inject header string before calling downstream AWS services
|
30
34
|
context.http_request.headers[TRACE_HEADER] = prep_header_str entity: subsegment
|
31
35
|
response = @handler.call(context)
|
@@ -109,6 +113,10 @@ module XRay
|
|
109
113
|
v = target.keys if descriptor[:get_keys]
|
110
114
|
meta[descriptor[:rename_to]] = v
|
111
115
|
end
|
116
|
+
|
117
|
+
def skip?(service, op)
|
118
|
+
return service == 'XRay' && (op == :get_sampling_rules || op == :get_sampling_targets)
|
119
|
+
end
|
112
120
|
end
|
113
121
|
end
|
114
122
|
|
@@ -26,21 +26,14 @@ module XRay
|
|
26
26
|
# the highest precedence. If the `trace_header` doesn't contain
|
27
27
|
# sampling decision then it checks if sampling is enabled or not
|
28
28
|
# in the recorder. If not enbaled it returns 'true'. Otherwise it uses
|
29
|
-
# sampling
|
30
|
-
def should_sample?(header_obj:, recorder:,
|
31
|
-
host: nil, method: nil, path: nil,
|
32
|
-
**args)
|
29
|
+
# sampling rules to decide.
|
30
|
+
def should_sample?(header_obj:, recorder:, sampling_req:, **args)
|
33
31
|
# check outside decision
|
34
32
|
if i = header_obj.sampled
|
35
|
-
|
36
|
-
false
|
37
|
-
else
|
38
|
-
true
|
39
|
-
end
|
33
|
+
!i.zero?
|
40
34
|
# check sampling rules
|
41
35
|
elsif recorder.sampling_enabled?
|
42
|
-
recorder.sampler.sample_request?(
|
43
|
-
http_method: method)
|
36
|
+
recorder.sampler.sample_request?(sampling_req)
|
44
37
|
# sample if no reason not to
|
45
38
|
else
|
46
39
|
true
|
@@ -21,6 +21,10 @@ module XRay
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def request(req, body = nil, &block)
|
24
|
+
if req.path && (req.path == ('/GetSamplingRules') || req.path == ('/SamplingTargets'))
|
25
|
+
return super
|
26
|
+
end
|
27
|
+
|
24
28
|
entity = XRay.recorder.current_entity
|
25
29
|
capture = !(entity && entity.namespace && entity.namespace == 'aws'.freeze)
|
26
30
|
if started? && capture && entity
|
@@ -8,6 +8,7 @@ module XRay
|
|
8
8
|
class Middleware
|
9
9
|
include XRay::Facets::Helper
|
10
10
|
X_FORWARD = 'HTTP_X_FORWARDED_FOR'.freeze
|
11
|
+
SCHEME_SEPARATOR = "://".freeze
|
11
12
|
|
12
13
|
def initialize(app, recorder: nil)
|
13
14
|
@app = app
|
@@ -22,16 +23,15 @@ module XRay
|
|
22
23
|
host = req.host
|
23
24
|
url_path = req.path
|
24
25
|
method = req.request_method
|
26
|
+
# get segment name from host header if applicable
|
27
|
+
seg_name = @recorder.segment_naming.provide_name(host: req.host)
|
25
28
|
|
26
29
|
# get sampling decision
|
27
30
|
sampled = should_sample?(
|
28
|
-
header_obj: header, recorder: @recorder,
|
29
|
-
host: host,
|
31
|
+
header_obj: header, recorder: @recorder, sampling_req:
|
32
|
+
{ host: host, http_method: method, url_path: url_path, service: seg_name }
|
30
33
|
)
|
31
34
|
|
32
|
-
# get segment name from host header if applicable
|
33
|
-
seg_name = @recorder.segment_naming.provide_name(host: req.host)
|
34
|
-
|
35
35
|
# begin the segment
|
36
36
|
segment = @recorder.begin_segment seg_name, trace_id: header.root, parent_id: header.parent_id,
|
37
37
|
sampled: sampled
|
@@ -63,7 +63,9 @@ module XRay
|
|
63
63
|
|
64
64
|
def extract_request_meta(req)
|
65
65
|
req_meta = {}
|
66
|
-
req_meta[:url] = req.
|
66
|
+
req_meta[:url] = req.scheme + SCHEME_SEPARATOR if req.scheme
|
67
|
+
req_meta[:url] += req.host_with_port if req.host_with_port
|
68
|
+
req_meta[:url] += req.path if req.path
|
67
69
|
req_meta[:user_agent] = req.user_agent if req.user_agent
|
68
70
|
req_meta[:method] = req.request_method if req.request_method
|
69
71
|
if req.has_header?(X_FORWARD)
|
@@ -6,7 +6,7 @@ module XRay
|
|
6
6
|
class Railtie < ::Rails::Railtie
|
7
7
|
RAILS_OPTIONS = %I[active_record].freeze
|
8
8
|
|
9
|
-
initializer
|
9
|
+
initializer("aws-xray-sdk.rack_middleware") do |app|
|
10
10
|
app.middleware.insert 0, Rack::Middleware
|
11
11
|
app.middleware.use XRay::Rails::ExceptionMiddleware
|
12
12
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'multi_json'
|
2
2
|
|
3
3
|
module XRay
|
4
4
|
# Represents cause section in segment and subsegment document.
|
@@ -26,7 +26,7 @@ module XRay
|
|
26
26
|
|
27
27
|
def to_json
|
28
28
|
@to_json ||= begin
|
29
|
-
|
29
|
+
MultiJson.dump to_h
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
require 'bigdecimal'
|
3
|
-
require '
|
3
|
+
require 'multi_json'
|
4
4
|
require 'aws-xray-sdk/exceptions'
|
5
5
|
require 'aws-xray-sdk/model/cause'
|
6
6
|
require 'aws-xray-sdk/model/annotations'
|
@@ -168,7 +168,7 @@ module XRay
|
|
168
168
|
|
169
169
|
def to_json
|
170
170
|
@to_json ||= begin
|
171
|
-
|
171
|
+
MultiJson.dump(to_h)
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'multi_json'
|
2
2
|
require 'aws-xray-sdk/exceptions'
|
3
3
|
|
4
4
|
module XRay
|
@@ -48,7 +48,7 @@ module XRay
|
|
48
48
|
|
49
49
|
def to_json
|
50
50
|
@to_json ||= begin
|
51
|
-
|
51
|
+
MultiJson.dump to_h
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -6,7 +6,8 @@ module XRay
|
|
6
6
|
# details about the request, and details about the work done.
|
7
7
|
class Segment
|
8
8
|
include Entity
|
9
|
-
attr_accessor :ref_counter, :subsegment_size, :origin,
|
9
|
+
attr_accessor :ref_counter, :subsegment_size, :origin,
|
10
|
+
:user, :service
|
10
11
|
|
11
12
|
# @param [String] trace_id Manually crafted trace id.
|
12
13
|
# @param [String] name Must be specified either on object creation or
|
@@ -39,6 +40,12 @@ module XRay
|
|
39
40
|
@subsegment_size = subsegment_size - subsegment.all_children_count - 1
|
40
41
|
end
|
41
42
|
|
43
|
+
def sampling_rule_name=(v)
|
44
|
+
@aws ||= {}
|
45
|
+
@aws[:xray] ||= {}
|
46
|
+
@aws[:xray][:sampling_rule_name] = v
|
47
|
+
end
|
48
|
+
|
42
49
|
def decrement_ref_counter
|
43
50
|
@ref_counter -= 1
|
44
51
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'multi_json'
|
2
2
|
require 'aws-xray-sdk/logger'
|
3
3
|
|
4
4
|
module XRay
|
@@ -14,7 +14,7 @@ module XRay
|
|
14
14
|
def self.aws
|
15
15
|
@@aws ||= begin
|
16
16
|
file = File.open(CONF_PATH)
|
17
|
-
{ elastic_beanstalk:
|
17
|
+
{ elastic_beanstalk: MultiJson.load(file) }
|
18
18
|
rescue StandardError => e
|
19
19
|
@@aws = {}
|
20
20
|
Logging.logger.warn %(can not get the environment config due to: #{e.message}.)
|
@@ -12,11 +12,12 @@ module XRay
|
|
12
12
|
# and send them to the X-Ray daemon. It is also responsible for managing
|
13
13
|
# context.
|
14
14
|
class Recorder
|
15
|
-
attr_reader :config
|
15
|
+
attr_reader :config, :origin
|
16
16
|
|
17
17
|
def initialize(user_config: nil)
|
18
18
|
@config = Configuration.new
|
19
19
|
@config.configure(user_config) unless user_config.nil?
|
20
|
+
@origin = nil
|
20
21
|
end
|
21
22
|
|
22
23
|
# Begin a segment for the current context. The recorder
|
@@ -31,7 +32,7 @@ module XRay
|
|
31
32
|
sample = sampled.nil? ? config.sample? : sampled
|
32
33
|
if sample
|
33
34
|
segment = Segment.new name: seg_name, trace_id: trace_id, parent_id: parent_id
|
34
|
-
populate_runtime_context(segment)
|
35
|
+
populate_runtime_context(segment, sample)
|
35
36
|
else
|
36
37
|
segment = DummySegment.new name: seg_name, trace_id: trace_id, parent_id: parent_id
|
37
38
|
end
|
@@ -204,14 +205,14 @@ module XRay
|
|
204
205
|
|
205
206
|
private_class_method
|
206
207
|
|
207
|
-
def populate_runtime_context(segment)
|
208
|
+
def populate_runtime_context(segment, sample)
|
208
209
|
@aws ||= begin
|
209
210
|
aws = {}
|
210
211
|
config.plugins.each do |p|
|
211
212
|
meta = p.aws
|
212
213
|
if meta.is_a?(Hash) && !meta.empty?
|
213
214
|
aws.merge! meta
|
214
|
-
|
215
|
+
@origin = p::ORIGIN
|
215
216
|
end
|
216
217
|
end
|
217
218
|
xray_meta = { xray:
|
@@ -230,6 +231,8 @@ module XRay
|
|
230
231
|
|
231
232
|
segment.aws = @aws
|
232
233
|
segment.service = @service
|
234
|
+
segment.origin = @origin
|
235
|
+
segment.sampling_rule_name = sample if sample.is_a?(String)
|
233
236
|
end
|
234
237
|
end
|
235
238
|
end
|