elastic-apm 0.6.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of elastic-apm might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rspec +0 -1
- data/.rubocop.yml +3 -0
- data/Gemfile +0 -3
- data/elastic-apm.gemspec +1 -2
- data/lib/elastic_apm/agent.rb +13 -8
- data/lib/elastic_apm/config.rb +7 -6
- data/lib/elastic_apm/context_builder.rb +1 -1
- data/lib/elastic_apm/error_builder.rb +13 -5
- data/lib/elastic_apm/instrumenter.rb +10 -9
- data/lib/elastic_apm/middleware.rb +4 -3
- data/lib/elastic_apm/normalizers/active_record.rb +2 -2
- data/lib/elastic_apm/railtie.rb +10 -3
- data/lib/elastic_apm/{injectors.rb → spies.rb} +17 -17
- data/lib/elastic_apm/{injectors → spies}/action_dispatch.rb +3 -3
- data/lib/elastic_apm/{injectors → spies}/delayed_job.rb +4 -4
- data/lib/elastic_apm/{injectors → spies}/elasticsearch.rb +3 -3
- data/lib/elastic_apm/{injectors → spies}/json.rb +3 -3
- data/lib/elastic_apm/{injectors → spies}/mongo.rb +9 -5
- data/lib/elastic_apm/{injectors → spies}/net_http.rb +3 -3
- data/lib/elastic_apm/{injectors → spies}/redis.rb +3 -3
- data/lib/elastic_apm/{injectors → spies}/sequel.rb +4 -4
- data/lib/elastic_apm/{injectors → spies}/sidekiq.rb +10 -7
- data/lib/elastic_apm/{injectors → spies}/sinatra.rb +4 -4
- data/lib/elastic_apm/{injectors → spies}/tilt.rb +3 -3
- data/lib/elastic_apm/sql_summarizer.rb +10 -5
- data/lib/elastic_apm/stacktrace.rb +1 -105
- data/lib/elastic_apm/stacktrace/frame.rb +1 -5
- data/lib/elastic_apm/stacktrace_builder.rb +98 -0
- data/lib/elastic_apm/subscriber.rb +2 -3
- data/lib/elastic_apm/timed_worker.rb +4 -0
- data/lib/elastic_apm/transaction.rb +6 -2
- data/lib/elastic_apm/util/inflector.rb +45 -11
- data/lib/elastic_apm/version.rb +1 -1
- metadata +16 -30
- data/lib/elastic_apm/stacktrace/line_cache.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09106c431ff50c403a81c2013f49d9b6dfb17a23fefd88a1643919322dcf4ebe'
|
4
|
+
data.tar.gz: 4d3bde4e2bbd1de3dba89e992cd4ff032ad8580b82bce0b3d22eed5ce7c11f12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2f6b1e3e0da8311d54801cc8f9e84f2e9d6b119652a97e86549fdb9ddc03cab252830507c8c2489fbddb77e2903139490c710753f29a2f40357c65803575d53
|
7
|
+
data.tar.gz: 18050a76699c39f5cda9783a4c8eefb4443d2eefef61f5eaaf5107128f54806a34e6460271c63076425235eb86f408ca6663c9609a6547e969ff30f8eda0e5c6
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/elastic-apm.gemspec
CHANGED
@@ -14,10 +14,9 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.license = 'Apache-2.0'
|
15
15
|
spec.required_ruby_version = ">= 2.2.0"
|
16
16
|
|
17
|
-
spec.add_dependency('activesupport', '>= 3.0.0')
|
18
|
-
|
19
17
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
20
18
|
f.match(%r{^(test|spec|features)/})
|
21
19
|
end
|
20
|
+
|
22
21
|
spec.require_paths = ['lib']
|
23
22
|
end
|
data/lib/elastic_apm/agent.rb
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
require 'elastic_apm/naively_hashable'
|
4
4
|
require 'elastic_apm/context_builder'
|
5
5
|
require 'elastic_apm/error_builder'
|
6
|
+
require 'elastic_apm/stacktrace_builder'
|
6
7
|
require 'elastic_apm/error'
|
7
8
|
require 'elastic_apm/http'
|
8
|
-
require 'elastic_apm/
|
9
|
+
require 'elastic_apm/spies'
|
9
10
|
require 'elastic_apm/serializers'
|
10
11
|
require 'elastic_apm/timed_worker'
|
11
12
|
|
@@ -58,26 +59,28 @@ module ElasticAPM
|
|
58
59
|
|
59
60
|
def initialize(config)
|
60
61
|
@config = config
|
62
|
+
@http = Http.new(config)
|
61
63
|
|
62
64
|
@messages = Queue.new
|
63
65
|
@pending_transactions = Queue.new
|
64
|
-
@http = Http.new(config)
|
65
66
|
|
66
|
-
@instrumenter = Instrumenter.new(
|
67
|
-
|
68
|
-
@
|
67
|
+
@instrumenter = Instrumenter.new(self)
|
68
|
+
|
69
|
+
@context_builder = ContextBuilder.new(self)
|
70
|
+
@error_builder = ErrorBuilder.new(self)
|
71
|
+
@stacktrace_builder = StacktraceBuilder.new(self)
|
69
72
|
end
|
70
73
|
|
71
74
|
attr_reader :config, :messages, :pending_transactions, :instrumenter,
|
72
|
-
:context_builder, :http
|
75
|
+
:context_builder, :stacktrace_builder, :http
|
73
76
|
|
74
77
|
def start
|
75
78
|
debug '[%s] Starting agent, reporting to %s', VERSION, config.server_url
|
76
79
|
|
77
80
|
@instrumenter.start
|
78
81
|
|
79
|
-
config.
|
80
|
-
require "elastic_apm/
|
82
|
+
config.enabled_spies.each do |lib|
|
83
|
+
require "elastic_apm/spies/#{lib}"
|
81
84
|
end
|
82
85
|
|
83
86
|
self
|
@@ -95,6 +98,8 @@ module ElasticAPM
|
|
95
98
|
stop
|
96
99
|
end
|
97
100
|
|
101
|
+
# queues
|
102
|
+
|
98
103
|
def enqueue_transaction(transaction)
|
99
104
|
boot_worker unless worker_running?
|
100
105
|
|
data/lib/elastic_apm/config.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'logger'
|
4
|
+
require 'yaml'
|
4
5
|
|
5
6
|
module ElasticAPM
|
6
7
|
# rubocop:disable Metrics/ClassLength
|
@@ -36,7 +37,7 @@ module ElasticAPM
|
|
36
37
|
source_lines_error_library_frames: 0,
|
37
38
|
source_lines_span_library_frames: 0,
|
38
39
|
|
39
|
-
|
40
|
+
disabled_spies: %w[json],
|
40
41
|
|
41
42
|
current_user_id_method: :id,
|
42
43
|
current_user_email_method: :email,
|
@@ -74,7 +75,7 @@ module ElasticAPM
|
|
74
75
|
'ELASTIC_APM_VERIFY_SERVER_CERT' => [:bool, 'verify_server_cert'],
|
75
76
|
'ELASTIC_APM_TRANSACTION_MAX_SPANS' => [:int, 'transaction_max_spans'],
|
76
77
|
|
77
|
-
'
|
78
|
+
'ELASTIC_APM_DISABLED_SPIES' => [:list, 'disabled_spies']
|
78
79
|
}.freeze
|
79
80
|
|
80
81
|
def initialize(options = {})
|
@@ -123,7 +124,7 @@ module ElasticAPM
|
|
123
124
|
attr_accessor :source_lines_error_library_frames
|
124
125
|
attr_accessor :source_lines_span_library_frames
|
125
126
|
|
126
|
-
attr_accessor :
|
127
|
+
attr_accessor :disabled_spies
|
127
128
|
|
128
129
|
attr_accessor :view_paths
|
129
130
|
attr_accessor :root_path
|
@@ -170,7 +171,7 @@ module ElasticAPM
|
|
170
171
|
end
|
171
172
|
|
172
173
|
# rubocop:disable Metrics/MethodLength
|
173
|
-
def
|
174
|
+
def available_spies
|
174
175
|
%w[
|
175
176
|
action_dispatch
|
176
177
|
delayed_job
|
@@ -187,8 +188,8 @@ module ElasticAPM
|
|
187
188
|
end
|
188
189
|
# rubocop:enable Metrics/MethodLength
|
189
190
|
|
190
|
-
def
|
191
|
-
|
191
|
+
def enabled_spies
|
192
|
+
available_spies - disabled_spies
|
192
193
|
end
|
193
194
|
|
194
195
|
private
|
@@ -3,15 +3,18 @@
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
5
|
class ErrorBuilder
|
6
|
-
def initialize(
|
7
|
-
@
|
6
|
+
def initialize(agent)
|
7
|
+
@agent = agent
|
8
8
|
end
|
9
9
|
|
10
10
|
def build_exception(exception, handled: true)
|
11
11
|
error = Error.new
|
12
12
|
error.exception = Error::Exception.new(exception, handled: handled)
|
13
13
|
|
14
|
-
|
14
|
+
if exception.backtrace
|
15
|
+
add_stacktrace error, :exception, exception.backtrace
|
16
|
+
end
|
17
|
+
|
15
18
|
add_transaction_id error
|
16
19
|
|
17
20
|
if (transaction = ElasticAPM.current_transaction)
|
@@ -25,7 +28,10 @@ module ElasticAPM
|
|
25
28
|
error = Error.new
|
26
29
|
error.log = Error::Log.new(message, **attrs)
|
27
30
|
|
28
|
-
|
31
|
+
if backtrace
|
32
|
+
add_stacktrace error, :log, backtrace
|
33
|
+
end
|
34
|
+
|
29
35
|
add_transaction_id error
|
30
36
|
|
31
37
|
error
|
@@ -34,7 +40,9 @@ module ElasticAPM
|
|
34
40
|
private
|
35
41
|
|
36
42
|
def add_stacktrace(error, kind, backtrace)
|
37
|
-
|
43
|
+
stacktrace =
|
44
|
+
@agent.stacktrace_builder.build(backtrace, type: :error)
|
45
|
+
return unless stacktrace
|
38
46
|
|
39
47
|
case kind
|
40
48
|
when :exception
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'elastic_apm/subscriber'
|
4
3
|
require 'elastic_apm/span'
|
5
4
|
require 'elastic_apm/transaction'
|
6
5
|
|
@@ -26,24 +25,26 @@ module ElasticAPM
|
|
26
25
|
end
|
27
26
|
end
|
28
27
|
|
29
|
-
def initialize(
|
30
|
-
@config = config
|
28
|
+
def initialize(agent)
|
31
29
|
@agent = agent
|
30
|
+
@config = agent.config
|
32
31
|
|
33
32
|
@transaction_info = TransactionInfo.new
|
34
|
-
|
35
|
-
@subscriber = subscriber_class.new(config)
|
36
33
|
end
|
37
34
|
|
38
|
-
attr_reader :config, :pending_transactions
|
35
|
+
attr_reader :agent, :config, :pending_transactions
|
39
36
|
|
40
37
|
def start
|
41
|
-
@subscriber.register!
|
42
38
|
end
|
43
39
|
|
44
40
|
def stop
|
45
41
|
current_transaction.release if current_transaction
|
46
|
-
@subscriber.unregister!
|
42
|
+
@subscriber.unregister! if @subscriber
|
43
|
+
end
|
44
|
+
|
45
|
+
def subscriber=(subscriber)
|
46
|
+
@subscriber = subscriber
|
47
|
+
@subscriber.register!
|
47
48
|
end
|
48
49
|
|
49
50
|
def current_transaction
|
@@ -112,7 +113,7 @@ module ElasticAPM
|
|
112
113
|
end
|
113
114
|
|
114
115
|
def submit_transaction(transaction)
|
115
|
-
|
116
|
+
agent.enqueue_transaction transaction
|
116
117
|
|
117
118
|
return unless config.debug_transactions
|
118
119
|
debug('Submitted transaction:') { Util.inspect_transaction transaction }
|
@@ -10,20 +10,21 @@ module ElasticAPM
|
|
10
10
|
# rubocop:disable Metrics/MethodLength
|
11
11
|
def call(env)
|
12
12
|
begin
|
13
|
-
transaction = ElasticAPM.transaction 'Rack', '
|
13
|
+
transaction = ElasticAPM.transaction 'Rack', 'request',
|
14
14
|
context: ElasticAPM.build_context(env)
|
15
15
|
|
16
16
|
resp = @app.call env
|
17
17
|
status, headers, = resp
|
18
18
|
|
19
19
|
if transaction
|
20
|
-
|
20
|
+
result = "HTTP #{status.to_s[0]}xx"
|
21
|
+
transaction.submit(result, status: status, headers: headers)
|
21
22
|
end
|
22
23
|
rescue InternalError
|
23
24
|
raise # Don't report ElasticAPM errors
|
24
25
|
rescue ::Exception => e
|
25
26
|
ElasticAPM.report(e, handled: false)
|
26
|
-
transaction.submit(
|
27
|
+
transaction.submit('HTTP 5xx', status: 500) if transaction
|
27
28
|
raise
|
28
29
|
ensure
|
29
30
|
transaction.release if transaction
|
@@ -19,8 +19,8 @@ module ElasticAPM
|
|
19
19
|
def normalize(_transaction, _name, payload)
|
20
20
|
return :skip if %w[SCHEMA CACHE].include?(payload[:name])
|
21
21
|
|
22
|
-
name = summarize(payload[:sql]) || payload[:name]
|
23
|
-
context = Span::Context.new(statement: payload[:sql])
|
22
|
+
name = summarize(payload[:sql]) || payload[:name]
|
23
|
+
context = Span::Context.new(statement: payload[:sql].to_s)
|
24
24
|
[name, @type, context]
|
25
25
|
end
|
26
26
|
|
data/lib/elastic_apm/railtie.rb
CHANGED
@@ -1,18 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'elastic_apm/subscriber'
|
4
|
+
|
3
5
|
module ElasticAPM
|
4
6
|
# @api private
|
5
7
|
class Railtie < Rails::Railtie
|
6
8
|
config.elastic_apm = ActiveSupport::OrderedOptions.new
|
9
|
+
|
7
10
|
Config::DEFAULTS.each { |option, value| config.elastic_apm[option] = value }
|
8
11
|
|
9
12
|
initializer 'elastic_apm.initialize' do |app|
|
10
13
|
config = app.config.elastic_apm.merge(app: app)
|
11
14
|
|
12
15
|
begin
|
13
|
-
ElasticAPM.start config
|
16
|
+
agent = ElasticAPM.start config
|
17
|
+
|
18
|
+
if agent
|
19
|
+
agent.instrumenter.subscriber = ElasticAPM::Subscriber.new(agent)
|
14
20
|
|
15
|
-
|
21
|
+
app.middleware.insert 0, Middleware
|
22
|
+
end
|
16
23
|
rescue StandardError => e
|
17
24
|
Rails.logger.error "#{Log::PREFIX}Failed to start: #{e.message}"
|
18
25
|
Rails.logger.debug e.backtrace.join("\n")
|
@@ -20,7 +27,7 @@ module ElasticAPM
|
|
20
27
|
end
|
21
28
|
|
22
29
|
config.after_initialize do
|
23
|
-
require 'elastic_apm/
|
30
|
+
require 'elastic_apm/spies/action_dispatch'
|
24
31
|
end
|
25
32
|
end
|
26
33
|
end
|
@@ -4,20 +4,20 @@ require 'elastic_apm/util/inflector'
|
|
4
4
|
|
5
5
|
module ElasticAPM
|
6
6
|
# @api private
|
7
|
-
module
|
7
|
+
module Spies
|
8
8
|
# @api private
|
9
9
|
class Registration
|
10
|
-
|
10
|
+
extend Forwardable
|
11
|
+
|
12
|
+
def initialize(const_name, require_paths, spy)
|
11
13
|
@const_name = const_name
|
12
14
|
@require_paths = Array(require_paths)
|
13
|
-
@
|
15
|
+
@spy = spy
|
14
16
|
end
|
15
17
|
|
16
|
-
attr_reader :const_name, :require_paths
|
18
|
+
attr_reader :const_name, :require_paths
|
17
19
|
|
18
|
-
|
19
|
-
injector.install
|
20
|
-
end
|
20
|
+
def_delegator :@spy, :install
|
21
21
|
end
|
22
22
|
|
23
23
|
def self.require_hooks
|
@@ -31,9 +31,9 @@ module ElasticAPM
|
|
31
31
|
def self.register(*args)
|
32
32
|
registration = Registration.new(*args)
|
33
33
|
|
34
|
-
if
|
35
|
-
installed[registration.const_name] = registration
|
34
|
+
if safe_defined?(registration.const_name)
|
36
35
|
registration.install
|
36
|
+
installed[registration.const_name] = registration
|
37
37
|
else
|
38
38
|
register_require_hook registration
|
39
39
|
end
|
@@ -47,7 +47,7 @@ module ElasticAPM
|
|
47
47
|
|
48
48
|
def self.hook_into(name)
|
49
49
|
return unless (registration = require_hooks[name])
|
50
|
-
return unless
|
50
|
+
return unless safe_defined?(registration.const_name)
|
51
51
|
|
52
52
|
installed[registration.const_name] = registration
|
53
53
|
registration.install
|
@@ -57,11 +57,8 @@ module ElasticAPM
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
def self.
|
61
|
-
|
62
|
-
!!const
|
63
|
-
rescue NameError
|
64
|
-
false
|
60
|
+
def self.safe_defined?(const_name)
|
61
|
+
Util::Inflector.safe_constantize(const_name)
|
65
62
|
end
|
66
63
|
end
|
67
64
|
end
|
@@ -76,8 +73,11 @@ module Kernel
|
|
76
73
|
res = require_without_apm(path)
|
77
74
|
|
78
75
|
begin
|
79
|
-
ElasticAPM::
|
80
|
-
rescue ::Exception
|
76
|
+
ElasticAPM::Spies.hook_into(path)
|
77
|
+
rescue ::Exception => e
|
78
|
+
puts "Failed hooking into '#{path}'. Please report this at " \
|
79
|
+
'github.com/elastic/apm-agent-ruby'
|
80
|
+
puts e.backtrace.join("\n")
|
81
81
|
end
|
82
82
|
|
83
83
|
res
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class ActionDispatchSpy
|
8
8
|
def install
|
9
9
|
::ActionDispatch::ShowExceptions.class_eval do
|
10
10
|
alias render_exception_without_apm render_exception
|
@@ -20,7 +20,7 @@ module ElasticAPM
|
|
20
20
|
register(
|
21
21
|
'ActionDispatch::ShowExceptions',
|
22
22
|
'action_dispatch/show_exception',
|
23
|
-
|
23
|
+
ActionDispatchSpy.new
|
24
24
|
)
|
25
25
|
end
|
26
26
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class DelayedJobSpy
|
8
8
|
CLASS_SEPARATOR = '.'.freeze
|
9
9
|
METHOD_SEPARATOR = '#'.freeze
|
10
10
|
TYPE = 'Delayed::Job'.freeze
|
@@ -14,7 +14,7 @@ module ElasticAPM
|
|
14
14
|
alias invoke_job_without_apm invoke_job
|
15
15
|
|
16
16
|
def invoke_job(*args, &block)
|
17
|
-
::ElasticAPM::
|
17
|
+
::ElasticAPM::Spies::DelayedJobSpy
|
18
18
|
.invoke_job(self, *args, &block)
|
19
19
|
end
|
20
20
|
end
|
@@ -62,7 +62,7 @@ module ElasticAPM
|
|
62
62
|
register(
|
63
63
|
'Delayed::Backend::Base',
|
64
64
|
'delayed/backend/base',
|
65
|
-
|
65
|
+
DelayedJobSpy.new
|
66
66
|
)
|
67
67
|
end
|
68
68
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class ElasticsearchSpy
|
8
8
|
NAME_FORMAT = '%s %s'.freeze
|
9
9
|
TYPE = 'db.elasticsearch'.freeze
|
10
10
|
|
@@ -27,7 +27,7 @@ module ElasticAPM
|
|
27
27
|
register(
|
28
28
|
'Elasticsearch::Transport::Client',
|
29
29
|
'elasticsearch-transport',
|
30
|
-
|
30
|
+
ElasticsearchSpy.new
|
31
31
|
)
|
32
32
|
end
|
33
33
|
end
|
@@ -4,9 +4,9 @@ require 'elastic_apm/span_helpers'
|
|
4
4
|
|
5
5
|
module ElasticAPM
|
6
6
|
# @api private
|
7
|
-
module
|
7
|
+
module Spies
|
8
8
|
# @api private
|
9
|
-
class
|
9
|
+
class JSONSpy
|
10
10
|
def install
|
11
11
|
::JSON.class_eval do
|
12
12
|
include SpanHelpers
|
@@ -17,6 +17,6 @@ module ElasticAPM
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
register 'JSON', 'json',
|
20
|
+
register 'JSON', 'json', JSONSpy.new
|
21
21
|
end
|
22
22
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class MongoSpy
|
8
8
|
def install
|
9
9
|
::Mongo::Monitoring::Global.subscribe(
|
10
10
|
::Mongo::Monitoring::COMMAND,
|
@@ -35,6 +35,8 @@ module ElasticAPM
|
|
35
35
|
private
|
36
36
|
|
37
37
|
def push_event(event)
|
38
|
+
return unless ElasticAPM.current_transaction
|
39
|
+
|
38
40
|
ctx = Span::Context.new(
|
39
41
|
instance: event.database_name,
|
40
42
|
statement: nil,
|
@@ -46,12 +48,14 @@ module ElasticAPM
|
|
46
48
|
end
|
47
49
|
|
48
50
|
def pop_event(event)
|
49
|
-
|
50
|
-
|
51
|
+
return unless ElasticAPM.current_transaction
|
52
|
+
|
53
|
+
span = @events.delete(event.operation_id)
|
54
|
+
span && span.done
|
51
55
|
end
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
|
-
register 'Mongo', 'mongo',
|
59
|
+
register 'Mongo', 'mongo', MongoSpy.new
|
56
60
|
end
|
57
61
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class NetHTTPSpy
|
8
8
|
# rubocop:disable Metrics/MethodLength
|
9
9
|
def install
|
10
10
|
Net::HTTP.class_eval do
|
@@ -32,6 +32,6 @@ module ElasticAPM
|
|
32
32
|
# rubocop:enable Metrics/MethodLength
|
33
33
|
end
|
34
34
|
|
35
|
-
register 'Net::HTTP', 'net/http',
|
35
|
+
register 'Net::HTTP', 'net/http', NetHTTPSpy.new
|
36
36
|
end
|
37
37
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class RedisSpy
|
8
8
|
def install
|
9
9
|
::Redis::Client.class_eval do
|
10
10
|
alias call_without_apm call
|
@@ -22,6 +22,6 @@ module ElasticAPM
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
register 'Redis', 'redis',
|
25
|
+
register 'Redis', 'redis', RedisSpy.new
|
26
26
|
end
|
27
27
|
end
|
@@ -4,9 +4,9 @@ require 'elastic_apm/sql_summarizer'
|
|
4
4
|
|
5
5
|
module ElasticAPM
|
6
6
|
# @api private
|
7
|
-
module
|
7
|
+
module Spies
|
8
8
|
# @api private
|
9
|
-
class
|
9
|
+
class SequelSpy
|
10
10
|
TYPE = 'db.sequel.sql'.freeze
|
11
11
|
|
12
12
|
def self.summarizer
|
@@ -25,7 +25,7 @@ module ElasticAPM
|
|
25
25
|
return log_connection_yield_without_apm(sql, *args, &block)
|
26
26
|
end
|
27
27
|
|
28
|
-
summarizer = ElasticAPM::
|
28
|
+
summarizer = ElasticAPM::Spies::SequelSpy.summarizer
|
29
29
|
name = summarizer.summarize sql
|
30
30
|
context = Span::Context.new(
|
31
31
|
statement: sql,
|
@@ -40,6 +40,6 @@ module ElasticAPM
|
|
40
40
|
# rubocop:enable Metrics/MethodLength
|
41
41
|
end
|
42
42
|
|
43
|
-
register 'Sequel', 'sequel',
|
43
|
+
register 'Sequel', 'sequel', SequelSpy.new
|
44
44
|
end
|
45
45
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class SidekiqSpy
|
8
8
|
ACTIVE_JOB_WRAPPER =
|
9
9
|
'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper'.freeze
|
10
10
|
|
@@ -12,7 +12,7 @@ module ElasticAPM
|
|
12
12
|
class Middleware
|
13
13
|
# rubocop:disable Metrics/MethodLength
|
14
14
|
def call(_worker, job, queue)
|
15
|
-
name =
|
15
|
+
name = SidekiqSpy.name_for(job)
|
16
16
|
transaction = ElasticAPM.transaction(name, 'Sidekiq')
|
17
17
|
ElasticAPM.set_tag(:queue, queue)
|
18
18
|
|
@@ -58,10 +58,13 @@ module ElasticAPM
|
|
58
58
|
|
59
59
|
def start
|
60
60
|
result = start_without_apm
|
61
|
-
ElasticAPM.start # might already be running from railtie
|
62
61
|
|
63
|
-
|
64
|
-
ElasticAPM.
|
62
|
+
# Already running from Railtie if Rails
|
63
|
+
if ElasticAPM.running?
|
64
|
+
ElasticAPM.agent.config.logger = Sidekiq.logger
|
65
|
+
else
|
66
|
+
ElasticAPM.start
|
67
|
+
end
|
65
68
|
|
66
69
|
result
|
67
70
|
end
|
@@ -81,6 +84,6 @@ module ElasticAPM
|
|
81
84
|
end
|
82
85
|
end
|
83
86
|
|
84
|
-
register 'Sidekiq', 'sidekiq',
|
87
|
+
register 'Sidekiq', 'sidekiq', SidekiqSpy.new
|
85
88
|
end
|
86
89
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class SinatraSpy
|
8
8
|
# rubocop:disable Metrics/MethodLength
|
9
9
|
def install
|
10
10
|
::Sinatra::Base.class_eval do
|
@@ -34,8 +34,8 @@ module ElasticAPM
|
|
34
34
|
# rubocop:enable Metrics/MethodLength
|
35
35
|
end
|
36
36
|
|
37
|
-
register 'Sinatra::Base', 'sinatra/base',
|
37
|
+
register 'Sinatra::Base', 'sinatra/base', SinatraSpy.new
|
38
38
|
|
39
|
-
require 'elastic_apm/
|
39
|
+
require 'elastic_apm/spies/tilt'
|
40
40
|
end
|
41
41
|
end
|
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
4
|
# @api private
|
5
|
-
module
|
5
|
+
module Spies
|
6
6
|
# @api private
|
7
|
-
class
|
7
|
+
class TiltSpy
|
8
8
|
TYPE = 'template.tilt'.freeze
|
9
9
|
|
10
10
|
def install
|
@@ -22,6 +22,6 @@ module ElasticAPM
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
register 'Tilt::Template', 'tilt/template',
|
25
|
+
register 'Tilt::Template', 'tilt/template', TiltSpy.new
|
26
26
|
end
|
27
27
|
end
|
@@ -5,11 +5,16 @@ require 'elastic_apm/util/lru_cache'
|
|
5
5
|
module ElasticAPM
|
6
6
|
# @api private
|
7
7
|
class SqlSummarizer
|
8
|
+
DEFAULT = 'SQL'.freeze
|
9
|
+
TABLE_REGEX = %{["'`]?([A-Za-z0-9]+)}.freeze
|
10
|
+
|
8
11
|
REGEXES = {
|
9
|
-
/^
|
10
|
-
/^
|
11
|
-
/^
|
12
|
-
/^
|
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 '
|
13
18
|
}.freeze
|
14
19
|
|
15
20
|
FORMAT = '%s%s'.freeze
|
@@ -24,7 +29,7 @@ module ElasticAPM
|
|
24
29
|
if (match = sql.match(regex))
|
25
30
|
break format(FORMAT, sig, match[1].gsub(/["']/, ''))
|
26
31
|
end
|
27
|
-
end
|
32
|
+
end || DEFAULT
|
28
33
|
end
|
29
34
|
end
|
30
35
|
end
|
@@ -1,36 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'elastic_apm/stacktrace/frame'
|
4
|
-
require 'elastic_apm/stacktrace/line_cache'
|
5
|
-
|
6
3
|
module ElasticAPM
|
7
4
|
# @api private
|
8
5
|
class Stacktrace
|
9
|
-
|
10
|
-
RUBY_FORMAT = /^(.+?):(\d+)(?::in `(.+?)')?$/
|
11
|
-
|
12
|
-
RUBY_VERS_REGEX = %r{ruby(/gems)?[-/](\d+\.)+\d}
|
13
|
-
JRUBY_ORG_REGEX = %r{org/jruby}
|
14
|
-
|
15
|
-
def initialize(backtrace)
|
16
|
-
@backtrace = backtrace
|
17
|
-
end
|
18
|
-
|
19
|
-
attr_reader :frames
|
20
|
-
|
21
|
-
def self.build(config, backtrace, type)
|
22
|
-
return nil unless backtrace
|
23
|
-
|
24
|
-
stack = new(backtrace)
|
25
|
-
stack.build_frames(config, type)
|
26
|
-
stack
|
27
|
-
end
|
28
|
-
|
29
|
-
def build_frames(config, type)
|
30
|
-
@frames = @backtrace.map do |line|
|
31
|
-
build_frame(config, line, type)
|
32
|
-
end
|
33
|
-
end
|
6
|
+
attr_accessor :frames
|
34
7
|
|
35
8
|
def length
|
36
9
|
frames.length
|
@@ -39,82 +12,5 @@ module ElasticAPM
|
|
39
12
|
def to_a
|
40
13
|
frames.map(&:to_h)
|
41
14
|
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def parse_line(line)
|
46
|
-
ruby_match = line.match(RUBY_FORMAT)
|
47
|
-
|
48
|
-
if ruby_match
|
49
|
-
_, file, number, method = ruby_match.to_a
|
50
|
-
file.sub!(/\.class$/, '.rb')
|
51
|
-
module_name = nil
|
52
|
-
else
|
53
|
-
java_match = line.match(JAVA_FORMAT)
|
54
|
-
_, module_name, method, file, number = java_match.to_a
|
55
|
-
end
|
56
|
-
|
57
|
-
[file, number, method, module_name]
|
58
|
-
end
|
59
|
-
|
60
|
-
def library_frame?(config, abs_path)
|
61
|
-
return false unless abs_path
|
62
|
-
|
63
|
-
if abs_path.start_with?(config.root_path)
|
64
|
-
return true if abs_path.start_with?(config.root_path + '/vendor')
|
65
|
-
return false
|
66
|
-
end
|
67
|
-
|
68
|
-
return true if abs_path.match(RUBY_VERS_REGEX)
|
69
|
-
return true if abs_path.match(JRUBY_ORG_REGEX)
|
70
|
-
|
71
|
-
false
|
72
|
-
end
|
73
|
-
|
74
|
-
class << self
|
75
|
-
attr_accessor :frame_cache
|
76
|
-
end
|
77
|
-
|
78
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
79
|
-
def build_frame(config, line, type)
|
80
|
-
# TODO: Eventually move this to agent 'context'
|
81
|
-
self.class.frame_cache ||= Util::LruCache.new(2048) do |cache, keys|
|
82
|
-
line, type = keys
|
83
|
-
abs_path, lineno, function, _module_name = parse_line(line)
|
84
|
-
|
85
|
-
frame = Frame.new
|
86
|
-
frame.abs_path = abs_path
|
87
|
-
frame.filename = strip_load_path(abs_path)
|
88
|
-
frame.function = function
|
89
|
-
frame.lineno = lineno.to_i
|
90
|
-
frame.library_frame = library_frame?(config, abs_path)
|
91
|
-
|
92
|
-
line_count =
|
93
|
-
context_lines_for(config, type, library_frame: frame.library_frame)
|
94
|
-
frame.build_context line_count
|
95
|
-
|
96
|
-
cache[[line, type]] = frame
|
97
|
-
end
|
98
|
-
|
99
|
-
self.class.frame_cache[[line, type]]
|
100
|
-
end
|
101
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
102
|
-
|
103
|
-
def strip_load_path(path)
|
104
|
-
return nil if path.nil?
|
105
|
-
|
106
|
-
prefix =
|
107
|
-
$LOAD_PATH
|
108
|
-
.map(&:to_s)
|
109
|
-
.select { |s| path.start_with?(s) }
|
110
|
-
.max_by(&:length)
|
111
|
-
|
112
|
-
prefix ? path[prefix.chomp(File::SEPARATOR).length + 1..-1] : path
|
113
|
-
end
|
114
|
-
|
115
|
-
def context_lines_for(config, type, library_frame:)
|
116
|
-
key = "source_lines_#{type}_#{library_frame ? 'library' : 'app'}_frames"
|
117
|
-
config.send(key.to_sym)
|
118
|
-
end
|
119
15
|
end
|
120
16
|
end
|
@@ -38,11 +38,7 @@ module ElasticAPM
|
|
38
38
|
private
|
39
39
|
|
40
40
|
def read_lines(path, range)
|
41
|
-
|
42
|
-
return cached
|
43
|
-
end
|
44
|
-
|
45
|
-
LineCache.set(path, range, File.readlines(path)[range]) || []
|
41
|
+
File.readlines(path)[range]
|
46
42
|
rescue Errno::ENOENT
|
47
43
|
[]
|
48
44
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'elastic_apm/stacktrace/frame'
|
4
|
+
require 'elastic_apm/util/lru_cache'
|
5
|
+
|
6
|
+
module ElasticAPM
|
7
|
+
# @api private
|
8
|
+
class StacktraceBuilder
|
9
|
+
JAVA_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/
|
10
|
+
RUBY_FORMAT = /^(.+?):(\d+)(?::in `(.+?)')?$/
|
11
|
+
|
12
|
+
RUBY_VERS_REGEX = %r{ruby(/gems)?[-/](\d+\.)+\d}
|
13
|
+
JRUBY_ORG_REGEX = %r{org/jruby}
|
14
|
+
|
15
|
+
def initialize(agent)
|
16
|
+
@config = agent.config
|
17
|
+
@cache = Util::LruCache.new(2048, &method(:build_frame))
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :config
|
21
|
+
|
22
|
+
def build(backtrace, type:)
|
23
|
+
Stacktrace.new.tap do |s|
|
24
|
+
s.frames = backtrace.map do |line|
|
25
|
+
@cache[[line, type]]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
33
|
+
def build_frame(cache, keys)
|
34
|
+
line, type = keys
|
35
|
+
abs_path, lineno, function, _module_name = parse_line(line)
|
36
|
+
|
37
|
+
frame = Stacktrace::Frame.new
|
38
|
+
frame.abs_path = abs_path
|
39
|
+
frame.filename = strip_load_path(abs_path)
|
40
|
+
frame.function = function
|
41
|
+
frame.lineno = lineno.to_i
|
42
|
+
frame.library_frame = library_frame?(config, abs_path)
|
43
|
+
|
44
|
+
line_count =
|
45
|
+
context_lines_for(config, type, library_frame: frame.library_frame)
|
46
|
+
frame.build_context line_count
|
47
|
+
|
48
|
+
cache[[line, type]] = frame
|
49
|
+
end
|
50
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
51
|
+
|
52
|
+
def parse_line(line)
|
53
|
+
ruby_match = line.match(RUBY_FORMAT)
|
54
|
+
|
55
|
+
if ruby_match
|
56
|
+
_, file, number, method = ruby_match.to_a
|
57
|
+
file.sub!(/\.class$/, '.rb')
|
58
|
+
module_name = nil
|
59
|
+
else
|
60
|
+
java_match = line.match(JAVA_FORMAT)
|
61
|
+
_, module_name, method, file, number = java_match.to_a
|
62
|
+
end
|
63
|
+
|
64
|
+
[file, number, method, module_name]
|
65
|
+
end
|
66
|
+
|
67
|
+
def library_frame?(config, abs_path)
|
68
|
+
return false unless abs_path
|
69
|
+
|
70
|
+
if abs_path.start_with?(config.root_path)
|
71
|
+
return true if abs_path.start_with?(config.root_path + '/vendor')
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
|
75
|
+
return true if abs_path.match(RUBY_VERS_REGEX)
|
76
|
+
return true if abs_path.match(JRUBY_ORG_REGEX)
|
77
|
+
|
78
|
+
false
|
79
|
+
end
|
80
|
+
|
81
|
+
def strip_load_path(path)
|
82
|
+
return nil if path.nil?
|
83
|
+
|
84
|
+
prefix =
|
85
|
+
$LOAD_PATH
|
86
|
+
.map(&:to_s)
|
87
|
+
.select { |s| path.start_with?(s) }
|
88
|
+
.max_by(&:length)
|
89
|
+
|
90
|
+
prefix ? path[prefix.chomp(File::SEPARATOR).length + 1..-1] : path
|
91
|
+
end
|
92
|
+
|
93
|
+
def context_lines_for(config, type, library_frame:)
|
94
|
+
key = "source_lines_#{type}_#{library_frame ? 'library' : 'app'}_frames"
|
95
|
+
config.send(key.to_sym)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -8,10 +8,9 @@ module ElasticAPM
|
|
8
8
|
class Subscriber
|
9
9
|
include Log
|
10
10
|
|
11
|
-
def initialize(
|
12
|
-
@config = config
|
11
|
+
def initialize(agent)
|
13
12
|
@agent = agent
|
14
|
-
@normalizers = Normalizers.build(config)
|
13
|
+
@normalizers = Normalizers.build(agent.config)
|
15
14
|
end
|
16
15
|
|
17
16
|
def register!
|
@@ -75,6 +75,7 @@ module ElasticAPM
|
|
75
75
|
@adapter.post('/v1/errors', payload)
|
76
76
|
end
|
77
77
|
|
78
|
+
# rubocop:disable Metrics/MethodLength
|
78
79
|
def collect_and_send_transactions
|
79
80
|
return if pending_transactions.empty?
|
80
81
|
|
@@ -89,7 +90,10 @@ module ElasticAPM
|
|
89
90
|
debug e.backtrace.join("\n")
|
90
91
|
nil
|
91
92
|
end
|
93
|
+
|
94
|
+
@last_sent_transactions = Time.now
|
92
95
|
end
|
96
|
+
# rubocop:enable Metrics/MethodLength
|
93
97
|
|
94
98
|
def collect_batched_transactions
|
95
99
|
batch = []
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ElasticAPM
|
4
|
+
# rubocop:disable Metrics/ClassLength
|
4
5
|
# @api private
|
5
6
|
class Transaction
|
6
7
|
DEFAULT_TYPE = 'custom'.freeze
|
@@ -103,8 +104,10 @@ module ElasticAPM
|
|
103
104
|
span = next_span(name, type, context)
|
104
105
|
spans << span
|
105
106
|
|
106
|
-
|
107
|
-
|
107
|
+
if backtrace
|
108
|
+
span.stacktrace =
|
109
|
+
@instrumenter.agent.stacktrace_builder.build(backtrace, type: :span)
|
110
|
+
end
|
108
111
|
|
109
112
|
span.start
|
110
113
|
end
|
@@ -141,4 +144,5 @@ module ElasticAPM
|
|
141
144
|
)
|
142
145
|
end
|
143
146
|
end
|
147
|
+
# rubocop:enable Metrics/ClassLength
|
144
148
|
end
|
@@ -1,14 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ElasticAPM
|
4
|
+
# rubocop:disable all
|
2
5
|
module Util
|
3
|
-
#
|
6
|
+
# From https://github.com/rails/rails/blob/v5.2.0/activesupport/lib/active_support/inflector/methods.rb#L254-L332
|
4
7
|
module Inflector
|
5
|
-
|
6
|
-
|
8
|
+
extend self
|
9
|
+
|
7
10
|
#
|
8
11
|
# Tries to find a constant with the name specified in the argument string.
|
9
12
|
#
|
10
|
-
# 'Module'
|
11
|
-
# '
|
13
|
+
# constantize('Module') # => Module
|
14
|
+
# constantize('Foo::Bar') # => Foo::Bar
|
12
15
|
#
|
13
16
|
# The name is assumed to be the one of a top-level constant, no matter
|
14
17
|
# whether it starts with "::" or not. No lexical context is taken into
|
@@ -17,14 +20,14 @@ module ElasticAPM
|
|
17
20
|
# C = 'outside'
|
18
21
|
# module M
|
19
22
|
# C = 'inside'
|
20
|
-
# C
|
21
|
-
# 'C'
|
23
|
+
# C # => 'inside'
|
24
|
+
# constantize('C') # => 'outside', same as ::C
|
22
25
|
# end
|
23
26
|
#
|
24
27
|
# NameError is raised when the name is not in CamelCase or the constant is
|
25
28
|
# unknown.
|
26
|
-
def
|
27
|
-
names = camel_cased_word.split(
|
29
|
+
def constantize(camel_cased_word)
|
30
|
+
names = camel_cased_word.split("::".freeze)
|
28
31
|
|
29
32
|
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
30
33
|
Object.const_get(camel_cased_word) if names.empty?
|
@@ -42,7 +45,7 @@ module ElasticAPM
|
|
42
45
|
|
43
46
|
# Go down the ancestors to check if it is owned directly. The check
|
44
47
|
# stops when we reach Object or the end of ancestors tree.
|
45
|
-
constant = constant.ancestors.inject do |const, ancestor|
|
48
|
+
constant = constant.ancestors.inject(constant) do |const, ancestor|
|
46
49
|
break const if ancestor == Object
|
47
50
|
break ancestor if ancestor.const_defined?(name, false)
|
48
51
|
const
|
@@ -53,7 +56,38 @@ module ElasticAPM
|
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|
56
|
-
|
59
|
+
|
60
|
+
# Tries to find a constant with the name specified in the argument string.
|
61
|
+
#
|
62
|
+
# safe_constantize('Module') # => Module
|
63
|
+
# safe_constantize('Foo::Bar') # => Foo::Bar
|
64
|
+
#
|
65
|
+
# The name is assumed to be the one of a top-level constant, no matter
|
66
|
+
# whether it starts with "::" or not. No lexical context is taken into
|
67
|
+
# account:
|
68
|
+
#
|
69
|
+
# C = 'outside'
|
70
|
+
# module M
|
71
|
+
# C = 'inside'
|
72
|
+
# C # => 'inside'
|
73
|
+
# safe_constantize('C') # => 'outside', same as ::C
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# +nil+ is returned when the name is not in CamelCase or the constant (or
|
77
|
+
# part of it) is unknown.
|
78
|
+
#
|
79
|
+
# safe_constantize('blargle') # => nil
|
80
|
+
# safe_constantize('UnknownModule') # => nil
|
81
|
+
# safe_constantize('UnknownModule::Foo::Bar') # => nil
|
82
|
+
def safe_constantize(camel_cased_word)
|
83
|
+
constantize(camel_cased_word)
|
84
|
+
rescue NameError => e
|
85
|
+
raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
|
86
|
+
e.name.to_s == camel_cased_word.to_s)
|
87
|
+
rescue ArgumentError => e
|
88
|
+
raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message)
|
89
|
+
end
|
57
90
|
end
|
58
91
|
end
|
92
|
+
# rubocop:enable all
|
59
93
|
end
|
data/lib/elastic_apm/version.rb
CHANGED
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elastic-apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikkel Malmberg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 3.0.0
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 3.0.0
|
11
|
+
date: 2018-05-16 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
27
13
|
description:
|
28
14
|
email:
|
29
15
|
- mikkel@elastic.co
|
@@ -71,18 +57,6 @@ files:
|
|
71
57
|
- lib/elastic_apm/filters/request_body_filter.rb
|
72
58
|
- lib/elastic_apm/filters/secrets_filter.rb
|
73
59
|
- lib/elastic_apm/http.rb
|
74
|
-
- lib/elastic_apm/injectors.rb
|
75
|
-
- lib/elastic_apm/injectors/action_dispatch.rb
|
76
|
-
- lib/elastic_apm/injectors/delayed_job.rb
|
77
|
-
- lib/elastic_apm/injectors/elasticsearch.rb
|
78
|
-
- lib/elastic_apm/injectors/json.rb
|
79
|
-
- lib/elastic_apm/injectors/mongo.rb
|
80
|
-
- lib/elastic_apm/injectors/net_http.rb
|
81
|
-
- lib/elastic_apm/injectors/redis.rb
|
82
|
-
- lib/elastic_apm/injectors/sequel.rb
|
83
|
-
- lib/elastic_apm/injectors/sidekiq.rb
|
84
|
-
- lib/elastic_apm/injectors/sinatra.rb
|
85
|
-
- lib/elastic_apm/injectors/tilt.rb
|
86
60
|
- lib/elastic_apm/instrumenter.rb
|
87
61
|
- lib/elastic_apm/internal_error.rb
|
88
62
|
- lib/elastic_apm/log.rb
|
@@ -102,10 +76,22 @@ files:
|
|
102
76
|
- lib/elastic_apm/span.rb
|
103
77
|
- lib/elastic_apm/span/context.rb
|
104
78
|
- lib/elastic_apm/span_helpers.rb
|
79
|
+
- lib/elastic_apm/spies.rb
|
80
|
+
- lib/elastic_apm/spies/action_dispatch.rb
|
81
|
+
- lib/elastic_apm/spies/delayed_job.rb
|
82
|
+
- lib/elastic_apm/spies/elasticsearch.rb
|
83
|
+
- lib/elastic_apm/spies/json.rb
|
84
|
+
- lib/elastic_apm/spies/mongo.rb
|
85
|
+
- lib/elastic_apm/spies/net_http.rb
|
86
|
+
- lib/elastic_apm/spies/redis.rb
|
87
|
+
- lib/elastic_apm/spies/sequel.rb
|
88
|
+
- lib/elastic_apm/spies/sidekiq.rb
|
89
|
+
- lib/elastic_apm/spies/sinatra.rb
|
90
|
+
- lib/elastic_apm/spies/tilt.rb
|
105
91
|
- lib/elastic_apm/sql_summarizer.rb
|
106
92
|
- lib/elastic_apm/stacktrace.rb
|
107
93
|
- lib/elastic_apm/stacktrace/frame.rb
|
108
|
-
- lib/elastic_apm/
|
94
|
+
- lib/elastic_apm/stacktrace_builder.rb
|
109
95
|
- lib/elastic_apm/subscriber.rb
|
110
96
|
- lib/elastic_apm/system_info.rb
|
111
97
|
- lib/elastic_apm/timed_worker.rb
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'elastic_apm/util/lru_cache'
|
4
|
-
|
5
|
-
module ElasticAPM
|
6
|
-
class Stacktrace
|
7
|
-
# A basic LRU Cache
|
8
|
-
# @api private
|
9
|
-
class LineCache
|
10
|
-
class << self
|
11
|
-
def cache
|
12
|
-
@cache ||= Util::LruCache.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def get(*key)
|
16
|
-
cache[key]
|
17
|
-
end
|
18
|
-
|
19
|
-
def set(*key, value)
|
20
|
-
cache[key] = value
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|