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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c3c774cf96a6a211650f1fffabed007073ccb93
4
- data.tar.gz: bd321d8d0567c66caeb6a96ca3a65a72a48db39a
3
+ metadata.gz: 9959104d4317f9bb646443606363b67e7a33b4f9
4
+ data.tar.gz: 866026e27f92c5607fbf8bcf15f6f921bcbc7786
5
5
  SHA512:
6
- metadata.gz: e3071d8c222b7e3954aaa04a3eb25fe5ea89b780894be1763173ff5b061cf4cc565659267b3f353754dfeb16f9927db7108c22a6d60055f880d8561a74194e7e
7
- data.tar.gz: 84ab4cc77107f927537587f080b6b23950330da0075c9819f03c4038929006087256fce9449f54f39ae51a98ee91678307fe836abc66ccbf2e75c0e20c229118
6
+ metadata.gz: 05a3afbfa039ec01f844940000910689753579311313d386f8487b5e69413bce155ee11103b92fd808b93a0ba801cbf58fbfe195b9ecff7e62c012c9d5251f51
7
+ data.tar.gz: 7e6b9e8da470b075e6df0a7d4b9974939f11a1aaef323f3eff12f567561718627325ba6b64c76189557c8461f92f32ad966b8d85ce731fdea1ee3b4b934c98e7
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,7 @@
1
+ # 0.1.13
2
+
3
+ * Fix support for ActiveRecord and ActionController instruments on Rails 2.3
4
+
1
5
  # 0.1.12
2
6
 
3
7
  * Fix Puma integration. Now detects both branches of preload_app! setting.
@@ -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 + "[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{ScoutApm::Agent.instance.environment.hostname} (#{$$})] #{severity} : #{msg}\n"
35
+ prefix + "[#{Utils::Time.to_s(timestamp)} #{ScoutApm::Agent.instance.environment.hostname} (#{$$})] #{severity} : #{msg}\n"
36
36
  end
37
37
  end
38
38
 
@@ -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
- require File.expand_path(File.join(File.dirname(__FILE__),'instruments/rails/action_controller_instruments.rb'))
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
- require File.expand_path(File.join(File.dirname(__FILE__),'instruments/active_record_instruments.rb'))
185
- require File.expand_path(File.join(File.dirname(__FILE__),'instruments/net_http.rb'))
186
- require File.expand_path(File.join(File.dirname(__FILE__),'instruments/moped_instruments.rb'))
187
- require File.expand_path(File.join(File.dirname(__FILE__),'instruments/mongoid_instruments.rb'))
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
- class ScoutApm::BackgroundWorker
3
- # in seconds, time between when the worker thread wakes up and runs.
4
- PERIOD = 60
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
- def initialize
7
- @keep_running = true
8
- end
7
+ attr_reader :period
9
8
 
10
- def stop
11
- @keep_running = false
12
- end
9
+ def initialize(period=DEFAULT_PERIOD)
10
+ @period = period
11
+ @keep_running = true
12
+ end
13
13
 
14
- # Runs the task passed to +start+ once.
15
- def run_once
16
- @task.call if @task
17
- end
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
- # Starts running the passed block every 60 seconds (starting now).
20
- def start(&block)
21
- @task = block
22
- begin
23
- ScoutApm::Agent.instance.logger.debug "Starting Background Worker, running every #{PERIOD} seconds"
24
- next_time = Time.now
25
- while @keep_running do
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
- @task.call
33
- while next_time <= now
34
- next_time += PERIOD
35
- end
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
@@ -1,54 +1,56 @@
1
1
  # Encapsulates logic for determining capacity utilization of the Ruby processes.
2
- class ScoutApm::Capacity
3
- attr_reader :processing_start_time, :accumulated_time, :transaction_entry_time
2
+ module ScoutApm
3
+ class Capacity
4
+ attr_reader :processing_start_time, :accumulated_time, :transaction_entry_time
4
5
 
5
- def initialize
6
- @processing_start_time = Time.now
7
- @lock ||= Mutex.new # the transaction_entry_time could be modified while processing a request or when #process is called.
8
- @accumulated_time = 0.0
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
- # Called when a transaction completes to record its time used.
19
- def finish_transaction!
20
- @lock.synchronize do
21
- if transaction_entry_time
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
- # Ran when sending metrics to server. Reports capacity usage metrics.
31
- def process
32
- process_time = Time.now
33
- ScoutApm::Agent.instance.logger.debug "Processing capacity usage for [#{@processing_start_time}] to [#{process_time}]. Time Spent: #{@accumulated_time}."
34
- @lock.synchronize do
35
- time_spent = @accumulated_time
36
- @accumulated_time = 0.0
37
- # If a transaction is still running, capture its running time up to now and
38
- # reset the +transaction_entry_time+ to now.
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
- time_spent = 0.0 if time_spent < 0.0
29
+ end
45
30
 
46
- window = (process_time - processing_start_time).to_f # time period we are evaulating capacity usage.
47
- window = 1.0 if window <= 0.0 # prevent divide-by-zero if clock adjusted.
48
- capacity = time_spent / window
49
- ScoutApm::Agent.instance.logger.debug "Instance/Capacity: #{capacity}"
50
- ScoutApm::Agent.instance.store.track!("Instance/Capacity",capacity,:scope => nil)
51
- @processing_start_time = process_time
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
- default = :mysql
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
@@ -25,6 +25,11 @@ module ScoutApm
25
25
  def env
26
26
  ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
27
27
  end
28
+
29
+ # TODO: Figure out how to accomodate odd environments
30
+ def database_engine
31
+ :mysql
32
+ end
28
33
  end
29
34
  end
30
35
  end
@@ -26,6 +26,11 @@ module ScoutApm
26
26
  def env
27
27
  ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
28
28
  end
29
+
30
+ # TODO: Figure out how to detect this smarter
31
+ def database_engine
32
+ :mysql
33
+ end
29
34
  end
30
35
  end
31
36
  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
- if defined?(::Rails) && ::Rails::VERSION::MAJOR.to_i == 3 && ::Rails.respond_to?(:configuration)
68
- Rails.configuration.after_initialize do
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
+