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,147 @@
|
|
1
|
+
module XRay
|
2
|
+
# AWS Services listed below will be recorded as subsegments
|
3
|
+
module AwsServices
|
4
|
+
# exausted list can be tracked at http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Seahorse/Client/Base.html
|
5
|
+
@whitelist = %I[
|
6
|
+
ACM
|
7
|
+
APIGateway
|
8
|
+
AlexaForBusiness
|
9
|
+
AppStream
|
10
|
+
AppSync
|
11
|
+
ApplicationAutoScaling
|
12
|
+
ApplicationDiscoveryService
|
13
|
+
Athena
|
14
|
+
AutoScaling
|
15
|
+
Batch
|
16
|
+
Budgets
|
17
|
+
Cloud9
|
18
|
+
CloudDirectory
|
19
|
+
CloudFormatioin
|
20
|
+
CloudFront
|
21
|
+
CloudHSM
|
22
|
+
CloudHSMV2
|
23
|
+
CloudSearch
|
24
|
+
CloudSearchDomain
|
25
|
+
CloudTrail
|
26
|
+
CloudWatch
|
27
|
+
CloudWatchEvents
|
28
|
+
CloudWatchLogs
|
29
|
+
CodeBuild
|
30
|
+
CodeCommit
|
31
|
+
CodeDeploy
|
32
|
+
CodePipeline
|
33
|
+
CodeStar
|
34
|
+
CognitoIdentity
|
35
|
+
CognitoIdentityProvider
|
36
|
+
CognitoSync
|
37
|
+
Comprehend
|
38
|
+
ConfigService
|
39
|
+
CostExplore
|
40
|
+
CostandUsageReportService
|
41
|
+
DAX
|
42
|
+
DataPipeline
|
43
|
+
DatabaseMigrationService
|
44
|
+
DeviceFarm
|
45
|
+
DirectConnect
|
46
|
+
DirectoryService
|
47
|
+
DynamoDB
|
48
|
+
DynamoDBStreams
|
49
|
+
EC2
|
50
|
+
ECR
|
51
|
+
ECS
|
52
|
+
EFS
|
53
|
+
EMR
|
54
|
+
ElastiCache
|
55
|
+
ElasticBeanstalk
|
56
|
+
ElasticLoadBalancing
|
57
|
+
ElasticLoadBalancingV2
|
58
|
+
ElasticTranscoder
|
59
|
+
ElasticsearchService
|
60
|
+
Firehost
|
61
|
+
GameLift
|
62
|
+
Glacier
|
63
|
+
Glue
|
64
|
+
Greengrass
|
65
|
+
GuardDuty
|
66
|
+
Health
|
67
|
+
IAM
|
68
|
+
ImportExport
|
69
|
+
Inspector
|
70
|
+
IoT
|
71
|
+
IoTDataPlane
|
72
|
+
IoTJobsDataPlane
|
73
|
+
KMS
|
74
|
+
Kinesis
|
75
|
+
KinesisAnalytics
|
76
|
+
KinesisVideo
|
77
|
+
KinesisVideoArchiveMedia
|
78
|
+
KinesisVideoMedia
|
79
|
+
Lambda
|
80
|
+
LambdaPreview
|
81
|
+
Lex
|
82
|
+
LexModelBuildingService
|
83
|
+
LexRuntimeService
|
84
|
+
Lightsail
|
85
|
+
MQ
|
86
|
+
MTurk
|
87
|
+
MachineLearning
|
88
|
+
MarketplaceCommerceAnalytics
|
89
|
+
MarketplaceEntitlementService
|
90
|
+
MarketplaceMetering
|
91
|
+
MediaConvert
|
92
|
+
MediaLive
|
93
|
+
MediaPackage
|
94
|
+
MediaStore
|
95
|
+
MediaStoreData
|
96
|
+
MigrationHub
|
97
|
+
Mobile
|
98
|
+
OpsWorks
|
99
|
+
OpsWorksCM
|
100
|
+
Organizations
|
101
|
+
Pinpoint
|
102
|
+
Polly
|
103
|
+
Pricing
|
104
|
+
RDS
|
105
|
+
Redshift
|
106
|
+
Rekognition
|
107
|
+
ResourceGroups
|
108
|
+
ResourceGroupsTaggingAPI
|
109
|
+
Route53
|
110
|
+
Route53Domains
|
111
|
+
S3
|
112
|
+
SES
|
113
|
+
SFN
|
114
|
+
SMS
|
115
|
+
SNS
|
116
|
+
SQS
|
117
|
+
SSM
|
118
|
+
STS
|
119
|
+
SWF
|
120
|
+
SageMaker
|
121
|
+
SageMakerRuntime
|
122
|
+
ServerlessApplicationRepository
|
123
|
+
ServiceCatalog
|
124
|
+
ServiceDiscovery
|
125
|
+
Shield
|
126
|
+
SimpleDB
|
127
|
+
Snowball
|
128
|
+
States
|
129
|
+
StorageGateway
|
130
|
+
Support
|
131
|
+
Translate
|
132
|
+
WAF
|
133
|
+
WAFRegional
|
134
|
+
WorkDocs
|
135
|
+
WorkSpaces
|
136
|
+
XRay
|
137
|
+
]
|
138
|
+
|
139
|
+
def self.whitelist
|
140
|
+
@whitelist
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.whitelist=(v)
|
144
|
+
@whitelist = v
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# Provide global logger for classes that include this module.
|
5
|
+
# It serves as a proxy to global recorder's logger.
|
6
|
+
module Logging
|
7
|
+
def logger
|
8
|
+
Logging.logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.logger
|
12
|
+
@logger ||= Logger.new($stdout).tap { |l| l.level = Logger::INFO }
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.logger=(v)
|
16
|
+
@logger = v
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'aws-xray-sdk/logger'
|
2
|
+
require 'aws-xray-sdk/exceptions'
|
3
|
+
|
4
|
+
module XRay
|
5
|
+
# Annotations are simple key-value pairs that are indexed for use with filter expressions.
|
6
|
+
# Use annotations to record data that you want to use to group traces in the console,
|
7
|
+
# or when calling the GetTraceSummaries API.
|
8
|
+
class Annotations
|
9
|
+
include Logging
|
10
|
+
|
11
|
+
def initialize(entity)
|
12
|
+
@entity = entity
|
13
|
+
@data = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
@data[key]
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [Symbol] k Only characters in `A-Za-z0-9_` are supported.
|
21
|
+
# @param v Only `Numeric`, `String` true/false is supported.
|
22
|
+
def []=(k, v)
|
23
|
+
raise EntityClosedError if @entity.closed?
|
24
|
+
if key_supported?(k) && value_supported?(v)
|
25
|
+
@data[k] = v
|
26
|
+
else
|
27
|
+
logger.warn %(Dropping annotation with key #{k} due to invalid characters.)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [Hash] h Update annotations with a single input hash.
|
32
|
+
def update(h)
|
33
|
+
raise EntityClosedError if @entity.closed?
|
34
|
+
filtered = filter_annotations(h)
|
35
|
+
@data.merge!(filtered)
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_h
|
39
|
+
sanitize_values(@data)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def filter_annotations(h)
|
45
|
+
h.delete_if do |k, v|
|
46
|
+
drop = !key_supported?(k) || !value_supported?(v)
|
47
|
+
logger.warn %(Dropping annotation with key #{k} due to invalid characters.) if drop
|
48
|
+
drop
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def sanitize_values(h)
|
53
|
+
h.each_pair do |k, v|
|
54
|
+
if v.is_a?(Float)
|
55
|
+
h[k] = v.to_s if v.nan? || v.infinite? == 1 || v.infinite? == -1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def key_supported?(k)
|
61
|
+
k.match(/[A-Za-z0-9_]+/)
|
62
|
+
end
|
63
|
+
|
64
|
+
def value_supported?(v)
|
65
|
+
case v
|
66
|
+
when Numeric
|
67
|
+
true
|
68
|
+
when true, false
|
69
|
+
true
|
70
|
+
else
|
71
|
+
v.is_a?(String)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Singleton facade annotations class doing no-op for performance
|
77
|
+
# in case of not sampled X-Ray entities.
|
78
|
+
module FacadeAnnotations
|
79
|
+
class << self
|
80
|
+
def [](key)
|
81
|
+
# no-op
|
82
|
+
end
|
83
|
+
|
84
|
+
def []=(k, v)
|
85
|
+
# no-op
|
86
|
+
end
|
87
|
+
|
88
|
+
def update(h)
|
89
|
+
# no-op
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_h
|
93
|
+
# no-op
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'oj'
|
2
|
+
|
3
|
+
module XRay
|
4
|
+
# Represents cause section in segment and subsegment document.
|
5
|
+
# It records information about application runtime exceptions.
|
6
|
+
class Cause
|
7
|
+
attr_reader :id
|
8
|
+
@@depth = 15
|
9
|
+
|
10
|
+
def initialize(exception: nil, id: nil, remote: false)
|
11
|
+
if exception
|
12
|
+
@exception_h = normalize e: exception, remote: remote
|
13
|
+
end
|
14
|
+
@id = id
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
return id if id
|
19
|
+
h = {
|
20
|
+
working_directory: Dir.pwd,
|
21
|
+
paths: Gem.paths.path,
|
22
|
+
exceptions: @exception_h
|
23
|
+
}
|
24
|
+
h
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_json
|
28
|
+
@to_json ||= begin
|
29
|
+
Oj.dump to_h, mode: :compat, use_as_json: true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def normalize(e:, remote: false)
|
36
|
+
exceptions = []
|
37
|
+
exceptions << normalize_exception(e: e, remote: remote)
|
38
|
+
|
39
|
+
# don't propagate remote flag
|
40
|
+
while e.cause
|
41
|
+
exceptions << normalize_exception(e: e.cause)
|
42
|
+
e = e.cause
|
43
|
+
end
|
44
|
+
|
45
|
+
exceptions
|
46
|
+
end
|
47
|
+
|
48
|
+
def normalize_exception(e:, remote: false)
|
49
|
+
h = {
|
50
|
+
message: e.to_s,
|
51
|
+
type: e.class.to_s
|
52
|
+
}
|
53
|
+
h[:remote] = true if remote
|
54
|
+
|
55
|
+
backtrace = e.backtrace_locations
|
56
|
+
return h unless backtrace
|
57
|
+
h[:stack] = backtrace.first(@@depth).collect do |t|
|
58
|
+
{
|
59
|
+
path: t.path,
|
60
|
+
line: t.lineno,
|
61
|
+
label: t.label
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
truncated = backtrace.size - @@depth
|
66
|
+
h[:truncated] = truncated if truncated > 0
|
67
|
+
h
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'aws-xray-sdk/model/segment'
|
2
|
+
require 'aws-xray-sdk/model/subsegment'
|
3
|
+
require 'aws-xray-sdk/model/annotations'
|
4
|
+
require 'aws-xray-sdk/model/metadata'
|
5
|
+
|
6
|
+
module XRay
|
7
|
+
# defines common no-op methods for dummy segments/subsegments
|
8
|
+
module DummyEntity
|
9
|
+
def sampled
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def annotations
|
14
|
+
FacadeAnnotations
|
15
|
+
end
|
16
|
+
|
17
|
+
def metadata(namespace: :default)
|
18
|
+
FacadeMetadata
|
19
|
+
end
|
20
|
+
|
21
|
+
def apply_status_code(status:)
|
22
|
+
# no-op
|
23
|
+
end
|
24
|
+
|
25
|
+
def merge_http_request(request:)
|
26
|
+
# no-op
|
27
|
+
end
|
28
|
+
|
29
|
+
def merge_http_response(response:)
|
30
|
+
# no-op
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_exception(exception:, remote: false)
|
34
|
+
# no-op
|
35
|
+
end
|
36
|
+
|
37
|
+
def aws=(v)
|
38
|
+
# no-op
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_h
|
42
|
+
# no-op
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_json
|
46
|
+
# no-op
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# A dummy segment is created when ``xray_recorder`` decides to not sample
|
51
|
+
# the segment based on sampling decisions.
|
52
|
+
# Adding data to a dummy segment becomes a no-op except for
|
53
|
+
# subsegments. This is to reduce the memory footprint of the SDK.
|
54
|
+
# A dummy segment will not be sent to the X-Ray daemon by the default emitter.
|
55
|
+
# Manually create dummy segments is not recommended.
|
56
|
+
class DummySegment < Segment
|
57
|
+
include DummyEntity
|
58
|
+
end
|
59
|
+
|
60
|
+
# A dummy subsegment will be created when ``xray_recorder`` tries
|
61
|
+
# to create a subsegment under a not sampled segment. Adding data
|
62
|
+
# to a dummy subsegment becomes no-op except for child subsegments.
|
63
|
+
# Dummy subsegment will not be sent to the X-Ray daemon by the default emitter.
|
64
|
+
# Manually create dummy subsegments is not recommended.
|
65
|
+
class DummySubsegment < Subsegment
|
66
|
+
include DummyEntity
|
67
|
+
|
68
|
+
def sql=(v)
|
69
|
+
# no-op
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'oj'
|
4
|
+
require 'aws-xray-sdk/exceptions'
|
5
|
+
require 'aws-xray-sdk/model/cause'
|
6
|
+
require 'aws-xray-sdk/model/annotations'
|
7
|
+
require 'aws-xray-sdk/model/metadata'
|
8
|
+
|
9
|
+
module XRay
|
10
|
+
# This module contains common properties and methods
|
11
|
+
# used by segment and subsegment class.
|
12
|
+
module Entity
|
13
|
+
attr_reader :name, :exception, :cause, :namespace,
|
14
|
+
:http_request, :http_response
|
15
|
+
attr_accessor :parent, :throttle, :error, :fault, :sampled, :aws,
|
16
|
+
:start_time, :end_time
|
17
|
+
|
18
|
+
HTTP_REQUEST_KEY = %I[url method user_agent client_ip x_forwarded_for].freeze
|
19
|
+
HTTP_RESPONSE_KEY = %I[status content_length].freeze
|
20
|
+
|
21
|
+
# Generates a random 8-digit hex number as the entity id and returns it.
|
22
|
+
def id
|
23
|
+
@id ||= begin
|
24
|
+
SecureRandom.hex(8)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def closed?
|
29
|
+
@closed ||= false
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [Float] end_time End time on epoch.
|
33
|
+
def close(end_time: nil)
|
34
|
+
raise EntityClosedError if closed?
|
35
|
+
@end_time = end_time || Time.now.to_f
|
36
|
+
@closed = true
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Array] The children subsegments of this entity.
|
40
|
+
def subsegments
|
41
|
+
@subsegments ||= []
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [Subsegment] subsegment Append the provided subsegment to children subsegments.
|
45
|
+
def add_subsegment(subsegment:)
|
46
|
+
raise EntityClosedError if closed?
|
47
|
+
subsegment.sampled = sampled
|
48
|
+
subsegment.parent = self
|
49
|
+
subsegments << subsegment
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
# @param [Subsegment] subsegment Remove the provided subsegment from children subsegments.
|
54
|
+
# @return [Subsegment] The deleted subsegment if the deletion is successful.
|
55
|
+
def remove_subsegment(subsegment:)
|
56
|
+
subsegments.delete(subsegment)
|
57
|
+
subsegment
|
58
|
+
end
|
59
|
+
|
60
|
+
def annotations
|
61
|
+
@annotations ||= Annotations.new(self)
|
62
|
+
end
|
63
|
+
|
64
|
+
def metadata(namespace: :default)
|
65
|
+
@metadata ||= Metadata.new(self)
|
66
|
+
@metadata.sub_meta(namespace)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Set error/fault/throttle flags based on http status code.
|
70
|
+
# This method is idempotent.
|
71
|
+
# @param [Integer] status
|
72
|
+
def apply_status_code(status:)
|
73
|
+
raise EntityClosedError if closed?
|
74
|
+
case status.to_i
|
75
|
+
when 429
|
76
|
+
@throttle = true
|
77
|
+
@error = true
|
78
|
+
@fault = false
|
79
|
+
when 400..499
|
80
|
+
@error = true
|
81
|
+
@throttle = false
|
82
|
+
@fault = false
|
83
|
+
when 500..599
|
84
|
+
@fault = true
|
85
|
+
@error = false
|
86
|
+
@throttle = false
|
87
|
+
end
|
88
|
+
|
89
|
+
@http_response ||= {}
|
90
|
+
@http_response[:status] = status.to_i
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param [Hash] request Supported keys are `:url`, `:user_agent`, `:client_ip`,
|
94
|
+
# `:x_forwarded_for`, `:method`. Value can be one of
|
95
|
+
# String or Integer or Boolean types depend on the key.
|
96
|
+
def merge_http_request(request:)
|
97
|
+
raise EntityClosedError if closed?
|
98
|
+
request.delete_if { |k| !HTTP_REQUEST_KEY.include?(k) }
|
99
|
+
@http_request ||= {}
|
100
|
+
@http_request.merge!(request)
|
101
|
+
end
|
102
|
+
|
103
|
+
# @param [Hash] response Supported keys are `:status`, `:content_length`.
|
104
|
+
# Value can be one of String or Integer types depend on the key.
|
105
|
+
def merge_http_response(response:)
|
106
|
+
raise EntityClosedError if closed?
|
107
|
+
response.delete_if { |k| !HTTP_RESPONSE_KEY.include?(k) }
|
108
|
+
@http_response ||= {}
|
109
|
+
@http_response.merge!(response)
|
110
|
+
apply_status_code status: response[:status] if response.key?(:status)
|
111
|
+
end
|
112
|
+
|
113
|
+
# @param [Exception] exception The exception object to capture.
|
114
|
+
# @param remote A boolean flag indicates whether the exception is
|
115
|
+
# returned from the downstream service.
|
116
|
+
def add_exception(exception:, remote: false)
|
117
|
+
raise EntityClosedError if closed?
|
118
|
+
@fault = true
|
119
|
+
@exception = exception
|
120
|
+
if cause_id = find_root_cause(exception)
|
121
|
+
@cause = Cause.new id: cause_id
|
122
|
+
else
|
123
|
+
@cause = Cause.new exception: exception, remote: remote
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# @return [String] Cause id is the id of the subsegment where
|
128
|
+
# the exception originally comes from.
|
129
|
+
def cause_id
|
130
|
+
return @cause.id if @cause
|
131
|
+
end
|
132
|
+
|
133
|
+
# @return [Hash] The hash that contains all attributes that will
|
134
|
+
# be later serialized and sent out.
|
135
|
+
def to_h
|
136
|
+
h = {
|
137
|
+
name: name,
|
138
|
+
id: id,
|
139
|
+
start_time: start_time
|
140
|
+
}
|
141
|
+
if closed?
|
142
|
+
h[:end_time] = end_time
|
143
|
+
else
|
144
|
+
h[:in_progress] = true
|
145
|
+
end
|
146
|
+
h[:subsegments] = subsegments unless subsegments.empty?
|
147
|
+
h[:aws] = aws if aws
|
148
|
+
if http_request || http_response
|
149
|
+
h[:http] = {}
|
150
|
+
h[:http][:request] = http_request if http_request
|
151
|
+
h[:http][:response] = http_response if http_response
|
152
|
+
end
|
153
|
+
if (a = annotations.to_h) && !a.empty?
|
154
|
+
h[:annotations] = a
|
155
|
+
end
|
156
|
+
if (m = @metadata) && !m.to_h.empty?
|
157
|
+
h[:metadata] = m.to_h
|
158
|
+
end
|
159
|
+
|
160
|
+
h[:parent_id] = parent.id if parent
|
161
|
+
# make sure the value in hash can only be boolean true
|
162
|
+
h[:fault] = !!fault if fault
|
163
|
+
h[:error] = !!error if error
|
164
|
+
h[:throttle] = !!throttle if throttle
|
165
|
+
h[:cause] = cause.to_h if cause
|
166
|
+
h
|
167
|
+
end
|
168
|
+
|
169
|
+
def to_json
|
170
|
+
@to_json ||= begin
|
171
|
+
Oj.dump to_h, mode: :compat, use_as_json: true
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def find_root_cause(e)
|
178
|
+
subsegment = subsegments.find { |i| i.exception.hash == e.hash }
|
179
|
+
return nil unless subsegment
|
180
|
+
if cause_id = subsegment.cause_id
|
181
|
+
cause_id
|
182
|
+
else
|
183
|
+
subsegment.id
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|