atatus 1.7.0 → 2.0.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/CHANGELOG.md +5 -0
- data/Gemfile +49 -13
- data/LICENSE +1 -1
- data/atatus.gemspec +3 -3
- data/lib/atatus/agent.rb +10 -7
- data/lib/atatus/central_config.rb +19 -8
- data/lib/atatus/collector/layer.rb +1 -1
- data/lib/atatus/{sql_summarizer.rb → config/log_level_map.rb} +22 -28
- data/lib/atatus/config/options.rb +2 -1
- data/lib/atatus/config/regexp_list.rb +1 -1
- data/lib/atatus/config/round_float.rb +31 -0
- data/lib/atatus/config/server_info.rb +50 -0
- data/lib/atatus/config/wildcard_pattern_list.rb +3 -1
- data/lib/atatus/config.rb +91 -70
- data/lib/atatus/context/request/socket.rb +1 -2
- data/lib/atatus/context/response.rb +1 -3
- data/lib/atatus/context.rb +3 -10
- data/lib/atatus/context_builder.rb +3 -3
- data/lib/atatus/error.rb +2 -1
- data/lib/atatus/error_builder.rb +1 -1
- data/lib/atatus/fields.rb +98 -0
- data/lib/atatus/graphql.rb +2 -0
- data/lib/atatus/grpc.rb +5 -7
- data/lib/atatus/instrumenter.rb +29 -25
- data/lib/atatus/metadata/cloud_info.rb +156 -0
- data/lib/atatus/metadata/service_info.rb +3 -3
- data/lib/atatus/metadata/system_info/container_info.rb +20 -8
- data/lib/atatus/metadata/system_info.rb +20 -5
- data/lib/atatus/metadata.rb +3 -1
- data/lib/atatus/metrics/cpu_mem_set.rb +10 -38
- data/lib/atatus/metrics/jvm_set.rb +88 -0
- data/lib/atatus/metrics/metric.rb +2 -0
- data/lib/atatus/metrics.rb +33 -16
- data/lib/atatus/middleware.rb +8 -3
- data/lib/atatus/naively_hashable.rb +1 -0
- data/lib/atatus/normalizers/rails/active_record.rb +25 -7
- data/lib/atatus/normalizers.rb +2 -2
- data/lib/atatus/opentracing.rb +5 -3
- data/lib/atatus/rails.rb +1 -1
- data/lib/atatus/span/context/db.rb +1 -1
- data/lib/atatus/span/context/destination.rb +58 -32
- data/lib/atatus/span/context/http.rb +2 -0
- data/lib/atatus/span/context/links.rb +32 -0
- data/lib/atatus/{sql.rb → span/context/message.rb} +16 -12
- data/lib/atatus/span/context/service.rb +55 -0
- data/lib/atatus/span/context.rb +28 -3
- data/lib/atatus/span.rb +35 -5
- data/lib/atatus/span_helpers.rb +12 -23
- data/lib/atatus/spies/action_dispatch.rb +10 -13
- data/lib/atatus/spies/azure_storage_table.rb +148 -0
- data/lib/atatus/spies/delayed_job.rb +19 -13
- data/lib/atatus/spies/dynamo_db.rb +56 -15
- data/lib/atatus/spies/elasticsearch.rb +54 -39
- data/lib/atatus/spies/faraday.rb +92 -58
- data/lib/atatus/spies/http.rb +33 -37
- data/lib/atatus/spies/json.rb +5 -9
- data/lib/atatus/spies/mongo.rb +26 -19
- data/lib/atatus/spies/net_http.rb +53 -51
- data/lib/atatus/spies/racecar.rb +77 -0
- data/lib/atatus/spies/rake.rb +27 -27
- data/lib/atatus/spies/redis.rb +11 -12
- data/lib/atatus/spies/resque.rb +18 -23
- data/lib/atatus/spies/s3.rb +132 -0
- data/lib/atatus/spies/sequel.rb +11 -2
- data/lib/atatus/spies/shoryuken.rb +4 -6
- data/lib/atatus/spies/sidekiq.rb +23 -31
- data/lib/atatus/spies/sinatra.rb +20 -28
- data/lib/atatus/spies/sneakers.rb +2 -0
- data/lib/atatus/spies/sns.rb +126 -0
- data/lib/atatus/spies/sqs.rb +231 -0
- data/lib/atatus/spies/sucker_punch.rb +20 -22
- data/lib/atatus/spies/tilt.rb +10 -13
- data/lib/atatus/spies.rb +20 -0
- data/lib/atatus/sql/signature.rb +4 -2
- data/lib/atatus/sql/tokenizer.rb +23 -7
- data/lib/atatus/stacktrace/frame.rb +1 -0
- data/lib/atatus/stacktrace_builder.rb +12 -16
- data/lib/atatus/subscriber.rb +1 -0
- data/lib/atatus/trace_context/traceparent.rb +5 -8
- data/lib/atatus/trace_context/tracestate.rb +16 -14
- data/lib/atatus/trace_context.rb +6 -16
- data/lib/atatus/transaction.rb +17 -4
- data/lib/atatus/transport/base.rb +1 -3
- data/lib/atatus/transport/connection/http.rb +11 -3
- data/lib/atatus/transport/connection/proxy_pipe.rb +1 -2
- data/lib/atatus/transport/connection.rb +3 -2
- data/lib/atatus/transport/filters/hash_sanitizer.rb +16 -34
- data/lib/atatus/transport/filters/secrets_filter.rb +35 -12
- data/lib/atatus/transport/serializers/context_serializer.rb +1 -2
- data/lib/atatus/transport/serializers/metadata_serializer.rb +54 -8
- data/lib/atatus/transport/serializers/metricset_serializer.rb +2 -2
- data/lib/atatus/transport/serializers/span_serializer.rb +55 -9
- data/lib/atatus/transport/serializers/transaction_serializer.rb +1 -0
- data/lib/atatus/transport/serializers.rb +9 -6
- data/lib/atatus/transport/user_agent.rb +16 -9
- data/lib/atatus/transport/worker.rb +2 -1
- data/lib/atatus/util/deep_dup.rb +65 -0
- data/lib/atatus/util/precision_validator.rb +46 -0
- data/lib/atatus/util.rb +2 -0
- data/lib/atatus/version.rb +1 -1
- data/lib/atatus.rb +32 -5
- metadata +40 -11
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Licensed to Elasticsearch B.V. under one or more contributor
|
|
2
|
+
# license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright
|
|
4
|
+
# ownership. Elasticsearch B.V. licenses this file to you under
|
|
5
|
+
# the Apache License, Version 2.0 (the "License"); you may
|
|
6
|
+
# not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing,
|
|
12
|
+
# software distributed under the License is distributed on an
|
|
13
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
14
|
+
# KIND, either express or implied. See the License for the
|
|
15
|
+
# specific language governing permissions and limitations
|
|
16
|
+
# under the License.
|
|
17
|
+
#
|
|
18
|
+
# frozen_string_literal: true
|
|
19
|
+
|
|
20
|
+
module Atatus
|
|
21
|
+
# @api private
|
|
22
|
+
module Spies
|
|
23
|
+
# @api private
|
|
24
|
+
class AzureStorageTableSpy
|
|
25
|
+
TYPE = "storage"
|
|
26
|
+
SUBTYPE = "azuretable"
|
|
27
|
+
|
|
28
|
+
module Helpers
|
|
29
|
+
class << self
|
|
30
|
+
def instrument(operation_name, table_name = nil, service:)
|
|
31
|
+
span_name = span_name(operation_name, table_name)
|
|
32
|
+
action = formatted_op_name(operation_name)
|
|
33
|
+
account_name = account_name_from_storage_table_host(service.storage_service_host[:primary])
|
|
34
|
+
|
|
35
|
+
destination = Atatus::Span::Context::Destination.from_uri(service.storage_service_host[:primary])
|
|
36
|
+
destination.service.resource = "#{SUBTYPE}/#{account_name}"
|
|
37
|
+
|
|
38
|
+
context = Atatus::Span::Context.new(destination: destination)
|
|
39
|
+
|
|
40
|
+
Atatus.with_span(span_name, TYPE, subtype: SUBTYPE, action: action, context: context) do
|
|
41
|
+
Atatus::Spies.without_faraday do
|
|
42
|
+
Atatus::Spies.without_net_http do
|
|
43
|
+
yield
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
DEFAULT_OP_NAMES = {
|
|
52
|
+
"create_table" => "Create",
|
|
53
|
+
"delete_table" => "Delete",
|
|
54
|
+
"get_table_acl" => "GetAcl",
|
|
55
|
+
"set_table_acl" => "SetAcl",
|
|
56
|
+
"insert_entity" => "Insert",
|
|
57
|
+
"query_entities" => "Query",
|
|
58
|
+
"update_entity" => "Update",
|
|
59
|
+
"merge_entity" => "Merge",
|
|
60
|
+
"delete_entity" => "Delete"
|
|
61
|
+
}.freeze
|
|
62
|
+
|
|
63
|
+
def formatted_op_names
|
|
64
|
+
@formatted_op_names ||= Concurrent::Map.new
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def account_names
|
|
68
|
+
@account_names ||= Concurrent::Map.new
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def span_name(operation_name, table_name = nil)
|
|
72
|
+
base = "AzureTable #{formatted_op_name(operation_name)}"
|
|
73
|
+
|
|
74
|
+
return base unless table_name
|
|
75
|
+
|
|
76
|
+
"#{base} #{table_name}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def formatted_op_name(operation_name)
|
|
80
|
+
formatted_op_names.compute_if_absent(operation_name) do
|
|
81
|
+
DEFAULT_OP_NAMES.fetch(operation_name) do
|
|
82
|
+
operation_name.to_s.split("_").collect(&:capitalize).join
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def account_name_from_storage_table_host(host)
|
|
88
|
+
account_names.compute_if_absent(host) do
|
|
89
|
+
URI(host).host.split(".").first || "unknown"
|
|
90
|
+
end
|
|
91
|
+
rescue Exception
|
|
92
|
+
"unknown"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# @api private
|
|
98
|
+
module Ext
|
|
99
|
+
# Methods with table_name as first parameter
|
|
100
|
+
%i[
|
|
101
|
+
create_table
|
|
102
|
+
delete_table
|
|
103
|
+
get_table
|
|
104
|
+
get_table_acl
|
|
105
|
+
set_table_acl
|
|
106
|
+
insert_entity
|
|
107
|
+
query_entities
|
|
108
|
+
update_entity
|
|
109
|
+
merge_entity
|
|
110
|
+
delete_entity
|
|
111
|
+
].each do |method_name|
|
|
112
|
+
define_method(method_name) do |table_name, *args|
|
|
113
|
+
unless (transaction = Atatus.current_transaction)
|
|
114
|
+
return super(table_name, *args)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
Atatus::Spies::AzureStorageTableSpy::Helpers.instrument(
|
|
118
|
+
method_name.to_s, table_name, service: self
|
|
119
|
+
) do
|
|
120
|
+
super(table_name, *args)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Methods WITHOUT table_name as first parameter
|
|
126
|
+
def query_tables(*args)
|
|
127
|
+
unless (transaction = Atatus.current_transaction)
|
|
128
|
+
return super(*args)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
Atatus::Spies::AzureStorageTableSpy::Helpers.instrument("query_tables", service: self) do
|
|
132
|
+
super(*args)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def install
|
|
138
|
+
::Azure::Storage::Table::TableService.prepend(Ext)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
register(
|
|
143
|
+
"Azure::Storage::Table::TableService",
|
|
144
|
+
"azure/storage/table",
|
|
145
|
+
AzureStorageTableSpy.new
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -27,39 +27,45 @@ module Atatus
|
|
|
27
27
|
TYPE = 'Delayed::Job'
|
|
28
28
|
|
|
29
29
|
def install
|
|
30
|
-
|
|
30
|
+
::Delayed::Backend::Base.class_eval do
|
|
31
|
+
alias invoke_job_without_apm invoke_job
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def invoke_job(*args, &block)
|
|
36
|
-
::Atatus::Spies::DelayedJobSpy
|
|
37
|
-
.invoke_job(self, *args, &block)
|
|
38
|
-
end
|
|
33
|
+
def invoke_job(*args, &block)
|
|
34
|
+
::Atatus::Spies::DelayedJobSpy
|
|
35
|
+
.invoke_job(self, *args, &block)
|
|
39
36
|
end
|
|
40
|
-
|
|
41
37
|
end
|
|
42
38
|
end
|
|
43
39
|
|
|
44
40
|
def self.invoke_job(job, *args, &block)
|
|
45
|
-
job_name =
|
|
41
|
+
job_name = job_name(job)
|
|
46
42
|
transaction = Atatus.start_transaction(job_name, TYPE)
|
|
47
43
|
job.invoke_job_without_apm(*args, &block)
|
|
48
|
-
transaction
|
|
44
|
+
transaction&.done 'success'
|
|
45
|
+
transaction&.outcome = Transaction::Outcome::SUCCESS
|
|
49
46
|
rescue ::Exception => e
|
|
50
47
|
Atatus.report(e, handled: false)
|
|
51
|
-
transaction
|
|
48
|
+
transaction&.done 'error'
|
|
49
|
+
transaction&.outcome = Transaction::Outcome::FAILURE
|
|
52
50
|
raise
|
|
53
51
|
ensure
|
|
54
52
|
Atatus.end_transaction
|
|
55
53
|
end
|
|
56
54
|
|
|
57
|
-
def self.
|
|
55
|
+
def self.job_name(job)
|
|
56
|
+
payload_object = job.payload_object
|
|
57
|
+
|
|
58
58
|
if payload_object.is_a?(::Delayed::PerformableMethod)
|
|
59
59
|
performable_method_name(payload_object)
|
|
60
|
+
elsif payload_object.instance_of?(
|
|
61
|
+
ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper
|
|
62
|
+
)
|
|
63
|
+
payload_object.job_data['job_class']
|
|
60
64
|
else
|
|
61
65
|
payload_object.class.name
|
|
62
66
|
end
|
|
67
|
+
rescue
|
|
68
|
+
job.name
|
|
63
69
|
end
|
|
64
70
|
|
|
65
71
|
def self.performable_method_name(payload_object)
|
|
@@ -22,35 +22,76 @@ module Atatus
|
|
|
22
22
|
module Spies
|
|
23
23
|
# @api private
|
|
24
24
|
class DynamoDBSpy
|
|
25
|
+
TYPE = 'db'
|
|
26
|
+
SUBTYPE = 'dynamodb'
|
|
27
|
+
ACTION = 'query'
|
|
28
|
+
|
|
29
|
+
@@formatted_op_names = Concurrent::Map.new
|
|
30
|
+
|
|
25
31
|
def self.without_net_http
|
|
26
32
|
return yield unless defined?(NetHTTPSpy)
|
|
27
33
|
|
|
34
|
+
# rubocop:disable Style/ExplicitBlockArgument
|
|
28
35
|
Atatus::Spies::NetHTTPSpy.disable_in do
|
|
29
36
|
yield
|
|
30
37
|
end
|
|
38
|
+
# rubocop:enable Style/ExplicitBlockArgument
|
|
31
39
|
end
|
|
32
40
|
|
|
33
|
-
def
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
def self.span_name(operation_name, params)
|
|
42
|
+
params[:table_name] ?
|
|
43
|
+
"DynamoDB #{formatted_op_name(operation_name)} #{params[:table_name]}" :
|
|
44
|
+
"DynamoDB #{formatted_op_name(operation_name)}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.formatted_op_name(operation_name)
|
|
48
|
+
@@formatted_op_names.compute_if_absent(operation_name) do
|
|
49
|
+
operation_name.to_s.split('_').collect(&:capitalize).join
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @api private
|
|
54
|
+
module Ext
|
|
55
|
+
def self.prepended(mod)
|
|
56
|
+
# Alias all available operations
|
|
57
|
+
mod.api.operation_names.each do |operation_name|
|
|
58
|
+
define_method(operation_name) do |params = {}, options = {}|
|
|
59
|
+
context = Atatus::Span::Context.new(
|
|
60
|
+
db: {
|
|
61
|
+
instance: config.region,
|
|
62
|
+
type: SUBTYPE,
|
|
63
|
+
statement: params[:key_condition_expression]
|
|
64
|
+
},
|
|
65
|
+
destination: {
|
|
66
|
+
address: config.endpoint.host,
|
|
67
|
+
port: config.endpoint.port,
|
|
68
|
+
service: {
|
|
69
|
+
name: SUBTYPE,
|
|
70
|
+
type: TYPE,
|
|
71
|
+
resource: SUBTYPE },
|
|
72
|
+
cloud: { region: config.region }
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
Atatus.with_span(
|
|
77
|
+
Atatus::Spies::DynamoDBSpy.span_name(operation_name, params),
|
|
78
|
+
TYPE,
|
|
79
|
+
subtype: SUBTYPE,
|
|
80
|
+
action: ACTION,
|
|
81
|
+
context: context
|
|
82
|
+
) do
|
|
83
|
+
Atatus::Spies::DynamoDBSpy.without_net_http do
|
|
84
|
+
super(params, options)
|
|
47
85
|
end
|
|
48
86
|
end
|
|
49
87
|
end
|
|
50
88
|
end
|
|
51
|
-
|
|
52
89
|
end
|
|
53
90
|
end
|
|
91
|
+
|
|
92
|
+
def install
|
|
93
|
+
::Aws::DynamoDB::Client.prepend(Ext)
|
|
94
|
+
end
|
|
54
95
|
end
|
|
55
96
|
|
|
56
97
|
register(
|
|
@@ -27,53 +27,62 @@ module Atatus
|
|
|
27
27
|
SUBTYPE = 'elasticsearch'
|
|
28
28
|
|
|
29
29
|
def self.sanitizer
|
|
30
|
-
@sanitizer ||=
|
|
30
|
+
@sanitizer ||=
|
|
31
|
+
begin
|
|
32
|
+
config = Atatus.agent.config
|
|
33
|
+
Atatus::Transport::Filters::HashSanitizer.new(
|
|
34
|
+
key_patterns: config.custom_key_filters +
|
|
35
|
+
config.sanitize_field_names
|
|
36
|
+
)
|
|
37
|
+
end
|
|
31
38
|
end
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
alias perform_request_without_apm perform_request
|
|
40
|
-
|
|
41
|
-
def perform_request(method, path, *args, &block)
|
|
42
|
-
unless Atatus.current_transaction
|
|
43
|
-
return perform_request_without_apm(method, path, *args, &block)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
name = format(NAME_FORMAT, method, path)
|
|
47
|
-
statement = []
|
|
48
|
-
|
|
49
|
-
statement << { params: args&.[](0) }
|
|
40
|
+
# @api private
|
|
41
|
+
module Ext
|
|
42
|
+
def perform_request(method, path, *args, &block)
|
|
43
|
+
unless Atatus.current_transaction
|
|
44
|
+
return super(method, path, *args, &block)
|
|
45
|
+
end
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
statement << {
|
|
54
|
-
body: Atatus::Spies::ElasticsearchSpy.sanitizer.strip_from!(args[1])
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
end
|
|
47
|
+
name = format(NAME_FORMAT, method, path)
|
|
48
|
+
statement = []
|
|
58
49
|
|
|
59
|
-
|
|
60
|
-
db: { statement: statement.reduce({}, :merge).to_json },
|
|
61
|
-
destination: {
|
|
62
|
-
name: SUBTYPE,
|
|
63
|
-
resource: SUBTYPE,
|
|
64
|
-
type: TYPE
|
|
65
|
-
}
|
|
66
|
-
)
|
|
50
|
+
statement << { params: args&.[](0) }
|
|
67
51
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
52
|
+
if Atatus.agent.config.capture_elasticsearch_queries
|
|
53
|
+
unless args[1].nil? || args[1].empty?
|
|
54
|
+
body =
|
|
55
|
+
Atatus::Spies::ElasticsearchSpy
|
|
56
|
+
.sanitizer.strip_from(args[1])
|
|
57
|
+
statement << { body: body }
|
|
74
58
|
end
|
|
75
59
|
end
|
|
76
60
|
|
|
61
|
+
context = Span::Context.new(
|
|
62
|
+
db: { statement: statement.reduce({}, :merge).to_json },
|
|
63
|
+
destination: {
|
|
64
|
+
service: {
|
|
65
|
+
name: SUBTYPE,
|
|
66
|
+
resource: SUBTYPE,
|
|
67
|
+
type: TYPE
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
Atatus.with_span(
|
|
73
|
+
name,
|
|
74
|
+
TYPE,
|
|
75
|
+
subtype: SUBTYPE,
|
|
76
|
+
context: context
|
|
77
|
+
) { super(method, path, *args, &block) }
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def install
|
|
82
|
+
if defined?(::Elastic::Transport::Client)
|
|
83
|
+
::Elastic::Transport::Client.prepend(Ext)
|
|
84
|
+
elsif defined?(::Elasticsearch::Transport::Client)
|
|
85
|
+
::Elasticsearch::Transport::Client.prepend(Ext)
|
|
77
86
|
end
|
|
78
87
|
end
|
|
79
88
|
end
|
|
@@ -83,5 +92,11 @@ module Atatus
|
|
|
83
92
|
'elasticsearch-transport',
|
|
84
93
|
ElasticsearchSpy.new
|
|
85
94
|
)
|
|
95
|
+
|
|
96
|
+
register(
|
|
97
|
+
'Elastic::Transport::Client',
|
|
98
|
+
'elastic-transport',
|
|
99
|
+
ElasticsearchSpy.new
|
|
100
|
+
)
|
|
86
101
|
end
|
|
87
102
|
end
|
data/lib/atatus/spies/faraday.rb
CHANGED
|
@@ -22,84 +22,118 @@ module Atatus
|
|
|
22
22
|
module Spies
|
|
23
23
|
# @api private
|
|
24
24
|
class FaradaySpy
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
DISABLE_KEY = :__atatus_faraday_disabled
|
|
26
|
+
TYPE = 'external'
|
|
27
|
+
SUBTYPE = 'http'
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Atatus::Spies::NetHTTPSpy.disable_in do
|
|
32
|
-
yield
|
|
29
|
+
class << self
|
|
30
|
+
def disabled=(disabled)
|
|
31
|
+
Thread.current[DISABLE_KEY] = disabled
|
|
33
32
|
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
37
|
-
def install
|
|
38
|
-
if defined?(::Faraday) && defined?(::Faraday::Connection)
|
|
39
33
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def run_request(method, url, body, headers, &block)
|
|
44
|
-
unless (transaction = Atatus.current_transaction)
|
|
45
|
-
return run_request_without_apm(method, url, body, headers, &block)
|
|
46
|
-
end
|
|
34
|
+
def disabled?
|
|
35
|
+
Thread.current[DISABLE_KEY] ||= false
|
|
36
|
+
end
|
|
47
37
|
|
|
48
|
-
|
|
38
|
+
def disable_in
|
|
39
|
+
self.disabled = true
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
end
|
|
58
|
-
uri = URI(tmp_request.path)
|
|
59
|
-
end
|
|
41
|
+
begin
|
|
42
|
+
yield
|
|
43
|
+
ensure
|
|
44
|
+
self.disabled = false
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
60
48
|
|
|
61
|
-
|
|
49
|
+
# @api private
|
|
50
|
+
module Ext
|
|
51
|
+
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
52
|
+
def run_request(method, url, body, headers, &block)
|
|
53
|
+
unless (transaction = Atatus.current_transaction)
|
|
54
|
+
return super(method, url, body, headers, &block)
|
|
55
|
+
end
|
|
62
56
|
|
|
63
|
-
|
|
57
|
+
if Atatus::Spies::FaradaySpy.disabled?
|
|
58
|
+
return super(method, url, body, headers, &block)
|
|
59
|
+
end
|
|
64
60
|
|
|
65
|
-
|
|
61
|
+
uri = URI(build_url(url))
|
|
66
62
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
63
|
+
# If url is set inside block it isn't available until yield,
|
|
64
|
+
# so we temporarily build the request to yield. This could be a
|
|
65
|
+
# problem if the block has side effects as it will be yielded twice
|
|
66
|
+
# ~mikker
|
|
67
|
+
unless uri.host
|
|
68
|
+
tmp_request = build_request(method) do |req|
|
|
69
|
+
yield(req) if block_given?
|
|
70
|
+
end
|
|
71
|
+
uri = tmp_request.path && URI(tmp_request.path)
|
|
72
|
+
end
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
"#{upcased_method} #{host}",
|
|
75
|
-
TYPE,
|
|
76
|
-
subtype: SUBTYPE,
|
|
77
|
-
action: upcased_method,
|
|
78
|
-
context: context
|
|
79
|
-
) do |span|
|
|
80
|
-
Atatus::Spies::FaradaySpy.without_net_http do
|
|
81
|
-
trace_context = span&.trace_context || transaction.trace_context
|
|
74
|
+
host = uri&.host || 'localhost'
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
run_request_without_apm(method, url, body, headers) do |req|
|
|
85
|
-
trace_context.apply_headers { |k, v| req[k] = v }
|
|
76
|
+
upcased_method = method.to_s.upcase
|
|
86
77
|
|
|
87
|
-
|
|
88
|
-
|
|
78
|
+
if uri
|
|
79
|
+
destination = Atatus::Span::Context::Destination.from_uri(uri, type: SUBTYPE)
|
|
89
80
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
context =
|
|
82
|
+
Atatus::Span::Context.new(
|
|
83
|
+
http: { url: uri, method: upcased_method },
|
|
84
|
+
destination: destination
|
|
85
|
+
)
|
|
86
|
+
else
|
|
87
|
+
context =
|
|
88
|
+
Atatus::Span::Context.new(http: { url: uri, method: upcased_method })
|
|
89
|
+
end
|
|
93
90
|
|
|
94
|
-
|
|
91
|
+
context =
|
|
92
|
+
Atatus::Span::Context.new(
|
|
93
|
+
http: { url: uri, method: upcased_method },
|
|
94
|
+
destination: destination
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
Atatus.with_span(
|
|
98
|
+
"#{upcased_method} #{host}",
|
|
99
|
+
TYPE,
|
|
100
|
+
subtype: SUBTYPE,
|
|
101
|
+
context: context
|
|
102
|
+
) do |span|
|
|
103
|
+
Atatus::Spies.without_net_http do
|
|
104
|
+
trace_context = span&.trace_context || transaction.trace_context
|
|
105
|
+
|
|
106
|
+
begin
|
|
107
|
+
result = super(method, url, body, headers) do |req|
|
|
108
|
+
trace_context.apply_headers { |k, v| req[k] = v }
|
|
109
|
+
yield req if block
|
|
110
|
+
end
|
|
111
|
+
rescue Faraday::ClientError, Faraday::ServerError => e # Faraday::Response::RaiseError
|
|
112
|
+
status = e.response_status if e.respond_to?(:response_status)
|
|
113
|
+
status ||= e.response&.fetch(:status)
|
|
114
|
+
http = span&.context&.http
|
|
115
|
+
if http && status
|
|
116
|
+
http.status_code = status.to_s
|
|
117
|
+
span.outcome = Span::Outcome.from_http_status(status)
|
|
95
118
|
end
|
|
119
|
+
raise e
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
if (http = span&.context&.http)
|
|
123
|
+
http.status_code = result.status.to_s
|
|
96
124
|
end
|
|
125
|
+
|
|
126
|
+
span&.outcome = Span::Outcome.from_http_status(result.status)
|
|
127
|
+
result
|
|
97
128
|
end
|
|
98
129
|
end
|
|
99
|
-
|
|
100
130
|
end
|
|
101
131
|
end
|
|
102
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
132
|
+
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
|
133
|
+
|
|
134
|
+
def install
|
|
135
|
+
::Faraday::Connection.prepend(Ext)
|
|
136
|
+
end
|
|
103
137
|
end
|
|
104
138
|
|
|
105
139
|
register 'Faraday', 'faraday', FaradaySpy.new
|
data/lib/atatus/spies/http.rb
CHANGED
|
@@ -22,54 +22,50 @@ module Atatus
|
|
|
22
22
|
module Spies
|
|
23
23
|
# @api private
|
|
24
24
|
class HTTPSpy
|
|
25
|
-
TYPE = '
|
|
26
|
-
SUBTYPE = '
|
|
27
|
-
def install
|
|
28
|
-
if defined?(::HTTP) && defined?(::HTTP::Client)
|
|
29
|
-
|
|
30
|
-
::HTTP::Client.class_eval do
|
|
31
|
-
alias perform_without_apm perform
|
|
32
|
-
|
|
33
|
-
def perform(req, options)
|
|
34
|
-
unless (transaction = Atatus.current_transaction)
|
|
35
|
-
return perform_without_apm(req, options)
|
|
36
|
-
end
|
|
25
|
+
TYPE = 'external'
|
|
26
|
+
SUBTYPE = 'http'
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
# @api private
|
|
29
|
+
module Ext
|
|
30
|
+
def perform(req, options)
|
|
31
|
+
unless (transaction = Atatus.current_transaction)
|
|
32
|
+
return super(req, options)
|
|
33
|
+
end
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
context = Atatus::Span::Context.new(
|
|
44
|
-
http: { url: req.uri, method: method },
|
|
45
|
-
destination: destination
|
|
46
|
-
)
|
|
35
|
+
method = req.verb.to_s.upcase
|
|
36
|
+
host = req.uri.host
|
|
47
37
|
|
|
48
|
-
|
|
38
|
+
context = Atatus::Span::Context.new(
|
|
39
|
+
http: { url: req.uri, method: method },
|
|
40
|
+
destination: Atatus::Span::Context::Destination.from_uri(req.uri, type: SUBTYPE)
|
|
41
|
+
)
|
|
49
42
|
|
|
50
|
-
|
|
51
|
-
name,
|
|
52
|
-
TYPE,
|
|
53
|
-
subtype: SUBTYPE,
|
|
54
|
-
action: method,
|
|
55
|
-
context: context
|
|
56
|
-
) do |span|
|
|
57
|
-
trace_context = span&.trace_context || transaction.trace_context
|
|
58
|
-
trace_context.apply_headers { |key, value| req[key] = value }
|
|
43
|
+
name = "#{method} #{host}"
|
|
59
44
|
|
|
60
|
-
|
|
45
|
+
Atatus.with_span(
|
|
46
|
+
name,
|
|
47
|
+
TYPE,
|
|
48
|
+
subtype: SUBTYPE,
|
|
49
|
+
context: context
|
|
50
|
+
) do |span|
|
|
51
|
+
trace_context = span&.trace_context || transaction.trace_context
|
|
52
|
+
trace_context.apply_headers { |key, value| req[key] = value }
|
|
61
53
|
|
|
62
|
-
|
|
63
|
-
http.status_code = result.status.to_s
|
|
64
|
-
end
|
|
54
|
+
result = super(req, options)
|
|
65
55
|
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
if (http = span&.context&.http)
|
|
57
|
+
http.status_code = result.status.to_s
|
|
68
58
|
end
|
|
69
|
-
end
|
|
70
59
|
|
|
60
|
+
span&.outcome = Span::Outcome.from_http_status(result.status)
|
|
61
|
+
result
|
|
62
|
+
end
|
|
71
63
|
end
|
|
72
64
|
end
|
|
65
|
+
|
|
66
|
+
def install
|
|
67
|
+
::HTTP::Client.prepend(Ext)
|
|
68
|
+
end
|
|
73
69
|
end
|
|
74
70
|
|
|
75
71
|
register 'HTTP', 'http', HTTPSpy.new
|