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
data/lib/atatus/config.rb
CHANGED
|
@@ -17,20 +17,26 @@
|
|
|
17
17
|
|
|
18
18
|
# frozen_string_literal: true
|
|
19
19
|
|
|
20
|
-
require 'atatus/config/options'
|
|
21
|
-
require 'atatus/config/duration'
|
|
22
20
|
require 'atatus/config/bytes'
|
|
21
|
+
require 'atatus/config/duration'
|
|
22
|
+
require 'atatus/config/log_level_map'
|
|
23
|
+
require 'atatus/config/options'
|
|
24
|
+
require 'atatus/config/round_float'
|
|
23
25
|
require 'atatus/config/regexp_list'
|
|
24
26
|
require 'atatus/config/wildcard_pattern_list'
|
|
27
|
+
require 'atatus/deprecations'
|
|
28
|
+
require 'atatus/config/server_info'
|
|
25
29
|
|
|
26
30
|
module Atatus
|
|
27
31
|
# @api private
|
|
28
32
|
class Config
|
|
29
33
|
extend Options
|
|
34
|
+
extend Deprecations
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
SANITIZE_FIELD_NAMES_DEFAULT =
|
|
37
|
+
%w[password passwd pwd secret *key *token* *session* *credit* *card* *auth* set-cookie].freeze
|
|
32
38
|
|
|
33
|
-
# rubocop:disable
|
|
39
|
+
# rubocop:disable Layout/LineLength, Layout/ExtraSpacing
|
|
34
40
|
option :app_name, type: :string
|
|
35
41
|
option :license_key, type: :string
|
|
36
42
|
option :notify_host, type: :string, default: 'https://apm-rx.atatus.com'
|
|
@@ -51,6 +57,7 @@ module Atatus
|
|
|
51
57
|
option :capture_elasticsearch_queries, type: :bool, default: false
|
|
52
58
|
option :capture_env, type: :bool, default: true
|
|
53
59
|
option :central_config, type: :bool, default: true
|
|
60
|
+
option :cloud_provider, type: :string, default: 'auto'
|
|
54
61
|
option :current_user_email_method, type: :string, default: 'email'
|
|
55
62
|
option :current_user_id_method, type: :string, default: 'id'
|
|
56
63
|
option :current_user_username_method, type: :string, default: 'username'
|
|
@@ -73,7 +80,8 @@ module Atatus
|
|
|
73
80
|
option :ignore_url_patterns, type: :list, default: [], converter: RegexpList.new
|
|
74
81
|
option :instrument, type: :bool, default: true
|
|
75
82
|
option :instrumented_rake_tasks, type: :list, default: []
|
|
76
|
-
option :
|
|
83
|
+
option :log_ecs_reformatting, type: :string, default: 'off'
|
|
84
|
+
option :log_level, type: :int, default: Logger::INFO, converter: LogLevelMap.new
|
|
77
85
|
option :log_path, type: :string, default: '-'
|
|
78
86
|
option :metrics_interval, type: :int, default: '30s', converter: Duration.new
|
|
79
87
|
option :pool_size, type: :int, default: 1
|
|
@@ -83,8 +91,8 @@ module Atatus
|
|
|
83
91
|
option :proxy_port, type: :int
|
|
84
92
|
option :proxy_username, type: :string
|
|
85
93
|
option :recording, type: :bool, default: true
|
|
86
|
-
option :sanitize_field_names, type: :list, default:
|
|
87
|
-
option :
|
|
94
|
+
option :sanitize_field_names, type: :list, default: SANITIZE_FIELD_NAMES_DEFAULT, converter: WildcardPatternList.new
|
|
95
|
+
option :server_ca_cert_file, type: :string
|
|
88
96
|
option :service_name, type: :string
|
|
89
97
|
option :service_node_name, type: :string
|
|
90
98
|
option :service_version, type: :string
|
|
@@ -96,12 +104,21 @@ module Atatus
|
|
|
96
104
|
option :stack_trace_limit, type: :int, default: 999_999
|
|
97
105
|
option :transaction_ignore_urls, type: :list, default: [], converter: WildcardPatternList.new
|
|
98
106
|
option :transaction_max_spans, type: :int, default: 500
|
|
99
|
-
option :transaction_sample_rate, type: :float, default: 1.0
|
|
107
|
+
option :transaction_sample_rate, type: :float, default: 1.0, converter: RoundFloat.new
|
|
100
108
|
option :use_atatus_traceparent_header, type: :bool, default: true
|
|
101
|
-
option :use_legacy_sql_parser, type: :bool, default: false
|
|
102
109
|
option :verify_server_cert, type: :bool, default: true
|
|
103
110
|
|
|
104
|
-
|
|
111
|
+
def log_ecs_formatting
|
|
112
|
+
log_ecs_reformatting
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def log_ecs_formatting=(value)
|
|
116
|
+
@options[:log_ecs_reformatting].set(value)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
deprecate :log_ecs_formatting, :log_ecs_reformatting
|
|
120
|
+
|
|
121
|
+
# rubocop:enable Layout/LineLength, Layout/ExtraSpacing
|
|
105
122
|
def initialize(options = {})
|
|
106
123
|
@options = load_schema
|
|
107
124
|
|
|
@@ -114,19 +131,20 @@ module Atatus
|
|
|
114
131
|
self.config_file = env_config_file
|
|
115
132
|
end
|
|
116
133
|
|
|
117
|
-
assign(load_config_file)
|
|
134
|
+
assign(load_config_file(self.environment))
|
|
118
135
|
assign(env)
|
|
119
136
|
|
|
120
137
|
yield self if block_given?
|
|
121
138
|
|
|
122
|
-
self.logger
|
|
139
|
+
if self.logger.nil? || self.log_path
|
|
140
|
+
self.logger = build_logger
|
|
141
|
+
end
|
|
123
142
|
|
|
124
143
|
@__view_paths ||= []
|
|
125
144
|
@__root_path ||= Dir.pwd
|
|
126
145
|
end
|
|
127
146
|
|
|
128
|
-
attr_accessor :__view_paths, :__root_path
|
|
129
|
-
attr_accessor :logger
|
|
147
|
+
attr_accessor :__view_paths, :__root_path, :logger
|
|
130
148
|
|
|
131
149
|
attr_reader :options
|
|
132
150
|
|
|
@@ -138,6 +156,7 @@ module Atatus
|
|
|
138
156
|
def available_instrumentations
|
|
139
157
|
%w[
|
|
140
158
|
action_dispatch
|
|
159
|
+
azure_storage_table
|
|
141
160
|
delayed_job
|
|
142
161
|
dynamo_db
|
|
143
162
|
elasticsearch
|
|
@@ -147,13 +166,17 @@ module Atatus
|
|
|
147
166
|
mongo
|
|
148
167
|
net_http
|
|
149
168
|
rake
|
|
169
|
+
racecar
|
|
150
170
|
redis
|
|
151
171
|
resque
|
|
172
|
+
s3
|
|
152
173
|
sequel
|
|
153
174
|
shoryuken
|
|
154
175
|
sidekiq
|
|
155
176
|
sinatra
|
|
156
177
|
sneakers
|
|
178
|
+
sns
|
|
179
|
+
sqs
|
|
157
180
|
sucker_punch
|
|
158
181
|
tilt
|
|
159
182
|
]
|
|
@@ -163,11 +186,6 @@ module Atatus
|
|
|
163
186
|
available_instrumentations - disable_instrumentations
|
|
164
187
|
end
|
|
165
188
|
|
|
166
|
-
def method_missing(name, *args)
|
|
167
|
-
return super unless DEPRECATED_OPTIONS.include?(name)
|
|
168
|
-
warn "The option `#{name}' has been removed."
|
|
169
|
-
end
|
|
170
|
-
|
|
171
189
|
def replace_options(new_options)
|
|
172
190
|
return if new_options.nil? || new_options.empty?
|
|
173
191
|
options_copy = @options.dup
|
|
@@ -214,8 +232,8 @@ module Atatus
|
|
|
214
232
|
|
|
215
233
|
@ssl_context ||=
|
|
216
234
|
OpenSSL::SSL::SSLContext.new.tap do |context|
|
|
217
|
-
if
|
|
218
|
-
context.ca_file =
|
|
235
|
+
if server_ca_cert_file
|
|
236
|
+
context.ca_file = server_ca_cert_file
|
|
219
237
|
else
|
|
220
238
|
context.cert_store =
|
|
221
239
|
OpenSSL::X509::Store.new.tap(&:set_default_paths)
|
|
@@ -234,66 +252,49 @@ module Atatus
|
|
|
234
252
|
super.split.first + '>'
|
|
235
253
|
end
|
|
236
254
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
def default_tags=(value)
|
|
240
|
-
warn '[DEPRECATED] The option default_tags has been renamed to ' \
|
|
241
|
-
'default_labels.'
|
|
242
|
-
self.default_labels = value
|
|
255
|
+
def version
|
|
256
|
+
@version ||= ServerInfo.new(self).version
|
|
243
257
|
end
|
|
244
258
|
|
|
245
|
-
|
|
246
|
-
unless value == self.class.schema[:ignore_url_patterns][:default]
|
|
247
|
-
warn '[DEPRECATED] The option ignore_url_patterns is being removed. ' \
|
|
248
|
-
'Consider using transaction_ignore_urls instead.'
|
|
249
|
-
end
|
|
259
|
+
private
|
|
250
260
|
|
|
251
|
-
set(:ignore_url_patterns, value)
|
|
252
|
-
end
|
|
253
261
|
|
|
254
|
-
def
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
262
|
+
def parse_erb(file)
|
|
263
|
+
begin
|
|
264
|
+
file.gsub!(/^\s*#.*$/, '#')
|
|
265
|
+
ERB.new(file).result(binding)
|
|
266
|
+
rescue ScriptError, StandardError => e
|
|
267
|
+
warn "[Atatus] FATAL : Failed ERB processing of atatus.yml file. Please check contents of the file. #{e}"
|
|
268
|
+
nil
|
|
258
269
|
end
|
|
259
|
-
|
|
260
|
-
set(:custom_key_filters, value)
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
def disabled_instrumentations
|
|
264
|
-
disable_instrumentations
|
|
265
270
|
end
|
|
266
271
|
|
|
267
|
-
def
|
|
268
|
-
|
|
269
|
-
end
|
|
270
|
-
alias active? active
|
|
272
|
+
def load_config_file(env)
|
|
273
|
+
return unless File.exist?(config_file)
|
|
271
274
|
|
|
272
|
-
|
|
273
|
-
warn '[DEPRECATED] The option disabled_instrumentations has been ' \
|
|
274
|
-
'renamed to disable_instrumentations to align with other agents.'
|
|
275
|
-
self.disable_instrumentations = value
|
|
276
|
-
end
|
|
275
|
+
config = {}
|
|
277
276
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
277
|
+
begin
|
|
278
|
+
read = File.read(config_file)
|
|
279
|
+
evaled = parse_erb(read)
|
|
280
|
+
|
|
281
|
+
# YAML.safe_load(evaled)
|
|
282
282
|
|
|
283
|
-
|
|
284
|
-
warn '[DEPRECATED] The option active has been renamed to enabled ' \
|
|
285
|
-
'to align with other agents and with the remote config.'
|
|
286
|
-
self.enabled = value
|
|
287
|
-
end
|
|
283
|
+
loaded_config = YAML.load(evaled)
|
|
288
284
|
|
|
289
|
-
|
|
285
|
+
if loaded_config.key?("default")
|
|
286
|
+
unless loaded_config.key?(env)
|
|
287
|
+
warn "[Atatus] ERROR : atatus.yml does not include '#{env}' section!"
|
|
288
|
+
loaded_config = loaded_config["default"]
|
|
289
|
+
end
|
|
290
|
+
end
|
|
290
291
|
|
|
291
|
-
|
|
292
|
-
|
|
292
|
+
config = loaded_config[env] || loaded_config
|
|
293
|
+
rescue ScriptError, StandardError => e
|
|
294
|
+
warn "[Atatus] FATAL : Error parsing atatus.yml configuration '#{e}'"
|
|
295
|
+
end
|
|
293
296
|
|
|
294
|
-
|
|
295
|
-
evaled = ERB.new(read).result
|
|
296
|
-
YAML.safe_load(evaled)
|
|
297
|
+
config
|
|
297
298
|
end
|
|
298
299
|
|
|
299
300
|
def load_env
|
|
@@ -304,7 +305,25 @@ module Atatus
|
|
|
304
305
|
end
|
|
305
306
|
|
|
306
307
|
def build_logger
|
|
307
|
-
|
|
308
|
+
if self.log_ecs_reformatting == 'override'
|
|
309
|
+
begin
|
|
310
|
+
return build_ecs_logger
|
|
311
|
+
rescue LoadError
|
|
312
|
+
logger.info "Attempted to use EcsLogging::Logger but the gem couldn't be " \
|
|
313
|
+
"loaded so a ::Logger was created instead. Check if you have the `ecs-logging` " \
|
|
314
|
+
"gem installed and attempt to start the agent again."
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
Logger.new(log_path == '-' ? $stdout : log_path).tap do |logger|
|
|
319
|
+
logger.level = log_level
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def build_ecs_logger
|
|
324
|
+
require 'ecs_logging/logger'
|
|
325
|
+
|
|
326
|
+
::EcsLogging::Logger.new(log_path == '-' ? $stdout : log_path).tap do |logger|
|
|
308
327
|
logger.level = log_level
|
|
309
328
|
end
|
|
310
329
|
end
|
|
@@ -333,9 +352,11 @@ module Atatus
|
|
|
333
352
|
self.framework_name ||= 'Rails'
|
|
334
353
|
self.framework_version ||= ::Rails::VERSION::STRING
|
|
335
354
|
self.logger ||= ::Rails.logger
|
|
355
|
+
self.log_level ||= ::Rails.logger.log_level
|
|
336
356
|
|
|
337
357
|
self.__root_path = ::Rails.root.to_s
|
|
338
|
-
self.__view_paths = app.config.paths['app/views'].existent +
|
|
358
|
+
self.__view_paths = app.config.paths['app/views'].existent +
|
|
359
|
+
[::Rails.root.to_s]
|
|
339
360
|
end
|
|
340
361
|
|
|
341
362
|
def rails_app_name(app)
|
data/lib/atatus/context.rb
CHANGED
|
@@ -37,16 +37,10 @@ module Atatus
|
|
|
37
37
|
Service = Struct.new(:framework)
|
|
38
38
|
Framework = Struct.new(:name, :version)
|
|
39
39
|
|
|
40
|
-
attr_accessor :request
|
|
41
|
-
|
|
42
|
-
attr_accessor :
|
|
43
|
-
attr_reader :custom
|
|
44
|
-
attr_reader :labels
|
|
45
|
-
attr_reader :service
|
|
46
|
-
attr_accessor :company
|
|
47
|
-
attr_accessor :response_body
|
|
40
|
+
attr_accessor :request, :response, :user
|
|
41
|
+
attr_reader :custom, :labels, :service
|
|
42
|
+
attr_accessor :company, :response_body
|
|
48
43
|
|
|
49
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
|
50
44
|
def empty?
|
|
51
45
|
return false if labels.any?
|
|
52
46
|
return false if custom.any?
|
|
@@ -56,7 +50,6 @@ module Atatus
|
|
|
56
50
|
|
|
57
51
|
true
|
|
58
52
|
end
|
|
59
|
-
# rubocop:enable Metrics/CyclomaticComplexity
|
|
60
53
|
|
|
61
54
|
def set_service(framework_name: nil, framework_version: nil)
|
|
62
55
|
@service = Service.new(
|
|
@@ -44,7 +44,7 @@ module Atatus
|
|
|
44
44
|
request = context.request
|
|
45
45
|
|
|
46
46
|
request.socket = Context::Request::Socket.new(req)
|
|
47
|
-
request.http_version = build_http_version
|
|
47
|
+
request.http_version = build_http_version req
|
|
48
48
|
request.method = req.request_method
|
|
49
49
|
request.url = Context::Request::Url.new(req)
|
|
50
50
|
|
|
@@ -104,8 +104,8 @@ module Atatus
|
|
|
104
104
|
key.gsub(/^HTTP_/, '').split('_').map(&:capitalize).join('-')
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
-
def build_http_version(
|
|
108
|
-
return unless (http_version =
|
|
107
|
+
def build_http_version(req)
|
|
108
|
+
return unless (http_version = req.env['HTTP_VERSION'])
|
|
109
109
|
http_version.gsub(%r{HTTP/}, '')
|
|
110
110
|
end
|
|
111
111
|
end
|
data/lib/atatus/error.rb
CHANGED
|
@@ -33,7 +33,7 @@ module Atatus
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
attr_accessor :id, :culprit, :exception, :log, :transaction_id,
|
|
36
|
-
:transaction, :context, :parent_id, :trace_id
|
|
36
|
+
:transaction_name, :transaction, :context, :parent_id, :trace_id
|
|
37
37
|
attr_reader :timestamp
|
|
38
38
|
|
|
39
39
|
def inspect
|
|
@@ -41,6 +41,7 @@ module Atatus
|
|
|
41
41
|
" culprit:#{culprit}" \
|
|
42
42
|
" timestamp:#{timestamp}" \
|
|
43
43
|
" transaction_id:#{transaction_id}" \
|
|
44
|
+
" transaction_name:#{transaction_name}" \
|
|
44
45
|
" trace_id:#{trace_id}" \
|
|
45
46
|
" exception:#{exception.inspect}" \
|
|
46
47
|
'>'
|
data/lib/atatus/error_builder.rb
CHANGED
|
@@ -74,11 +74,11 @@ module Atatus
|
|
|
74
74
|
return unless transaction
|
|
75
75
|
|
|
76
76
|
error.transaction_id = transaction.id
|
|
77
|
+
error.transaction_name = transaction.name
|
|
77
78
|
error.transaction = {
|
|
78
79
|
sampled: transaction.sampled?,
|
|
79
80
|
type: transaction.type
|
|
80
81
|
}
|
|
81
|
-
error.transaction[:name] = transaction.name unless transaction.name.nil?
|
|
82
82
|
error.trace_id = transaction.trace_id
|
|
83
83
|
error.parent_id = Atatus.current_span&.id || transaction.id
|
|
84
84
|
|
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
# An interface for creating simple, value holding objects that correspond to
|
|
22
|
+
# object fields in the API.
|
|
23
|
+
#
|
|
24
|
+
# Example:
|
|
25
|
+
# class MyThing
|
|
26
|
+
# include Fields
|
|
27
|
+
# field :name
|
|
28
|
+
# field :address, default: 'There'
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# MyThing.new(name: 'AJ').to_h
|
|
32
|
+
# # => { name: 'AJ' }
|
|
33
|
+
# MyThing.new().empty?
|
|
34
|
+
# # => true
|
|
35
|
+
module Fields
|
|
36
|
+
class Field
|
|
37
|
+
def initialize(key, default: nil)
|
|
38
|
+
@key = key
|
|
39
|
+
@default = default
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
attr_reader :key, :default
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module InstanceMethods
|
|
46
|
+
def initialize(**attrs)
|
|
47
|
+
schema.each do |key, field|
|
|
48
|
+
send(:"#{key}=", field.default)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
attrs.each do |key, value|
|
|
52
|
+
send(:"#{key}=", value)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
super()
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def empty?
|
|
59
|
+
self.class.schema.each do |key, field|
|
|
60
|
+
next if send(key).nil?
|
|
61
|
+
return false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def to_h
|
|
68
|
+
schema.each_with_object({}) do |(key, field), hsh|
|
|
69
|
+
hsh[key] = send(key)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def schema
|
|
76
|
+
self.class.schema
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
module ClassMethods
|
|
81
|
+
def field(key, default: nil)
|
|
82
|
+
field = Field.new(key, default: default)
|
|
83
|
+
schema[key] = field
|
|
84
|
+
|
|
85
|
+
attr_accessor(key)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
attr_reader :schema
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.included(cls)
|
|
92
|
+
cls.extend(ClassMethods)
|
|
93
|
+
cls.include(InstanceMethods)
|
|
94
|
+
|
|
95
|
+
cls.instance_variable_set(:@schema, {})
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
data/lib/atatus/graphql.rb
CHANGED
|
@@ -48,6 +48,7 @@ module Atatus
|
|
|
48
48
|
# "authorized" => "graphql.authorized",
|
|
49
49
|
}.freeze
|
|
50
50
|
|
|
51
|
+
# rubocop:disable Style/ExplicitBlockArgument
|
|
51
52
|
def self.trace(key, data)
|
|
52
53
|
return yield unless KEYS_TO_NAME.key?(key)
|
|
53
54
|
return yield unless (transaction = Atatus.current_transaction)
|
|
@@ -69,6 +70,7 @@ module Atatus
|
|
|
69
70
|
|
|
70
71
|
results
|
|
71
72
|
end
|
|
73
|
+
# rubocop:enable Style/ExplicitBlockArgument
|
|
72
74
|
|
|
73
75
|
class << self
|
|
74
76
|
private
|
data/lib/atatus/grpc.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Atatus
|
|
|
25
25
|
TYPE = 'external'
|
|
26
26
|
SUBTYPE = 'grpc'
|
|
27
27
|
|
|
28
|
-
# rubocop:disable Lint/UnusedMethodArgument
|
|
28
|
+
# rubocop:disable Lint/UnusedMethodArgument, Style/ExplicitBlockArgument
|
|
29
29
|
def request_response(request:, call:, method:, metadata:)
|
|
30
30
|
return yield unless (transaction = Atatus.current_transaction)
|
|
31
31
|
if (trace_context = transaction.trace_context)
|
|
@@ -40,7 +40,7 @@ module Atatus
|
|
|
40
40
|
yield
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
-
# rubocop:enable Lint/UnusedMethodArgument
|
|
43
|
+
# rubocop:enable Lint/UnusedMethodArgument, Style/ExplicitBlockArgument
|
|
44
44
|
|
|
45
45
|
private
|
|
46
46
|
|
|
@@ -50,11 +50,9 @@ module Atatus
|
|
|
50
50
|
|
|
51
51
|
split_peer = URI.split(peer)
|
|
52
52
|
destination = Atatus::Span::Context::Destination.new(
|
|
53
|
-
type: TYPE,
|
|
54
|
-
name: SUBTYPE,
|
|
55
|
-
resource: peer,
|
|
56
53
|
address: split_peer[0],
|
|
57
|
-
port: split_peer[6]
|
|
54
|
+
port: split_peer[6],
|
|
55
|
+
service: { type: TYPE, name: SUBTYPE, resource: peer }
|
|
58
56
|
)
|
|
59
57
|
Atatus::Span::Context.new(destination: destination)
|
|
60
58
|
end
|
|
@@ -71,7 +69,7 @@ module Atatus
|
|
|
71
69
|
transaction.done 'success'
|
|
72
70
|
rescue ::Exception => e
|
|
73
71
|
Atatus.report(e, handled: false)
|
|
74
|
-
transaction
|
|
72
|
+
transaction&.done 'error'
|
|
75
73
|
raise
|
|
76
74
|
ensure
|
|
77
75
|
Atatus.end_transaction
|
data/lib/atatus/instrumenter.rb
CHANGED
|
@@ -89,7 +89,7 @@ module Atatus
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
def subscriber=(subscriber)
|
|
92
|
-
debug 'Registering subscriber'
|
|
92
|
+
debug 'Registering ActiveSupport::Notifications subscriber'
|
|
93
93
|
@subscriber = subscriber
|
|
94
94
|
@subscriber.register!
|
|
95
95
|
end
|
|
@@ -120,11 +120,11 @@ module Atatus
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
if trace_context
|
|
123
|
-
|
|
123
|
+
sampled = trace_context.recorded?
|
|
124
124
|
sample_rate = trace_context.tracestate.sample_rate
|
|
125
125
|
else
|
|
126
126
|
sampled = random_sample?(config)
|
|
127
|
-
sample_rate = config.transaction_sample_rate
|
|
127
|
+
sample_rate = sampled ? config.transaction_sample_rate : 0
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
transaction =
|
|
@@ -150,7 +150,9 @@ module Atatus
|
|
|
150
150
|
|
|
151
151
|
transaction.done result
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
if transaction.sampled? || @config.version < Config::ServerInfo::VERSION_8_0
|
|
154
|
+
enqueue.call transaction
|
|
155
|
+
end
|
|
154
156
|
|
|
155
157
|
update_transaction_metrics(transaction)
|
|
156
158
|
|
|
@@ -179,7 +181,8 @@ module Atatus
|
|
|
179
181
|
context: nil,
|
|
180
182
|
trace_context: nil,
|
|
181
183
|
parent: nil,
|
|
182
|
-
sync: nil
|
|
184
|
+
sync: nil,
|
|
185
|
+
exit_span: nil
|
|
183
186
|
)
|
|
184
187
|
|
|
185
188
|
transaction =
|
|
@@ -197,6 +200,15 @@ module Atatus
|
|
|
197
200
|
|
|
198
201
|
parent ||= (current_span || current_transaction)
|
|
199
202
|
|
|
203
|
+
# To not mess with breakdown metric stats, exit spans MUST not add
|
|
204
|
+
# sub-spans unless they share the same type and subtype.
|
|
205
|
+
if parent && parent.is_a?(Span) && parent.exit_span?
|
|
206
|
+
if parent.type != type || parent.subtype != subtype
|
|
207
|
+
debug "Skipping new span '#{name}' as its parent is an exit_span"
|
|
208
|
+
return
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
200
212
|
span = Span.new(
|
|
201
213
|
name: name,
|
|
202
214
|
subtype: subtype,
|
|
@@ -207,7 +219,8 @@ module Atatus
|
|
|
207
219
|
type: type,
|
|
208
220
|
context: context,
|
|
209
221
|
stacktrace_builder: stacktrace_builder,
|
|
210
|
-
sync: sync
|
|
222
|
+
sync: sync,
|
|
223
|
+
exit_span: exit_span
|
|
211
224
|
)
|
|
212
225
|
|
|
213
226
|
if backtrace && transaction.span_frames_min_duration
|
|
@@ -222,8 +235,14 @@ module Atatus
|
|
|
222
235
|
# rubocop:enable Metrics/CyclomaticComplexity
|
|
223
236
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
224
237
|
|
|
225
|
-
def end_span
|
|
226
|
-
|
|
238
|
+
def end_span(span = nil)
|
|
239
|
+
if span
|
|
240
|
+
current_spans.delete(span)
|
|
241
|
+
else
|
|
242
|
+
span = current_spans.pop
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
return unless span
|
|
227
246
|
|
|
228
247
|
span.done
|
|
229
248
|
|
|
@@ -239,7 +258,7 @@ module Atatus
|
|
|
239
258
|
def set_label(key, value)
|
|
240
259
|
return unless current_transaction
|
|
241
260
|
|
|
242
|
-
key = key.to_s.gsub(/[
|
|
261
|
+
key = key.to_s.gsub(/[."*]/, '_').to_sym
|
|
243
262
|
current_transaction.context.labels[key] = value
|
|
244
263
|
end
|
|
245
264
|
|
|
@@ -261,7 +280,7 @@ module Atatus
|
|
|
261
280
|
def set_response_body(response_body)
|
|
262
281
|
return unless current_transaction
|
|
263
282
|
current_transaction.set_response_body(response_body)
|
|
264
|
-
end
|
|
283
|
+
end
|
|
265
284
|
|
|
266
285
|
def inspect
|
|
267
286
|
'<Atatus::Instrumenter ' \
|
|
@@ -283,24 +302,9 @@ module Atatus
|
|
|
283
302
|
'transaction.type': transaction.type
|
|
284
303
|
}
|
|
285
304
|
|
|
286
|
-
@metrics.get(:transaction).timer(
|
|
287
|
-
:'transaction.duration.sum.us',
|
|
288
|
-
tags: tags, reset_on_collect: true
|
|
289
|
-
).update(transaction.duration)
|
|
290
|
-
|
|
291
|
-
@metrics.get(:transaction).counter(
|
|
292
|
-
:'transaction.duration.count',
|
|
293
|
-
tags: tags, reset_on_collect: true
|
|
294
|
-
).inc!
|
|
295
|
-
|
|
296
305
|
return unless transaction.sampled?
|
|
297
306
|
return unless transaction.breakdown_metrics
|
|
298
307
|
|
|
299
|
-
@metrics.get(:breakdown).counter(
|
|
300
|
-
:'transaction.breakdown.count',
|
|
301
|
-
tags: tags, reset_on_collect: true
|
|
302
|
-
).inc!
|
|
303
|
-
|
|
304
308
|
span_tags = tags.merge('span.type': 'app')
|
|
305
309
|
|
|
306
310
|
@metrics.get(:breakdown).timer(
|