scout_apm 0.1.12 → 0.1.13
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.markdown +4 -0
- data/lib/scout_apm/agent/logging.rb +1 -1
- data/lib/scout_apm/agent.rb +14 -8
- data/lib/scout_apm/background_worker.rb +37 -32
- data/lib/scout_apm/capacity.rb +44 -42
- data/lib/scout_apm/environment.rb +1 -19
- data/lib/scout_apm/framework_integrations/rails_2.rb +24 -0
- data/lib/scout_apm/framework_integrations/rails_3_or_4.rb +21 -0
- data/lib/scout_apm/framework_integrations/ruby.rb +5 -0
- data/lib/scout_apm/framework_integrations/sinatra.rb +5 -0
- data/lib/scout_apm/instruments/action_controller_rails_2.rb +68 -0
- data/lib/scout_apm/instruments/action_controller_rails_3.rb +64 -0
- data/lib/scout_apm/instruments/{active_record_instruments.rb → active_record.rb} +43 -22
- data/lib/scout_apm/instruments/mongoid.rb +34 -0
- data/lib/scout_apm/instruments/moped.rb +49 -0
- data/lib/scout_apm/instruments/net_http.rb +33 -10
- data/lib/scout_apm/layaway.rb +82 -78
- data/lib/scout_apm/layaway_file.rb +59 -57
- data/lib/scout_apm/server_integrations/unicorn.rb +9 -1
- data/lib/scout_apm/store.rb +193 -184
- data/lib/scout_apm/utils/time.rb +12 -0
- data/lib/scout_apm/version.rb +1 -1
- data/lib/scout_apm.rb +11 -3
- metadata +8 -7
- data/lib/scout_apm/instruments/mongoid_instruments.rb +0 -10
- data/lib/scout_apm/instruments/moped_instruments.rb +0 -24
- data/lib/scout_apm/instruments/rails/action_controller_instruments.rb +0 -48
- data/lib/scout_apm/instruments/rails3_or_4/action_controller_instruments.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9959104d4317f9bb646443606363b67e7a33b4f9
|
4
|
+
data.tar.gz: 866026e27f92c5607fbf8bcf15f6f921bcbc7786
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05a3afbfa039ec01f844940000910689753579311313d386f8487b5e69413bce155ee11103b92fd808b93a0ba801cbf58fbfe195b9ecff7e62c012c9d5251f51
|
7
|
+
data.tar.gz: 7e6b9e8da470b075e6df0a7d4b9974939f11a1aaef323f3eff12f567561718627325ba6b64c76189557c8461f92f32ad966b8d85ce731fdea1ee3b4b934c98e7
|
data/CHANGELOG.markdown
CHANGED
@@ -32,7 +32,7 @@ module ScoutApm
|
|
32
32
|
def logger.format_message(severity, timestamp, progname, msg)
|
33
33
|
# since STDOUT isn't exclusive like the scout_apm.log file, apply a prefix.
|
34
34
|
prefix = @logdev.dev == STDOUT ? "[Scout] " : ''
|
35
|
-
prefix + "[#{
|
35
|
+
prefix + "[#{Utils::Time.to_s(timestamp)} #{ScoutApm::Agent.instance.environment.hostname} (#{$$})] #{severity} : #{msg}\n"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
data/lib/scout_apm/agent.rb
CHANGED
@@ -36,6 +36,7 @@ module ScoutApm
|
|
36
36
|
@metric_lookup = Hash.new
|
37
37
|
|
38
38
|
@capacity = ScoutApm::Capacity.new
|
39
|
+
@installed_instruments = []
|
39
40
|
end
|
40
41
|
|
41
42
|
def environment
|
@@ -176,19 +177,24 @@ module ScoutApm
|
|
176
177
|
logger.debug "Installing instrumentation"
|
177
178
|
|
178
179
|
case environment.framework
|
179
|
-
when :rails
|
180
|
-
|
181
|
-
when :rails3_or_4
|
182
|
-
require File.expand_path(File.join(File.dirname(__FILE__),'instruments/rails3_or_4/action_controller_instruments.rb'))
|
180
|
+
when :rails then install_instrument(ScoutApm::Instruments::ActionControllerRails2)
|
181
|
+
when :rails3_or_4 then install_instrument(ScoutApm::Instruments::ActionControllerRails3)
|
183
182
|
end
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
183
|
+
|
184
|
+
install_instrument(ScoutApm::Instruments::ActiveRecord)
|
185
|
+
install_instrument(ScoutApm::Instruments::Moped)
|
186
|
+
install_instrument(ScoutApm::Instruments::Mongoid)
|
187
|
+
install_instrument(ScoutApm::Instruments::NetHttp)
|
188
188
|
rescue
|
189
189
|
logger.warn "Exception loading instruments:"
|
190
190
|
logger.warn $!.message
|
191
191
|
logger.warn $!.backtrace
|
192
192
|
end
|
193
|
+
|
194
|
+
def install_instrument(instrument_klass)
|
195
|
+
instance = instrument_klass.new
|
196
|
+
@installed_instruments << instance
|
197
|
+
instance.install
|
198
|
+
end
|
193
199
|
end
|
194
200
|
end
|
@@ -1,43 +1,48 @@
|
|
1
1
|
# Used to run a given task every 60 seconds.
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
module ScoutApm
|
3
|
+
class BackgroundWorker
|
4
|
+
# in seconds, time between when the worker thread wakes up and runs.
|
5
|
+
DEFAULT_PERIOD = 60
|
5
6
|
|
6
|
-
|
7
|
-
@keep_running = true
|
8
|
-
end
|
7
|
+
attr_reader :period
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def initialize(period=DEFAULT_PERIOD)
|
10
|
+
@period = period
|
11
|
+
@keep_running = true
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def stop
|
15
|
+
@keep_running = false
|
16
|
+
end
|
17
|
+
|
18
|
+
# Runs the task passed to +start+ once.
|
19
|
+
def run_once
|
20
|
+
@task.call if @task
|
21
|
+
end
|
18
22
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
now = Time.now
|
27
|
-
while now < next_time
|
28
|
-
sleep_time = next_time - now
|
29
|
-
sleep(sleep_time) if sleep_time > 0
|
23
|
+
# Starts running the passed block every 60 seconds (starting now).
|
24
|
+
def start(&block)
|
25
|
+
@task = block
|
26
|
+
begin
|
27
|
+
ScoutApm::Agent.instance.logger.debug "Starting Background Worker, running every #{period} seconds"
|
28
|
+
next_time = Time.now
|
29
|
+
while @keep_running do
|
30
30
|
now = Time.now
|
31
|
+
while now < next_time
|
32
|
+
sleep_time = next_time - now
|
33
|
+
sleep(sleep_time) if sleep_time > 0
|
34
|
+
now = Time.now
|
35
|
+
end
|
36
|
+
@task.call
|
37
|
+
while next_time <= now
|
38
|
+
next_time += period
|
39
|
+
end
|
31
40
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
41
|
+
rescue
|
42
|
+
ScoutApm::Agent.instance.logger.debug "Background Worker Exception!!!!!!!"
|
43
|
+
ScoutApm::Agent.instance.logger.debug $!.message
|
44
|
+
ScoutApm::Agent.instance.logger.debug $!.backtrace
|
36
45
|
end
|
37
|
-
rescue
|
38
|
-
ScoutApm::Agent.instance.logger.debug "Background Worker Exception!!!!!!!"
|
39
|
-
ScoutApm::Agent.instance.logger.debug $!.message
|
40
|
-
ScoutApm::Agent.instance.logger.debug $!.backtrace
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
data/lib/scout_apm/capacity.rb
CHANGED
@@ -1,54 +1,56 @@
|
|
1
1
|
# Encapsulates logic for determining capacity utilization of the Ruby processes.
|
2
|
-
|
3
|
-
|
2
|
+
module ScoutApm
|
3
|
+
class Capacity
|
4
|
+
attr_reader :processing_start_time, :accumulated_time, :transaction_entry_time
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
|
11
|
-
# Called when a transaction is traced.
|
12
|
-
def start_transaction!
|
13
|
-
@lock.synchronize do
|
14
|
-
@transaction_entry_time = Time.now
|
6
|
+
def initialize
|
7
|
+
@processing_start_time = Time.now
|
8
|
+
@lock ||= Mutex.new # the transaction_entry_time could be modified while processing a request or when #process is called.
|
9
|
+
@accumulated_time = 0.0
|
15
10
|
end
|
16
|
-
end
|
17
11
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@accumulated_time += (Time.now - transaction_entry_time).to_f
|
23
|
-
else
|
24
|
-
ScoutApm::Agent.instance.logger.warn "No transaction entry time. Not recording capacity metrics for transaction."
|
12
|
+
# Called when a transaction is traced.
|
13
|
+
def start_transaction!
|
14
|
+
@lock.synchronize do
|
15
|
+
@transaction_entry_time = Time.now
|
25
16
|
end
|
26
|
-
@transaction_entry_time = nil
|
27
17
|
end
|
28
|
-
end
|
29
18
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if @transaction_entry_time
|
40
|
-
time_spent += (process_time - @transaction_entry_time).to_f
|
41
|
-
ScoutApm::Agent.instance.logger.debug "A transaction is running while calculating capacity. Start time: [#{transaction_entry_time}]. Will update the entry time to [#{process_time}]."
|
42
|
-
@transaction_entry_time = process_time # prevent from over-counting capacity usage. update the transaction start time to now.
|
19
|
+
# Called when a transaction completes to record its time used.
|
20
|
+
def finish_transaction!
|
21
|
+
@lock.synchronize do
|
22
|
+
if transaction_entry_time
|
23
|
+
@accumulated_time += (Time.now - transaction_entry_time).to_f
|
24
|
+
else
|
25
|
+
ScoutApm::Agent.instance.logger.warn "No transaction entry time. Not recording capacity metrics for transaction."
|
26
|
+
end
|
27
|
+
@transaction_entry_time = nil
|
43
28
|
end
|
44
|
-
|
29
|
+
end
|
45
30
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
ScoutApm::Agent.instance.logger.debug "
|
50
|
-
|
51
|
-
|
31
|
+
# Ran when sending metrics to server. Reports capacity usage metrics.
|
32
|
+
def process
|
33
|
+
process_time = Time.now
|
34
|
+
ScoutApm::Agent.instance.logger.debug "Processing capacity usage for [#{@processing_start_time}] to [#{process_time}]. Time Spent: #{@accumulated_time}."
|
35
|
+
@lock.synchronize do
|
36
|
+
time_spent = @accumulated_time
|
37
|
+
@accumulated_time = 0.0
|
38
|
+
# If a transaction is still running, capture its running time up to now and
|
39
|
+
# reset the +transaction_entry_time+ to now.
|
40
|
+
if @transaction_entry_time
|
41
|
+
time_spent += (process_time - @transaction_entry_time).to_f
|
42
|
+
ScoutApm::Agent.instance.logger.debug "A transaction is running while calculating capacity. Start time: [#{transaction_entry_time}]. Will update the entry time to [#{process_time}]."
|
43
|
+
@transaction_entry_time = process_time # prevent from over-counting capacity usage. update the transaction start time to now.
|
44
|
+
end
|
45
|
+
time_spent = 0.0 if time_spent < 0.0
|
46
|
+
|
47
|
+
window = (process_time - processing_start_time).to_f # time period we are evaulating capacity usage.
|
48
|
+
window = 1.0 if window <= 0.0 # prevent divide-by-zero if clock adjusted.
|
49
|
+
capacity = time_spent / window
|
50
|
+
ScoutApm::Agent.instance.logger.debug "Instance/Capacity: #{capacity}"
|
51
|
+
ScoutApm::Agent.instance.store.track!("Instance/Capacity",capacity,:scope => nil)
|
52
|
+
@processing_start_time = process_time
|
53
|
+
end
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
@@ -41,25 +41,7 @@ module ScoutApm
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def database_engine
|
44
|
-
|
45
|
-
|
46
|
-
if defined?(ActiveRecord::Base)
|
47
|
-
config = ActiveRecord::Base.connection_config
|
48
|
-
if config && config[:adapter]
|
49
|
-
case config[:adapter]
|
50
|
-
when "postgres" then :postgres
|
51
|
-
when "postgresql" then :postgres
|
52
|
-
when "sqlite3" then :sqlite
|
53
|
-
when "mysql" then :mysql
|
54
|
-
else default
|
55
|
-
end
|
56
|
-
else
|
57
|
-
default
|
58
|
-
end
|
59
|
-
else
|
60
|
-
# TODO: Figure out how to detect outside of Rails context. (sequel, ROM, etc)
|
61
|
-
default
|
62
|
-
end
|
44
|
+
framework_integration.database_engine
|
63
45
|
end
|
64
46
|
|
65
47
|
def processors
|
@@ -31,6 +31,30 @@ module ScoutApm
|
|
31
31
|
def env
|
32
32
|
RAILS_ENV.dup
|
33
33
|
end
|
34
|
+
|
35
|
+
# Attempts to determine the database engine being used
|
36
|
+
def database_engine
|
37
|
+
default = :mysql
|
38
|
+
|
39
|
+
if defined?(ActiveRecord::Base)
|
40
|
+
config = ActiveRecord::Base.configurations[env]
|
41
|
+
if config && config["adapter"]
|
42
|
+
case config["adapter"].to_s
|
43
|
+
when "postgres" then :postgres
|
44
|
+
when "postgresql" then :postgres
|
45
|
+
when "sqlite3" then :sqlite
|
46
|
+
when "mysql" then :mysql
|
47
|
+
else default
|
48
|
+
end
|
49
|
+
else
|
50
|
+
default
|
51
|
+
end
|
52
|
+
else
|
53
|
+
default
|
54
|
+
end
|
55
|
+
rescue
|
56
|
+
default
|
57
|
+
end
|
34
58
|
end
|
35
59
|
end
|
36
60
|
end
|
@@ -32,6 +32,27 @@ module ScoutApm
|
|
32
32
|
::Rails.env
|
33
33
|
end
|
34
34
|
|
35
|
+
def database_engine
|
36
|
+
default = :mysql
|
37
|
+
|
38
|
+
if defined?(ActiveRecord::Base)
|
39
|
+
config = ActiveRecord::Base.connection_config
|
40
|
+
if config && config[:adapter]
|
41
|
+
case config[:adapter]
|
42
|
+
when "postgres" then :postgres
|
43
|
+
when "postgresql" then :postgres
|
44
|
+
when "sqlite3" then :sqlite
|
45
|
+
when "mysql" then :mysql
|
46
|
+
else default
|
47
|
+
end
|
48
|
+
else
|
49
|
+
default
|
50
|
+
end
|
51
|
+
else
|
52
|
+
# TODO: Figure out how to detect outside of Rails context. (sequel, ROM, etc)
|
53
|
+
default
|
54
|
+
end
|
55
|
+
end
|
35
56
|
end
|
36
57
|
end
|
37
58
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Instruments
|
3
|
+
class ActionControllerRails2
|
4
|
+
attr_reader :logger
|
5
|
+
|
6
|
+
def initalize(logger=ScoutApm::Agent.instance.logger)
|
7
|
+
@logger = logger
|
8
|
+
@installed = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def installed?
|
12
|
+
@installed
|
13
|
+
end
|
14
|
+
|
15
|
+
def install
|
16
|
+
@installed = true
|
17
|
+
|
18
|
+
if defined?(::ActionController) && defined?(::ActionController::Base)
|
19
|
+
::ActionController::Base.class_eval do
|
20
|
+
include ScoutApm::Tracer
|
21
|
+
include ::ScoutApm::Instruments::ActionControllerRails2Instruments
|
22
|
+
|
23
|
+
def rescue_action_with_scout(exception)
|
24
|
+
ScoutApm::Agent.instance.store.track!("Errors/Request",1, :scope => nil)
|
25
|
+
ScoutApm::Agent.instance.store.ignore_transaction!
|
26
|
+
rescue_action_without_scout exception
|
27
|
+
end
|
28
|
+
|
29
|
+
alias_method :rescue_action_without_scout, :rescue_action
|
30
|
+
alias_method :rescue_action, :rescue_action_with_scout
|
31
|
+
protected :rescue_action
|
32
|
+
end
|
33
|
+
|
34
|
+
ScoutApm::Agent.instance.logger.debug "Instrumenting ActionView::Template"
|
35
|
+
::ActionView::Template.class_eval do
|
36
|
+
include ::ScoutApm::Tracer
|
37
|
+
instrument_method :render, :metric_name => 'View/#{path[%r{^(/.*/)?(.*)$},2]}/Rendering', :scope => true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module ActionControllerRails2Instruments
|
45
|
+
def self.included(instrumented_class)
|
46
|
+
ScoutApm::Agent.instance.logger.debug "Instrumenting #{instrumented_class.inspect}"
|
47
|
+
instrumented_class.class_eval do
|
48
|
+
unless instrumented_class.method_defined?(:perform_action_without_scout_instruments)
|
49
|
+
alias_method :perform_action_without_scout_instruments, :perform_action
|
50
|
+
alias_method :perform_action, :perform_action_with_scout_instruments
|
51
|
+
private :perform_action
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# In addition to instrumenting actions, this also sets the scope to the controller action name. The scope is later
|
57
|
+
# applied to metrics recorded during this transaction. This lets us associate ActiveRecord calls with
|
58
|
+
# specific controller actions.
|
59
|
+
def perform_action_with_scout_instruments(*args, &block)
|
60
|
+
scout_controller_action = "Controller/#{controller_path}/#{action_name}"
|
61
|
+
self.class.scout_apm_trace(scout_controller_action, :uri => request.request_uri, :ip => request.remote_ip) do
|
62
|
+
perform_action_without_scout_instruments(*args, &block)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Instruments
|
3
|
+
class ActionControllerRails3
|
4
|
+
attr_reader :logger
|
5
|
+
|
6
|
+
def initalize(logger=ScoutApm::Agent.instance.logger)
|
7
|
+
@logger = logger
|
8
|
+
@installed = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def installed?
|
12
|
+
@installed
|
13
|
+
end
|
14
|
+
|
15
|
+
def install
|
16
|
+
@installed = true
|
17
|
+
|
18
|
+
# ActionController::Base is a subclass of ActionController::Metal, so this instruments both
|
19
|
+
# standard Rails requests + Metal.
|
20
|
+
if defined?(::ActionController) && defined?(::ActionController::Metal)
|
21
|
+
ScoutApm::Agent.instance.logger.debug "Instrumenting ActionController::Metal"
|
22
|
+
::ActionController::Metal.class_eval do
|
23
|
+
include ScoutApm::Tracer
|
24
|
+
include ScoutApm::Instruments::ActionControllerRails3Instruments
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if defined?(::ActionView) && defined?(::ActionView::PartialRenderer)
|
29
|
+
ScoutApm::Agent.instance.logger.debug "Instrumenting ActionView::PartialRenderer"
|
30
|
+
ActionView::PartialRenderer.class_eval do
|
31
|
+
include ScoutApm::Tracer
|
32
|
+
instrument_method :render_partial, :metric_name => 'View/#{@template.virtual_path}/Rendering', :scope => true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module ActionControllerRails3Instruments
|
40
|
+
# Instruments the action and tracks errors.
|
41
|
+
def process_action(*args)
|
42
|
+
scout_controller_action = "Controller/#{controller_path}/#{action_name}"
|
43
|
+
|
44
|
+
self.class.scout_apm_trace(scout_controller_action, :uri => request.fullpath, :ip => request.remote_ip) do
|
45
|
+
begin
|
46
|
+
super
|
47
|
+
rescue Exception
|
48
|
+
ScoutApm::Agent.instance.store.track!("Errors/Request",1, :scope => nil)
|
49
|
+
raise
|
50
|
+
ensure
|
51
|
+
Thread::current[:scout_apm_scope_name] = nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# Rails 3/4
|
61
|
+
module ScoutApm
|
62
|
+
module Instruments
|
63
|
+
end
|
64
|
+
end
|
@@ -2,6 +2,47 @@ require 'scout_apm/utils/sql_sanitizer'
|
|
2
2
|
|
3
3
|
module ScoutApm
|
4
4
|
module Instruments
|
5
|
+
class ActiveRecord
|
6
|
+
attr_reader :logger
|
7
|
+
|
8
|
+
def initalize(logger=ScoutApm::Agent.instance.logger)
|
9
|
+
@logger = logger
|
10
|
+
@installed = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def installed?
|
14
|
+
@installed
|
15
|
+
end
|
16
|
+
|
17
|
+
def install
|
18
|
+
@installed = true
|
19
|
+
|
20
|
+
if defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3 && ::Rails.respond_to?(:configuration)
|
21
|
+
Rails.configuration.after_initialize do
|
22
|
+
ScoutApm::Agent.instance.logger.debug "Adding ActiveRecord instrumentation to a Rails 3 app"
|
23
|
+
add_instruments
|
24
|
+
end
|
25
|
+
else
|
26
|
+
add_instruments
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_instruments
|
31
|
+
if defined?(::ActiveRecord) && defined?(::ActiveRecord::Base)
|
32
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
|
33
|
+
include ::ScoutApm::Instruments::ActiveRecordInstruments
|
34
|
+
include ::ScoutApm::Tracer
|
35
|
+
end
|
36
|
+
|
37
|
+
::ActiveRecord::Base.class_eval do
|
38
|
+
include ::ScoutApm::Tracer
|
39
|
+
end
|
40
|
+
end
|
41
|
+
rescue
|
42
|
+
ScoutApm::Agent.instance.logger.warn "ActiveRecord instrumentation exception: #{$!.message}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
5
46
|
# Contains ActiveRecord instrument, aliasing +ActiveRecord::ConnectionAdapters::AbstractAdapter#log+ calls
|
6
47
|
# to trace calls to the database.
|
7
48
|
module ActiveRecordInstruments
|
@@ -47,28 +88,8 @@ module ScoutApm
|
|
47
88
|
metric
|
48
89
|
end
|
49
90
|
end # module ActiveRecordInstruments
|
50
|
-
end # module Instruments
|
51
|
-
end
|
52
|
-
|
53
|
-
def add_instruments
|
54
|
-
if defined?(ActiveRecord) && defined?(ActiveRecord::Base)
|
55
|
-
ActiveRecord::ConnectionAdapters::AbstractAdapter.module_eval do
|
56
|
-
include ::ScoutApm::Instruments::ActiveRecordInstruments
|
57
|
-
include ::ScoutApm::Tracer
|
58
|
-
end
|
59
|
-
ActiveRecord::Base.class_eval do
|
60
|
-
include ::ScoutApm::Tracer
|
61
|
-
end
|
62
91
|
end
|
63
|
-
rescue
|
64
|
-
ScoutApm::Agent.instance.logger.warn "ActiveRecord instrumentation exception: #{$!.message}"
|
65
92
|
end
|
66
93
|
|
67
|
-
|
68
|
-
|
69
|
-
ScoutApm::Agent.instance.logger.debug "Adding ActiveRecord instrumentation to a Rails 3 app"
|
70
|
-
add_instruments
|
71
|
-
end
|
72
|
-
else
|
73
|
-
add_instruments
|
74
|
-
end
|
94
|
+
|
95
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Instruments
|
3
|
+
class Mongoid
|
4
|
+
attr_reader :logger
|
5
|
+
|
6
|
+
def initalize(logger=ScoutApm::Agent.instance.logger)
|
7
|
+
@logger = logger
|
8
|
+
@installed = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def installed?
|
12
|
+
@installed
|
13
|
+
end
|
14
|
+
|
15
|
+
def install
|
16
|
+
@installed = true
|
17
|
+
|
18
|
+
# Mongoid versions that use Moped should instrument Moped.
|
19
|
+
if defined?(::Mongoid) and !defined?(::Moped)
|
20
|
+
ScoutApm::Agent.instance.logger.debug "Instrumenting Mongoid"
|
21
|
+
|
22
|
+
::Mongoid::Collection.class_eval do
|
23
|
+
include ScoutApm::Tracer
|
24
|
+
(::Mongoid::Collections::Operations::ALL - [:<<, :[]]).each do |method|
|
25
|
+
instrument_method method, :metric_name => "MongoDB/\#{@klass}/#{method}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ScoutApm
|
2
|
+
module Instruments
|
3
|
+
class Moped
|
4
|
+
attr_reader :logger
|
5
|
+
|
6
|
+
def initalize(logger=ScoutApm::Agent.instance.logger)
|
7
|
+
@logger = logger
|
8
|
+
@installed = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def installed?
|
12
|
+
@installed
|
13
|
+
end
|
14
|
+
|
15
|
+
def install
|
16
|
+
@installed = true
|
17
|
+
|
18
|
+
if defined?(::Moped)
|
19
|
+
ScoutApm::Agent.instance.logger.debug "Instrumenting Moped"
|
20
|
+
::Moped::Node.class_eval do
|
21
|
+
include ScoutApm::Tracer
|
22
|
+
|
23
|
+
def process_with_scout_instruments(operation, &callback)
|
24
|
+
if operation.respond_to?(:collection)
|
25
|
+
collection = operation.collection
|
26
|
+
self.class.instrument("MongoDB/Process/#{collection}/#{operation.class.to_s.split('::').last}",
|
27
|
+
:desc => scout_sanitize_log(operation.log_inspect)) do
|
28
|
+
process_without_scout_instruments(operation, &callback)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
alias_method :process_without_scout_instruments, :process
|
33
|
+
alias_method :process, :process_with_scout_instruments
|
34
|
+
|
35
|
+
# replaces values w/ ?
|
36
|
+
def scout_sanitize_log(log)
|
37
|
+
return nil if log.length > 1000 # safeguard - don't sanitize large SQL statements
|
38
|
+
log.gsub(/(=>")((?:[^"]|"")*)"/) do
|
39
|
+
$1 + '?' + '"'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|