aws-xray-sdk 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'oj'
|
2
|
+
require 'aws-xray-sdk/exceptions'
|
3
|
+
|
4
|
+
module XRay
|
5
|
+
# Metadata are key-value pairs with values of any type, including objects
|
6
|
+
# and lists, but that are not indexed. Use metadata to record data
|
7
|
+
# you want to store in the trace but don't need to use for searching traces.
|
8
|
+
class Metadata
|
9
|
+
def initialize(entity)
|
10
|
+
@data = {}
|
11
|
+
@entity = entity
|
12
|
+
end
|
13
|
+
|
14
|
+
def sub_meta(namespace)
|
15
|
+
@data[namespace] = SubMeta.new(@entity) unless @data[namespace]
|
16
|
+
@data[namespace]
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
@data
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# The actual class that stores all data under a certain namespace.
|
25
|
+
class SubMeta
|
26
|
+
def initialize(entity)
|
27
|
+
@data = {}
|
28
|
+
@entity = entity
|
29
|
+
end
|
30
|
+
|
31
|
+
def [](key)
|
32
|
+
@data[key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def []=(k, v)
|
36
|
+
raise EntityClosedError if @entity.closed?
|
37
|
+
@data[k] = v
|
38
|
+
end
|
39
|
+
|
40
|
+
def update(h)
|
41
|
+
raise EntityClosedError if @entity.closed?
|
42
|
+
@data.merge!(h)
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_h
|
46
|
+
@data
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_json
|
50
|
+
@to_json ||= begin
|
51
|
+
Oj.dump to_h, mode: :compat, use_as_json: true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Singleton facade metadata class doing no-op for performance
|
57
|
+
# in case of not sampled X-Ray entities.
|
58
|
+
module FacadeMetadata
|
59
|
+
class << self
|
60
|
+
def [](key)
|
61
|
+
# no-op
|
62
|
+
end
|
63
|
+
|
64
|
+
def []=(k, v)
|
65
|
+
# no-op
|
66
|
+
end
|
67
|
+
|
68
|
+
def update(h)
|
69
|
+
# no-op
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_h
|
73
|
+
# no-op
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'aws-xray-sdk/model/entity'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# The compute resources running your application logic send data
|
5
|
+
# about their work as segments. A segment provides the resource's name,
|
6
|
+
# details about the request, and details about the work done.
|
7
|
+
class Segment
|
8
|
+
include Entity
|
9
|
+
attr_accessor :ref_counter, :subsegment_size, :origin, :user
|
10
|
+
|
11
|
+
# @param [String] trace_id Manually crafted trace id.
|
12
|
+
# @param [String] name Must be specified either on object creation or
|
13
|
+
# on environment variable `AWS_TRACING_NAME`. The latter has higher precedence.
|
14
|
+
# @param [String] parent_id ID of the segment/subsegment representing the upstream caller.
|
15
|
+
def initialize(trace_id: nil, name: nil, parent_id: nil)
|
16
|
+
@trace_id = trace_id
|
17
|
+
@name = ENV['AWS_TRACING_NAME'] || name
|
18
|
+
@parent_id = parent_id
|
19
|
+
@start_time = Time.now.to_f
|
20
|
+
@ref_counter = 0
|
21
|
+
@subsegment_size = 0
|
22
|
+
@sampled = true
|
23
|
+
end
|
24
|
+
|
25
|
+
def trace_id
|
26
|
+
@trace_id ||= begin
|
27
|
+
%[1-#{Time.now.to_i.to_s(16)}-#{SecureRandom.hex(12)}]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_subsegment(subsegment:)
|
32
|
+
super subsegment: subsegment
|
33
|
+
@ref_counter += 1
|
34
|
+
@subsegment_size += 1
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_subsegment(subsegment:)
|
38
|
+
super subsegment: subsegment
|
39
|
+
@subsegment_size = subsegment_size - subsegment.all_children_count - 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def decrement_ref_counter
|
43
|
+
@ref_counter -= 1
|
44
|
+
end
|
45
|
+
|
46
|
+
def ready_to_send?
|
47
|
+
closed? && ref_counter.zero?
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_h
|
51
|
+
h = super
|
52
|
+
h[:trace_id] = trace_id
|
53
|
+
h[:origin] = origin if origin
|
54
|
+
h[:parent_id] = @parent_id if @parent_id
|
55
|
+
h[:user] = user if user
|
56
|
+
h
|
57
|
+
end
|
58
|
+
|
59
|
+
def segment
|
60
|
+
self
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'aws-xray-sdk/model/entity'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# The work done in a single segment can be broke down into subsegments.
|
5
|
+
# Subsegments provide more granular timing information and details about
|
6
|
+
# downstream calls that your application made to fulfill the original request.
|
7
|
+
# A subsegment can contain additional details about a call to an AWS service,
|
8
|
+
# an external HTTP API, or an SQL database.
|
9
|
+
class Subsegment
|
10
|
+
include Entity
|
11
|
+
|
12
|
+
attr_reader :segment
|
13
|
+
attr_accessor :sql
|
14
|
+
|
15
|
+
# @param [String] name The subsegment name.
|
16
|
+
# @param [Segment] segment The root parent segment. This segment
|
17
|
+
# may not be its direct parent.
|
18
|
+
# @param [String] namespace Currently supported namespaces are
|
19
|
+
# 'remote', 'aws', 'local'.
|
20
|
+
def initialize(name:, segment:, namespace: 'local')
|
21
|
+
@name = name
|
22
|
+
@segment = segment
|
23
|
+
@namespace = namespace
|
24
|
+
@start_time = Time.now.to_f
|
25
|
+
@sampled = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_subsegment(subsegment:)
|
29
|
+
super subsegment: subsegment
|
30
|
+
segment.ref_counter += 1
|
31
|
+
segment.subsegment_size += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def remove_subsegment(subsegment:)
|
35
|
+
super subsegment: subsegment
|
36
|
+
cur = segment.subsegment_size
|
37
|
+
segment.subsegment_size = cur - subsegment.all_children_count - 1
|
38
|
+
end
|
39
|
+
|
40
|
+
def close(end_time: nil)
|
41
|
+
super end_time: end_time
|
42
|
+
segment.decrement_ref_counter
|
43
|
+
end
|
44
|
+
|
45
|
+
def sql
|
46
|
+
@sql ||= {}
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the number of its direct and indirect children.
|
50
|
+
# This is useful when we remove the reference to a subsegment
|
51
|
+
# and need to keep remaining subsegment size accurate.
|
52
|
+
def all_children_count
|
53
|
+
size = subsegments.count
|
54
|
+
subsegments.each { |v| size += v.all_children_count }
|
55
|
+
size
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_h
|
59
|
+
h = super
|
60
|
+
h[:trace_id] = segment.trace_id
|
61
|
+
h[:sql] = sql unless sql.empty?
|
62
|
+
h[:type] = 'subsegment'
|
63
|
+
h[:namespace] = namespace if namespace
|
64
|
+
h
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'aws-xray-sdk/logger'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# The sampling decision and trace ID are added to HTTP requests in
|
5
|
+
# tracing headers named ``X-Amzn-Trace-Id``. The first X-Ray-integrated
|
6
|
+
# service that the request hits adds a tracing header, which is read
|
7
|
+
# by the X-Ray SDK and included in the response.
|
8
|
+
class TraceHeader
|
9
|
+
include Logging
|
10
|
+
attr_accessor :root, :parent_id, :sampled
|
11
|
+
|
12
|
+
# @param [String] root Trace id.
|
13
|
+
# @param [String] parent_id The id of the parent segment or subsegment.
|
14
|
+
# @param [Integer] sampled 0 means not sampled.
|
15
|
+
def initialize(root:, parent_id:, sampled:)
|
16
|
+
@root = root
|
17
|
+
@parent_id = parent_id
|
18
|
+
@sampled = sampled.to_i if sampled
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_header_string(header_str:)
|
22
|
+
empty_header if header_str.to_s.empty?
|
23
|
+
header = header_str.delete(' ').downcase
|
24
|
+
tmp = {}
|
25
|
+
begin
|
26
|
+
fields = header.split(';')
|
27
|
+
fields.each do |f|
|
28
|
+
pair = f.split('=')
|
29
|
+
tmp[pair[0].to_sym] = pair[1]
|
30
|
+
end
|
31
|
+
new root: tmp[:root], parent_id: tmp[:parent], sampled: tmp[:sampled]
|
32
|
+
rescue StandardError
|
33
|
+
logger.warn %(Invalid trace header #{header}. Ignored.)
|
34
|
+
empty_header
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [String] The heading string constructed based on this header object.
|
39
|
+
def header_string
|
40
|
+
return '' unless root
|
41
|
+
if !parent_id
|
42
|
+
%(Root=#{root};Sampled=#{sampled})
|
43
|
+
elsif !sampled
|
44
|
+
%(Root=#{root};Parent=#{parent_id})
|
45
|
+
else
|
46
|
+
%(Root=#{root};Parent=#{parent_id};Sampled=#{sampled})
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.empty_header
|
51
|
+
new root: nil, parent_id: nil, sampled: nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'aws-xray-sdk/exceptions'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# Patching external libraries/frameworks to be traced by X-Ray recorder.
|
5
|
+
module Patcher
|
6
|
+
# @param [Array] targets A list of libraries/frameworks to patch.
|
7
|
+
def patch(targets)
|
8
|
+
targets.each do |l|
|
9
|
+
case l
|
10
|
+
when :net_http
|
11
|
+
require 'aws-xray-sdk/facets/net_http'
|
12
|
+
when :aws_sdk
|
13
|
+
require 'aws-xray-sdk/facets/aws_sdk'
|
14
|
+
XRay::AwsSDKPatcher.patch
|
15
|
+
else
|
16
|
+
raise UnsupportedPatchingTargetError.new(%(#{l} is not supported by X-Ray SDK.))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'aws-xray-sdk/logger'
|
3
|
+
|
4
|
+
module XRay
|
5
|
+
module Plugins
|
6
|
+
# A plugin that gets the EC2 instance-id and AZ if running on an EC2 instance.
|
7
|
+
module EC2
|
8
|
+
include Logging
|
9
|
+
|
10
|
+
ORIGIN = 'AWS::EC2::Instance'.freeze
|
11
|
+
# http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-retrieval
|
12
|
+
ID_ADDR = 'http://169.254.169.254/latest/meta-data/instance-id'.freeze
|
13
|
+
AZ_ADDR = 'http://169.254.169.254/latest/meta-data/placement/availability-zone'.freeze
|
14
|
+
|
15
|
+
def self.aws
|
16
|
+
@@aws ||= begin
|
17
|
+
instance_id = open(ID_ADDR, open_timeout: 1).read
|
18
|
+
az = open(AZ_ADDR, open_timeout: 1).read
|
19
|
+
{
|
20
|
+
ec2: {
|
21
|
+
instance_id: instance_id,
|
22
|
+
availability_zone: az
|
23
|
+
}
|
24
|
+
}
|
25
|
+
rescue StandardError => e
|
26
|
+
# Two attempts in total to get EC2 metadata
|
27
|
+
@retries ||= 0
|
28
|
+
if @retries < 1
|
29
|
+
@retries += 1
|
30
|
+
retry
|
31
|
+
else
|
32
|
+
@@aws = {}
|
33
|
+
Logging.logger.warn %(can not get the ec2 instance metadata due to: #{e.message}.)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'aws-xray-sdk/logger'
|
3
|
+
|
4
|
+
module XRay
|
5
|
+
module Plugins
|
6
|
+
# Due to lack of ECS container metadata service, the only host information
|
7
|
+
# available is the host name.
|
8
|
+
module ECS
|
9
|
+
include Logging
|
10
|
+
|
11
|
+
ORIGIN = 'AWS::ECS::Container'.freeze
|
12
|
+
|
13
|
+
def self.aws
|
14
|
+
@@aws ||= begin
|
15
|
+
{ ecs: { container: Socket.gethostname } }
|
16
|
+
rescue StandardError => e
|
17
|
+
@@aws = {}
|
18
|
+
Logging.logger.warn %(can not get the ecs container hostname due to: #{e.message}.)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'oj'
|
2
|
+
require 'aws-xray-sdk/logger'
|
3
|
+
|
4
|
+
module XRay
|
5
|
+
module Plugins
|
6
|
+
# A plugin that records information about the elastic beanstalk environment
|
7
|
+
# hosting your application.
|
8
|
+
module ElasticBeanstalk
|
9
|
+
include Logging
|
10
|
+
|
11
|
+
CONF_PATH = '/var/elasticbeanstalk/xray/environment.conf'.freeze
|
12
|
+
ORIGIN = 'AWS::ElasticBeanstalk::Environment'.freeze
|
13
|
+
|
14
|
+
def self.aws
|
15
|
+
@@aws ||= begin
|
16
|
+
file = File.open(CONF_PATH)
|
17
|
+
{ elastic_beanstalk: Oj.load(file) }
|
18
|
+
rescue StandardError => e
|
19
|
+
@@aws = {}
|
20
|
+
Logging.logger.warn %(can not get the environment config due to: #{e.message}.)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'aws-xray-sdk/configuration'
|
2
|
+
require 'aws-xray-sdk/exceptions'
|
3
|
+
require 'aws-xray-sdk/model/segment'
|
4
|
+
require 'aws-xray-sdk/model/subsegment'
|
5
|
+
require 'aws-xray-sdk/model/dummy_entities'
|
6
|
+
require 'aws-xray-sdk/model/annotations'
|
7
|
+
require 'aws-xray-sdk/model/metadata'
|
8
|
+
|
9
|
+
module XRay
|
10
|
+
# A global AWS X-Ray recorder that will begin/end segments/subsegments
|
11
|
+
# and send them to the X-Ray daemon. It is also responsible for managing
|
12
|
+
# context.
|
13
|
+
class Recorder
|
14
|
+
attr_reader :config
|
15
|
+
|
16
|
+
def initialize(user_config: nil)
|
17
|
+
@config = Configuration.new
|
18
|
+
@config.configure(user_config) unless user_config.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
# Begin a segment for the current context. The recorder
|
22
|
+
# only keeps one segment at a time. Create a second one without
|
23
|
+
# closing existing one will overwrite the existing one.
|
24
|
+
# @return [Segment] thew newly created segment.
|
25
|
+
def begin_segment(name, trace_id: nil, parent_id: nil, sampled: nil)
|
26
|
+
seg_name = name || config.name
|
27
|
+
raise SegmentNameMissingError if seg_name.to_s.empty?
|
28
|
+
|
29
|
+
# sampling decision comes from outside has higher precedence.
|
30
|
+
sample = sampled.nil? ? config.sample? : sampled
|
31
|
+
if sample
|
32
|
+
segment = Segment.new name: seg_name, trace_id: trace_id, parent_id: parent_id
|
33
|
+
populate_runtime_context(segment)
|
34
|
+
else
|
35
|
+
segment = DummySegment.new name: seg_name, trace_id: trace_id, parent_id: parent_id
|
36
|
+
end
|
37
|
+
context.store_entity entity: segment
|
38
|
+
segment
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [Segment] the active segment tied to the current context.
|
42
|
+
# If the current context is under a subsegment, it returns its parent segment.
|
43
|
+
def current_segment
|
44
|
+
entity = current_entity
|
45
|
+
entity.segment if entity
|
46
|
+
end
|
47
|
+
|
48
|
+
# End the current segment and send it to X-Ray daemon if it is ready.
|
49
|
+
def end_segment(end_time: nil)
|
50
|
+
segment = current_segment
|
51
|
+
return unless segment
|
52
|
+
segment.close end_time: end_time
|
53
|
+
context.clear!
|
54
|
+
emitter.send_entity entity: segment if segment.ready_to_send?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Begin a new subsegment and add it to be the child of the current active
|
58
|
+
# subsegment or segment. Also tie the new created subsegment to the current context.
|
59
|
+
# Its sampling decision will follow its parent.
|
60
|
+
# @return [Subsegment] the newly created subsegment.
|
61
|
+
def begin_subsegment(name, namespace: nil, segment: nil)
|
62
|
+
entity = segment || current_entity
|
63
|
+
return unless entity
|
64
|
+
if entity.sampled
|
65
|
+
subsegment = Subsegment.new name: name, segment: entity.segment, namespace: namespace
|
66
|
+
else
|
67
|
+
subsegment = DummySubsegment.new name: name, segment: entity.segment
|
68
|
+
end
|
69
|
+
# attach the new created subsegment under the current active entity
|
70
|
+
entity.add_subsegment subsegment: subsegment
|
71
|
+
# associate the new subsegment to the current context
|
72
|
+
context.store_entity entity: subsegment
|
73
|
+
subsegment
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Subsegment] the active subsegment tied to the current context.
|
77
|
+
# Returns nil if the current context has no associated subsegment.
|
78
|
+
def current_subsegment
|
79
|
+
entity = context.current_entity
|
80
|
+
entity.is_a?(Subsegment) ? entity : nil
|
81
|
+
end
|
82
|
+
|
83
|
+
# End the current active subsegment. It also send the entire segment if
|
84
|
+
# this subsegment is the last one open or stream out subsegments of its
|
85
|
+
# parent segment if the stream threshold is breached.
|
86
|
+
def end_subsegment(end_time: nil)
|
87
|
+
entity = current_entity
|
88
|
+
return unless entity.is_a?(Subsegment)
|
89
|
+
entity.close end_time: end_time
|
90
|
+
# update current context
|
91
|
+
if entity.parent.closed?
|
92
|
+
context.clear!
|
93
|
+
else
|
94
|
+
context.store_entity entity: entity.parent
|
95
|
+
end
|
96
|
+
# check if the entire segment can be send.
|
97
|
+
# If not, stream subsegments when threshold is reached.
|
98
|
+
segment = entity.segment
|
99
|
+
if segment.ready_to_send?
|
100
|
+
emitter.send_entity entity: segment
|
101
|
+
elsif streamer.eligible? segment: segment
|
102
|
+
streamer.stream_subsegments root: segment, emitter: emitter
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Record the passed block as a subsegment.
|
107
|
+
def capture(name, namespace: nil, segment: nil)
|
108
|
+
subsegment = begin_subsegment name, namespace: namespace, segment: segment
|
109
|
+
begin
|
110
|
+
yield subsegment
|
111
|
+
rescue Exception => e
|
112
|
+
subsegment.add_exception exception: e
|
113
|
+
raise e
|
114
|
+
ensure
|
115
|
+
end_subsegment
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns current segment or subsegment that associated to the current context.
|
120
|
+
# This is a proxy method to Context class current_entity.
|
121
|
+
def current_entity
|
122
|
+
context.current_entity
|
123
|
+
end
|
124
|
+
|
125
|
+
def inject_context(entity, target_ctx: nil)
|
126
|
+
context.inject_context entity, target_ctx: target_ctx
|
127
|
+
return unless block_given?
|
128
|
+
yield
|
129
|
+
context.clear!
|
130
|
+
end
|
131
|
+
|
132
|
+
def clear_context
|
133
|
+
context.clear!
|
134
|
+
end
|
135
|
+
|
136
|
+
def sampled?
|
137
|
+
entity = current_entity
|
138
|
+
if block_given?
|
139
|
+
yield if entity && entity.sampled
|
140
|
+
else
|
141
|
+
entity && entity.sampled
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# A proxy method to get the annotations from the current active entity.
|
146
|
+
def annotations
|
147
|
+
entity = current_entity
|
148
|
+
if entity
|
149
|
+
entity.annotations
|
150
|
+
else
|
151
|
+
FacadeAnnotations
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# A proxy method to get the metadata under provided namespace
|
156
|
+
# from the current active entity.
|
157
|
+
def metadata(namespace: :default)
|
158
|
+
entity = current_entity
|
159
|
+
if entity
|
160
|
+
entity.metadata(namespace: namespace)
|
161
|
+
else
|
162
|
+
FacadeMetadata
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# A proxy method to XRay::Configuration.configure
|
167
|
+
def configure(user_config)
|
168
|
+
config.configure(user_config)
|
169
|
+
end
|
170
|
+
|
171
|
+
def context
|
172
|
+
config.context
|
173
|
+
end
|
174
|
+
|
175
|
+
def sampler
|
176
|
+
config.sampler
|
177
|
+
end
|
178
|
+
|
179
|
+
def emitter
|
180
|
+
config.emitter
|
181
|
+
end
|
182
|
+
|
183
|
+
def streamer
|
184
|
+
config.streamer
|
185
|
+
end
|
186
|
+
|
187
|
+
def segment_naming
|
188
|
+
config.segment_naming
|
189
|
+
end
|
190
|
+
|
191
|
+
def sampling_enabled?
|
192
|
+
config.sampling
|
193
|
+
end
|
194
|
+
|
195
|
+
private_class_method
|
196
|
+
|
197
|
+
def populate_runtime_context(segment)
|
198
|
+
aws = {}
|
199
|
+
config.plugins.each do |p|
|
200
|
+
meta = p.aws
|
201
|
+
if meta.is_a?(Hash) && !meta.empty?
|
202
|
+
aws.merge! meta
|
203
|
+
segment.origin = p::ORIGIN
|
204
|
+
end
|
205
|
+
end
|
206
|
+
segment.aws = aws unless aws.empty?
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|