atatus 1.7.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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(
|