atatus 1.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 +7 -0
- data/.gitignore +16 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +57 -0
- data/LICENSE +65 -0
- data/LICENSE-THIRD-PARTY +205 -0
- data/README.md +13 -0
- data/Rakefile +19 -0
- data/atatus.gemspec +36 -0
- data/atatus.yml +2 -0
- data/bench/.gitignore +2 -0
- data/bench/app.rb +53 -0
- data/bench/benchmark.rb +36 -0
- data/bench/report.rb +55 -0
- data/bench/rubyprof.rb +39 -0
- data/bench/stackprof.rb +23 -0
- data/bin/build_docs +5 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/bin/with_framework +7 -0
- data/lib/atatus.rb +325 -0
- data/lib/atatus/agent.rb +260 -0
- data/lib/atatus/central_config.rb +141 -0
- data/lib/atatus/central_config/cache_control.rb +34 -0
- data/lib/atatus/collector/base.rb +329 -0
- data/lib/atatus/collector/builder.rb +317 -0
- data/lib/atatus/collector/transport.rb +72 -0
- data/lib/atatus/config.rb +248 -0
- data/lib/atatus/config/bytes.rb +25 -0
- data/lib/atatus/config/duration.rb +23 -0
- data/lib/atatus/config/options.rb +134 -0
- data/lib/atatus/config/regexp_list.rb +13 -0
- data/lib/atatus/context.rb +33 -0
- data/lib/atatus/context/request.rb +11 -0
- data/lib/atatus/context/request/socket.rb +19 -0
- data/lib/atatus/context/request/url.rb +42 -0
- data/lib/atatus/context/response.rb +22 -0
- data/lib/atatus/context/user.rb +42 -0
- data/lib/atatus/context_builder.rb +97 -0
- data/lib/atatus/deprecations.rb +22 -0
- data/lib/atatus/error.rb +22 -0
- data/lib/atatus/error/exception.rb +46 -0
- data/lib/atatus/error/log.rb +24 -0
- data/lib/atatus/error_builder.rb +76 -0
- data/lib/atatus/instrumenter.rb +224 -0
- data/lib/atatus/internal_error.rb +6 -0
- data/lib/atatus/logging.rb +55 -0
- data/lib/atatus/metadata.rb +19 -0
- data/lib/atatus/metadata/process_info.rb +18 -0
- data/lib/atatus/metadata/service_info.rb +61 -0
- data/lib/atatus/metadata/system_info.rb +35 -0
- data/lib/atatus/metadata/system_info/container_info.rb +121 -0
- data/lib/atatus/metadata/system_info/hw_info.rb +118 -0
- data/lib/atatus/metadata/system_info/os_info.rb +31 -0
- data/lib/atatus/metrics.rb +98 -0
- data/lib/atatus/metrics/cpu_mem.rb +240 -0
- data/lib/atatus/metrics/vm.rb +60 -0
- data/lib/atatus/metricset.rb +19 -0
- data/lib/atatus/middleware.rb +76 -0
- data/lib/atatus/naively_hashable.rb +21 -0
- data/lib/atatus/normalizers.rb +68 -0
- data/lib/atatus/normalizers/action_controller.rb +27 -0
- data/lib/atatus/normalizers/action_mailer.rb +26 -0
- data/lib/atatus/normalizers/action_view.rb +77 -0
- data/lib/atatus/normalizers/active_record.rb +45 -0
- data/lib/atatus/opentracing.rb +346 -0
- data/lib/atatus/rails.rb +61 -0
- data/lib/atatus/railtie.rb +30 -0
- data/lib/atatus/span.rb +125 -0
- data/lib/atatus/span/context.rb +40 -0
- data/lib/atatus/span_helpers.rb +44 -0
- data/lib/atatus/spies.rb +86 -0
- data/lib/atatus/spies/action_dispatch.rb +28 -0
- data/lib/atatus/spies/delayed_job.rb +68 -0
- data/lib/atatus/spies/elasticsearch.rb +36 -0
- data/lib/atatus/spies/faraday.rb +70 -0
- data/lib/atatus/spies/http.rb +44 -0
- data/lib/atatus/spies/json.rb +22 -0
- data/lib/atatus/spies/mongo.rb +87 -0
- data/lib/atatus/spies/net_http.rb +70 -0
- data/lib/atatus/spies/rake.rb +45 -0
- data/lib/atatus/spies/redis.rb +27 -0
- data/lib/atatus/spies/sequel.rb +47 -0
- data/lib/atatus/spies/sidekiq.rb +89 -0
- data/lib/atatus/spies/sinatra.rb +41 -0
- data/lib/atatus/spies/tilt.rb +27 -0
- data/lib/atatus/sql_summarizer.rb +35 -0
- data/lib/atatus/stacktrace.rb +16 -0
- data/lib/atatus/stacktrace/frame.rb +52 -0
- data/lib/atatus/stacktrace_builder.rb +104 -0
- data/lib/atatus/subscriber.rb +77 -0
- data/lib/atatus/trace_context.rb +85 -0
- data/lib/atatus/transaction.rb +100 -0
- data/lib/atatus/transport/base.rb +174 -0
- data/lib/atatus/transport/connection.rb +156 -0
- data/lib/atatus/transport/connection/http.rb +116 -0
- data/lib/atatus/transport/connection/proxy_pipe.rb +75 -0
- data/lib/atatus/transport/filters.rb +43 -0
- data/lib/atatus/transport/filters/secrets_filter.rb +74 -0
- data/lib/atatus/transport/serializers.rb +93 -0
- data/lib/atatus/transport/serializers/context_serializer.rb +85 -0
- data/lib/atatus/transport/serializers/error_serializer.rb +77 -0
- data/lib/atatus/transport/serializers/metadata_serializer.rb +70 -0
- data/lib/atatus/transport/serializers/metricset_serializer.rb +28 -0
- data/lib/atatus/transport/serializers/span_serializer.rb +80 -0
- data/lib/atatus/transport/serializers/transaction_serializer.rb +37 -0
- data/lib/atatus/transport/worker.rb +73 -0
- data/lib/atatus/util.rb +42 -0
- data/lib/atatus/util/inflector.rb +93 -0
- data/lib/atatus/util/lru_cache.rb +48 -0
- data/lib/atatus/util/prefixed_logger.rb +18 -0
- data/lib/atatus/util/throttle.rb +35 -0
- data/lib/atatus/version.rb +5 -0
- data/vendor/.gitkeep +0 -0
- metadata +190 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
# @api private
|
|
5
|
+
module Spies
|
|
6
|
+
# @api private
|
|
7
|
+
class SidekiqSpy
|
|
8
|
+
ACTIVE_JOB_WRAPPER =
|
|
9
|
+
'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper'
|
|
10
|
+
|
|
11
|
+
# @api private
|
|
12
|
+
class Middleware
|
|
13
|
+
# rubocop:disable Metrics/MethodLength
|
|
14
|
+
def call(_worker, job, queue)
|
|
15
|
+
name = SidekiqSpy.name_for(job)
|
|
16
|
+
transaction = Atatus.start_transaction(name, 'Sidekiq')
|
|
17
|
+
Atatus.set_label(:queue, queue)
|
|
18
|
+
|
|
19
|
+
yield
|
|
20
|
+
|
|
21
|
+
transaction.done :success if transaction
|
|
22
|
+
rescue ::Exception => e
|
|
23
|
+
Atatus.report(e, handled: false)
|
|
24
|
+
transaction.done :error if transaction
|
|
25
|
+
raise
|
|
26
|
+
ensure
|
|
27
|
+
Atatus.end_transaction
|
|
28
|
+
end
|
|
29
|
+
# rubocop:enable Metrics/MethodLength
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.name_for(job)
|
|
33
|
+
klass = job['class']
|
|
34
|
+
|
|
35
|
+
case klass
|
|
36
|
+
when ACTIVE_JOB_WRAPPER
|
|
37
|
+
job['wrapped']
|
|
38
|
+
else
|
|
39
|
+
klass
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def install_middleware
|
|
44
|
+
Sidekiq.configure_server do |config|
|
|
45
|
+
config.server_middleware do |chain|
|
|
46
|
+
chain.add Middleware
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# rubocop:disable Metrics/MethodLength
|
|
52
|
+
def install_processor
|
|
53
|
+
require 'sidekiq/processor'
|
|
54
|
+
|
|
55
|
+
Sidekiq::Processor.class_eval do
|
|
56
|
+
alias start_without_apm start
|
|
57
|
+
alias terminate_without_apm terminate
|
|
58
|
+
|
|
59
|
+
def start
|
|
60
|
+
result = start_without_apm
|
|
61
|
+
|
|
62
|
+
# Already running from Railtie if Rails
|
|
63
|
+
if Atatus.running?
|
|
64
|
+
Atatus.agent.config.logger = Sidekiq.logger
|
|
65
|
+
else
|
|
66
|
+
Atatus.start
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
result
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def terminate
|
|
73
|
+
terminate_without_apm
|
|
74
|
+
|
|
75
|
+
Atatus.stop
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
# rubocop:enable Metrics/MethodLength
|
|
80
|
+
|
|
81
|
+
def install
|
|
82
|
+
install_processor
|
|
83
|
+
install_middleware
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
register 'Sidekiq', 'sidekiq', SidekiqSpy.new
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
# @api private
|
|
5
|
+
module Spies
|
|
6
|
+
# @api private
|
|
7
|
+
class SinatraSpy
|
|
8
|
+
# rubocop:disable Metrics/MethodLength
|
|
9
|
+
def install
|
|
10
|
+
::Sinatra::Base.class_eval do
|
|
11
|
+
alias dispatch_without_apm! dispatch!
|
|
12
|
+
alias compile_template_without_apm compile_template
|
|
13
|
+
|
|
14
|
+
def dispatch!(*args, &block)
|
|
15
|
+
dispatch_without_apm!(*args, &block).tap do
|
|
16
|
+
next unless (transaction = Atatus.current_transaction)
|
|
17
|
+
next unless (route = env['sinatra.route'])
|
|
18
|
+
|
|
19
|
+
transaction.name = route
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def compile_template(engine, data, opts, *args, &block)
|
|
24
|
+
opts[:__atatus_template_name] =
|
|
25
|
+
case data
|
|
26
|
+
when Symbol then data.to_s
|
|
27
|
+
else format('Inline %s', engine)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
compile_template_without_apm(engine, data, opts, *args, &block)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
# rubocop:enable Metrics/MethodLength
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
register 'Sinatra::Base', 'sinatra/base', SinatraSpy.new
|
|
38
|
+
|
|
39
|
+
require 'atatus/spies/tilt'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Atatus
|
|
4
|
+
# @api private
|
|
5
|
+
module Spies
|
|
6
|
+
# @api private
|
|
7
|
+
class TiltSpy
|
|
8
|
+
TYPE = 'template.tilt'
|
|
9
|
+
|
|
10
|
+
def install
|
|
11
|
+
::Tilt::Template.class_eval do
|
|
12
|
+
alias render_without_apm render
|
|
13
|
+
|
|
14
|
+
def render(*args, &block)
|
|
15
|
+
name = options[:__atatus_template_name] || 'Unknown template'
|
|
16
|
+
|
|
17
|
+
Atatus.with_span name, TYPE do
|
|
18
|
+
render_without_apm(*args, &block)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
register 'Tilt::Template', 'tilt/template', TiltSpy.new
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'atatus/util/lru_cache'
|
|
4
|
+
|
|
5
|
+
module Atatus
|
|
6
|
+
# @api private
|
|
7
|
+
class SqlSummarizer
|
|
8
|
+
DEFAULT = 'SQL'
|
|
9
|
+
TABLE_REGEX = %{["'`]?([A-Za-z0-9_]+)["'`]?}
|
|
10
|
+
|
|
11
|
+
REGEXES = {
|
|
12
|
+
/^BEGIN/i => 'BEGIN',
|
|
13
|
+
/^COMMIT/i => 'COMMIT',
|
|
14
|
+
/^SELECT .* FROM #{TABLE_REGEX}/i => 'SELECT FROM ',
|
|
15
|
+
/^INSERT INTO #{TABLE_REGEX}/i => 'INSERT INTO ',
|
|
16
|
+
/^UPDATE #{TABLE_REGEX}/i => 'UPDATE ',
|
|
17
|
+
/^DELETE FROM #{TABLE_REGEX}/i => 'DELETE FROM '
|
|
18
|
+
}.freeze
|
|
19
|
+
|
|
20
|
+
FORMAT = '%s%s'
|
|
21
|
+
|
|
22
|
+
def self.cache
|
|
23
|
+
@cache ||= Util::LruCache.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def summarize(sql)
|
|
27
|
+
self.class.cache[sql] ||=
|
|
28
|
+
REGEXES.find do |regex, sig|
|
|
29
|
+
if (match = sql[0...1000].match(regex))
|
|
30
|
+
break format(FORMAT, sig, match[1] && match[1].gsub(/["']/, ''))
|
|
31
|
+
end
|
|
32
|
+
end || DEFAULT
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'atatus/naively_hashable'
|
|
4
|
+
|
|
5
|
+
module Atatus
|
|
6
|
+
class Stacktrace
|
|
7
|
+
# @api private
|
|
8
|
+
class Frame
|
|
9
|
+
include NaivelyHashable
|
|
10
|
+
|
|
11
|
+
attr_accessor(
|
|
12
|
+
:abs_path,
|
|
13
|
+
:filename,
|
|
14
|
+
:function,
|
|
15
|
+
:vars,
|
|
16
|
+
:pre_context,
|
|
17
|
+
:context_line,
|
|
18
|
+
:post_context,
|
|
19
|
+
:library_frame,
|
|
20
|
+
:lineno,
|
|
21
|
+
:module,
|
|
22
|
+
:colno
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# rubocop:disable Metrics/AbcSize
|
|
26
|
+
def build_context(context_line_count)
|
|
27
|
+
return unless abs_path && context_line_count > 0
|
|
28
|
+
|
|
29
|
+
padding = (context_line_count - 1) / 2
|
|
30
|
+
from = lineno - padding - 1
|
|
31
|
+
from = 0 if from < 0
|
|
32
|
+
to = lineno + padding - 1
|
|
33
|
+
file_lines = read_lines(abs_path, from..to)
|
|
34
|
+
|
|
35
|
+
return unless file_lines
|
|
36
|
+
|
|
37
|
+
self.context_line = file_lines[padding]
|
|
38
|
+
self.pre_context = file_lines.first(padding)
|
|
39
|
+
self.post_context = file_lines.last(padding)
|
|
40
|
+
end
|
|
41
|
+
# rubocop:enable Metrics/AbcSize
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def read_lines(path, range)
|
|
46
|
+
File.readlines(path)[range]
|
|
47
|
+
rescue Errno::ENOENT
|
|
48
|
+
nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'atatus/stacktrace/frame'
|
|
4
|
+
require 'atatus/util/lru_cache'
|
|
5
|
+
|
|
6
|
+
module Atatus
|
|
7
|
+
# @api private
|
|
8
|
+
class StacktraceBuilder
|
|
9
|
+
JAVA_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
|
|
10
|
+
RUBY_FORMAT = /^(.+?):(\d+)(?::in `(.+?)')?$/.freeze
|
|
11
|
+
|
|
12
|
+
RUBY_VERS_REGEX = %r{ruby(/gems)?[-/](\d+\.)+\d}.freeze
|
|
13
|
+
JRUBY_ORG_REGEX = %r{org/jruby}.freeze
|
|
14
|
+
|
|
15
|
+
GEMS_PATH = defined?(Bundler) ? Bundler.bundle_path.to_s : Gem.dir
|
|
16
|
+
|
|
17
|
+
def initialize(config)
|
|
18
|
+
@config = config
|
|
19
|
+
@cache = Util::LruCache.new(2048, &method(:build_frame))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
attr_reader :config
|
|
23
|
+
|
|
24
|
+
def build(backtrace, type:)
|
|
25
|
+
Stacktrace.new.tap do |s|
|
|
26
|
+
s.frames = backtrace[0...config.stack_trace_limit].map do |line|
|
|
27
|
+
@cache[[line, type]]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
35
|
+
def build_frame(cache, keys)
|
|
36
|
+
line, type = keys
|
|
37
|
+
abs_path, lineno, function, _module_name = parse_line(line)
|
|
38
|
+
|
|
39
|
+
frame = Stacktrace::Frame.new
|
|
40
|
+
frame.abs_path = abs_path
|
|
41
|
+
frame.filename = strip_load_path(abs_path)
|
|
42
|
+
frame.function = function
|
|
43
|
+
frame.lineno = lineno.to_i
|
|
44
|
+
frame.library_frame = library_frame?(config, abs_path)
|
|
45
|
+
|
|
46
|
+
line_count =
|
|
47
|
+
context_lines_for(config, type, library_frame: frame.library_frame)
|
|
48
|
+
frame.build_context line_count
|
|
49
|
+
|
|
50
|
+
cache[[line, type]] = frame
|
|
51
|
+
end
|
|
52
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
|
53
|
+
|
|
54
|
+
def parse_line(line)
|
|
55
|
+
ruby_match = line.match(RUBY_FORMAT)
|
|
56
|
+
|
|
57
|
+
if ruby_match
|
|
58
|
+
_, file, number, method = ruby_match.to_a
|
|
59
|
+
file.sub!(/\.class$/, '.rb')
|
|
60
|
+
module_name = nil
|
|
61
|
+
else
|
|
62
|
+
java_match = line.match(JAVA_FORMAT)
|
|
63
|
+
_, module_name, method, file, number = java_match.to_a
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
[file, number, method, module_name]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
70
|
+
def library_frame?(config, abs_path)
|
|
71
|
+
return false unless abs_path
|
|
72
|
+
|
|
73
|
+
return true if abs_path.start_with?(GEMS_PATH)
|
|
74
|
+
|
|
75
|
+
if abs_path.start_with?(config.__root_path)
|
|
76
|
+
return true if abs_path.start_with?(config.__root_path + '/vendor')
|
|
77
|
+
return false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return true if abs_path.match(RUBY_VERS_REGEX)
|
|
81
|
+
return true if abs_path.match(JRUBY_ORG_REGEX)
|
|
82
|
+
|
|
83
|
+
false
|
|
84
|
+
end
|
|
85
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
86
|
+
|
|
87
|
+
def strip_load_path(path)
|
|
88
|
+
return nil if path.nil?
|
|
89
|
+
|
|
90
|
+
prefix =
|
|
91
|
+
$LOAD_PATH
|
|
92
|
+
.map(&:to_s)
|
|
93
|
+
.select { |s| path.start_with?(s) }
|
|
94
|
+
.max_by(&:length)
|
|
95
|
+
|
|
96
|
+
prefix ? path[prefix.chomp(File::SEPARATOR).length + 1..-1] : path
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def context_lines_for(config, type, library_frame:)
|
|
100
|
+
key = "source_lines_#{type}_#{library_frame ? 'library' : 'app'}_frames"
|
|
101
|
+
config.send(key.to_sym)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/notifications'
|
|
4
|
+
require 'atatus/normalizers'
|
|
5
|
+
|
|
6
|
+
module Atatus
|
|
7
|
+
# @api private
|
|
8
|
+
class Subscriber
|
|
9
|
+
include Logging
|
|
10
|
+
|
|
11
|
+
def initialize(agent)
|
|
12
|
+
@agent = agent
|
|
13
|
+
@normalizers = Normalizers.build(agent.config)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def register!
|
|
17
|
+
unregister! if @subscription
|
|
18
|
+
|
|
19
|
+
@subscription =
|
|
20
|
+
ActiveSupport::Notifications.subscribe(notifications_regex, self)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def unregister!
|
|
24
|
+
ActiveSupport::Notifications.unsubscribe @subscription
|
|
25
|
+
@subscription = nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# AS::Notifications API
|
|
29
|
+
|
|
30
|
+
Notification = Struct.new(:id, :span)
|
|
31
|
+
|
|
32
|
+
# rubocop:disable Metrics/MethodLength
|
|
33
|
+
def start(name, id, payload)
|
|
34
|
+
return unless (transaction = @agent.current_transaction)
|
|
35
|
+
|
|
36
|
+
normalized = @normalizers.normalize(transaction, name, payload)
|
|
37
|
+
|
|
38
|
+
span =
|
|
39
|
+
if normalized == :skip
|
|
40
|
+
nil
|
|
41
|
+
else
|
|
42
|
+
name, type, subtype, action, context = normalized
|
|
43
|
+
|
|
44
|
+
@agent.start_span(
|
|
45
|
+
name,
|
|
46
|
+
type,
|
|
47
|
+
subtype: subtype,
|
|
48
|
+
action: action,
|
|
49
|
+
context: context
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
transaction.notifications << Notification.new(id, span)
|
|
54
|
+
end
|
|
55
|
+
# rubocop:enable Metrics/MethodLength
|
|
56
|
+
|
|
57
|
+
def finish(_name, id, _payload)
|
|
58
|
+
# debug "AS::Notification#finish:#{name}:#{id}"
|
|
59
|
+
return unless (transaction = @agent.current_transaction)
|
|
60
|
+
|
|
61
|
+
while (notification = transaction.notifications.pop)
|
|
62
|
+
next unless notification.id == id
|
|
63
|
+
|
|
64
|
+
if (span = notification.span)
|
|
65
|
+
@agent.end_span if span == @agent.current_span
|
|
66
|
+
end
|
|
67
|
+
return
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def notifications_regex
|
|
74
|
+
@notifications_regex ||= /(#{@normalizers.keys.join('|')})/
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|