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
@@ -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
|