scout_apm 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,203 +1,212 @@
1
- require 'thread'
2
1
 
3
2
  # The store encapsolutes the logic that (1) saves instrumented data by Metric name to memory and (2) maintains a stack (just an Array)
4
3
  # of instrumented methods that are being called. It's accessed via +ScoutApm::Agent.instance.store+.
5
- class ScoutApm::Store
6
-
7
- # Limits the size of the metric hash to prevent a metric explosion.
8
- MAX_SIZE = 1000
9
-
10
- # Limit the number of slow transactions that we store metrics with to prevent writing too much data to the layaway file if there are are many processes and many slow slow_transactions.
11
- MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS = 10
12
-
13
- attr_accessor :metric_hash
14
- attr_accessor :transaction_hash
15
- attr_accessor :stack
16
- attr_accessor :slow_transactions # array of slow transaction slow_transactions
17
- attr_reader :slow_transaction_lock
18
-
19
- def initialize
20
- @metric_hash = Hash.new
21
- # Stores aggregate metrics for the current transaction. When the transaction is finished, metrics
22
- # are merged with the +metric_hash+.
23
- @transaction_hash = Hash.new
24
- @stack = Array.new
25
- # ensure background thread doesn't manipulate transaction sample while the store is.
26
- @slow_transaction_lock = Mutex.new
27
- @slow_transactions = Array.new
28
- end
29
-
30
- # Called when the last stack item completes for the current transaction to clear
31
- # for the next run.
32
- def reset_transaction!
33
- Thread::current[:scout_apm_ignore_transaction] = nil
34
- Thread::current[:scout_apm_scope_name] = nil
35
- @transaction_hash = Hash.new
36
- @stack = Array.new
37
- end
38
-
39
- def ignore_transaction!
40
- Thread::current[:scout_apm_ignore_transaction] = true
41
- end
42
-
43
- # Called at the start of Tracer#instrument:
44
- # (1) Either finds an existing MetricStats object in the metric_hash or
45
- # initialize a new one. An existing MetricStats object is present if this +metric_name+ has already been instrumented.
46
- # (2) Adds a StackItem to the stack. This StackItem is returned and later used to validate the item popped off the stack
47
- # when an instrumented code block completes.
48
- def record(metric_name)
49
- item = ScoutApm::StackItem.new(metric_name)
50
- stack << item
51
- item
52
- end
53
-
54
- # Options:
55
- # * :scope - If specified, sets the sub-scope for the metric. We allow additional scope level. This is used
56
- # * uri - the request uri
57
- def stop_recording(sanity_check_item, options={})
58
- item = stack.pop
59
- stack_empty = stack.empty?
60
- # if ignoring the transaction, the item is popped but nothing happens.
61
- if Thread::current[:scout_apm_ignore_transaction]
62
- return
4
+ module ScoutApm
5
+ class Store
6
+
7
+ # Limits the size of the metric hash to prevent a metric explosion.
8
+ MAX_SIZE = 1000
9
+
10
+ # Limit the number of slow transactions that we store metrics with to prevent writing too much data to the layaway file if there are are many processes and many slow slow_transactions.
11
+ MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS = 10
12
+
13
+ attr_accessor :metric_hash
14
+ attr_accessor :transaction_hash
15
+ attr_accessor :stack
16
+ attr_accessor :slow_transactions # array of slow transaction slow_transactions
17
+ attr_reader :slow_transaction_lock
18
+
19
+ def initialize
20
+ @metric_hash = Hash.new
21
+ # Stores aggregate metrics for the current transaction. When the transaction is finished, metrics
22
+ # are merged with the +metric_hash+.
23
+ @transaction_hash = Hash.new
24
+ @stack = Array.new
25
+ # ensure background thread doesn't manipulate transaction sample while the store is.
26
+ @slow_transaction_lock = Mutex.new
27
+ @slow_transactions = Array.new
63
28
  end
64
- # unbalanced stack check - unreproducable cases have seen this occur. when it does, sets a Thread variable
65
- # so we ignore further recordings. +Store#reset_transaction!+ resets this.
66
- if item != sanity_check_item
67
- ScoutApm::Agent.instance.logger.warn "Scope [#{Thread::current[:scout_apm_scope_name]}] Popped off stack: #{item.inspect} Expected: #{sanity_check_item.inspect}. Aborting."
68
- ignore_transaction!
69
- return
29
+
30
+ # Called when the last stack item completes for the current transaction to clear
31
+ # for the next run.
32
+ def reset_transaction!
33
+ Thread::current[:scout_apm_ignore_transaction] = nil
34
+ Thread::current[:scout_apm_scope_name] = nil
35
+ @transaction_hash = Hash.new
36
+ @stack = Array.new
70
37
  end
71
- duration = Time.now - item.start_time
72
- if last=stack.last
73
- last.children_time += duration
38
+
39
+ def ignore_transaction!
40
+ Thread::current[:scout_apm_ignore_transaction] = true
74
41
  end
75
- meta = ScoutApm::MetricMeta.new(item.metric_name, :desc => options[:desc])
76
- meta.scope = nil if stack_empty
77
42
 
78
- # add backtrace for slow calls ... how is exclusive time handled?
79
- if duration > ScoutApm::SlowTransaction::BACKTRACE_THRESHOLD and !stack_empty
80
- meta.extra = {:backtrace => ScoutApm::SlowTransaction.backtrace_parser(caller)}
43
+ # Called at the start of Tracer#instrument:
44
+ # (1) Either finds an existing MetricStats object in the metric_hash or
45
+ # initialize a new one. An existing MetricStats object is present if this +metric_name+ has already been instrumented.
46
+ # (2) Adds a StackItem to the stack. This StackItem is returned and later used to validate the item popped off the stack
47
+ # when an instrumented code block completes.
48
+ def record(metric_name)
49
+ item = ScoutApm::StackItem.new(metric_name)
50
+ stack << item
51
+ item
81
52
  end
82
- stat = transaction_hash[meta] || ScoutApm::MetricStats.new(!stack_empty)
83
- stat.update!(duration,duration-item.children_time)
84
- transaction_hash[meta] = stat if store_metric?(stack_empty)
85
-
86
- # Uses controllers as the entry point for a transaction. Otherwise, stats are ignored.
87
- if stack_empty and meta.metric_name.match(/\AController\//)
88
- aggs=aggregate_calls(transaction_hash.dup,meta)
89
- store_slow(options[:uri],transaction_hash.dup.merge(aggs),meta,stat)
90
- # deep duplicate
91
- duplicate = aggs.dup
92
- duplicate.each_pair do |k,v|
93
- duplicate[k.dup] = v.dup
53
+
54
+ # Options:
55
+ # * :scope - If specified, sets the sub-scope for the metric. We allow additional scope level. This is used
56
+ # * uri - the request uri
57
+ def stop_recording(sanity_check_item, options={})
58
+ item = stack.pop
59
+ stack_empty = stack.empty?
60
+
61
+ # if ignoring the transaction, the item is popped but nothing happens.
62
+ if Thread::current[:scout_apm_ignore_transaction]
63
+ return
94
64
  end
95
- merge_metrics(duplicate.merge({meta.dup => stat.dup})) # aggregrates + controller
96
- end
97
- end
98
-
99
- # TODO - Move more logic to SlowTransaction
100
- #
101
- # Limits the size of the transaction hash to prevent a large transactions. The final item on the stack
102
- # is allowed to be stored regardless of hash size to wrapup the transaction sample w/the parent metric.
103
- def store_metric?(stack_empty)
104
- transaction_hash.size < ScoutApm::SlowTransaction::MAX_SIZE or stack_empty
105
- end
106
-
107
- # Returns the top-level category names used in the +metrics+ hash.
108
- def categories(metrics)
109
- cats = Set.new
110
- metrics.keys.each do |meta|
111
- next if meta.scope.nil? # ignore controller
112
- if match=meta.metric_name.match(/\A([\w]+)\//)
113
- cats << match[1]
65
+
66
+ # unbalanced stack check - unreproducable cases have seen this occur. when it does, sets a Thread variable
67
+ # so we ignore further recordings. +Store#reset_transaction!+ resets this.
68
+ if item != sanity_check_item
69
+ ScoutApm::Agent.instance.logger.warn "Scope [#{Thread::current[:scout_apm_scope_name]}] Popped off stack: #{item.inspect} Expected: #{sanity_check_item.inspect}. Aborting."
70
+ ignore_transaction!
71
+ return
72
+ end
73
+
74
+ duration = Time.now - item.start_time
75
+ if last=stack.last
76
+ last.children_time += duration
114
77
  end
115
- end # metrics.each
116
- cats
117
- end
118
-
119
- # Takes a metric_hash of calls and generates aggregates for ActiveRecord and View calls.
120
- def aggregate_calls(metrics,parent_meta)
121
- categories = categories(metrics)
122
- aggregates = {}
123
- categories.each do |cat|
124
- agg_meta=ScoutApm::MetricMeta.new("#{cat}/all")
125
- agg_meta.scope = parent_meta.metric_name
126
- agg_stats = ScoutApm::MetricStats.new
127
- metrics.each do |meta,stats|
128
- if meta.metric_name =~ /\A#{cat}\//
129
- agg_stats.combine!(stats)
78
+
79
+ meta = ScoutApm::MetricMeta.new(item.metric_name, :desc => options[:desc])
80
+ meta.scope = nil if stack_empty
81
+
82
+ # add backtrace for slow calls ... how is exclusive time handled?
83
+ if duration > ScoutApm::SlowTransaction::BACKTRACE_THRESHOLD and !stack_empty
84
+ meta.extra = {:backtrace => ScoutApm::SlowTransaction.backtrace_parser(caller)}
85
+ end
86
+
87
+ stat = transaction_hash[meta] || ScoutApm::MetricStats.new(!stack_empty)
88
+ stat.update!(duration,duration-item.children_time)
89
+ transaction_hash[meta] = stat if store_metric?(stack_empty)
90
+
91
+ # Uses controllers as the entry point for a transaction. Otherwise, stats are ignored.
92
+ if stack_empty and meta.metric_name.match(/\AController\//)
93
+ aggs=aggregate_calls(transaction_hash.dup,meta)
94
+ store_slow(options[:uri],transaction_hash.dup.merge(aggs),meta,stat)
95
+ # deep duplicate
96
+ duplicate = aggs.dup
97
+ duplicate.each_pair do |k,v|
98
+ duplicate[k.dup] = v.dup
99
+ end
100
+ merge_metrics(duplicate.merge({meta.dup => stat.dup})) # aggregrates + controller
101
+ end
102
+ end
103
+
104
+ # TODO - Move more logic to SlowTransaction
105
+ #
106
+ # Limits the size of the transaction hash to prevent a large transactions. The final item on the stack
107
+ # is allowed to be stored regardless of hash size to wrapup the transaction sample w/the parent metric.
108
+ def store_metric?(stack_empty)
109
+ transaction_hash.size < ScoutApm::SlowTransaction::MAX_SIZE or stack_empty
110
+ end
111
+
112
+ # Returns the top-level category names used in the +metrics+ hash.
113
+ def categories(metrics)
114
+ cats = Set.new
115
+ metrics.keys.each do |meta|
116
+ next if meta.scope.nil? # ignore controller
117
+ if match=meta.metric_name.match(/\A([\w]+)\//)
118
+ cats << match[1]
130
119
  end
131
120
  end # metrics.each
132
- aggregates[agg_meta] = agg_stats unless agg_stats.call_count.zero?
133
- end # categories.each
134
- aggregates
135
- end
136
-
137
- # Stores slow transactions. This will be sent to the server.
138
- def store_slow(uri,transaction_hash,parent_meta,parent_stat,options = {})
139
- @slow_transaction_lock.synchronize do
140
- # tree map of all slow transactions
141
- if parent_stat.total_call_time >= 2
142
- @slow_transactions.push(ScoutApm::SlowTransaction.new(uri,parent_meta.metric_name,parent_stat.total_call_time,transaction_hash.dup,ScoutApm::Context.current,Thread::current[:scout_apm_trace_time]))
143
- ScoutApm::Agent.instance.logger.debug "Slow transaction sample added. [URI: #{uri}] [Context: #{ScoutApm::Context.current.to_hash}] Array Size: #{@slow_transactions.size}"
121
+ cats
122
+ end
123
+
124
+ # Takes a metric_hash of calls and generates aggregates for ActiveRecord and View calls.
125
+ def aggregate_calls(metrics,parent_meta)
126
+ categories = categories(metrics)
127
+ aggregates = {}
128
+ categories.each do |cat|
129
+ agg_meta=ScoutApm::MetricMeta.new("#{cat}/all")
130
+ agg_meta.scope = parent_meta.metric_name
131
+ agg_stats = ScoutApm::MetricStats.new
132
+ metrics.each do |meta,stats|
133
+ if meta.metric_name =~ /\A#{cat}\//
134
+ agg_stats.combine!(stats)
135
+ end
136
+ end # metrics.each
137
+ aggregates[agg_meta] = agg_stats unless agg_stats.call_count.zero?
138
+ end # categories.each
139
+ aggregates
140
+ end
141
+
142
+ # Stores slow transactions. This will be sent to the server.
143
+ def store_slow(uri,transaction_hash,parent_meta,parent_stat,options = {})
144
+ @slow_transaction_lock.synchronize do
145
+ # tree map of all slow transactions
146
+ if parent_stat.total_call_time >= 2
147
+ @slow_transactions.push(ScoutApm::SlowTransaction.new(uri,parent_meta.metric_name,parent_stat.total_call_time,transaction_hash.dup,ScoutApm::Context.current,Thread::current[:scout_apm_trace_time]))
148
+ ScoutApm::Agent.instance.logger.debug "Slow transaction sample added. [URI: #{uri}] [Context: #{ScoutApm::Context.current.to_hash}] Array Size: #{@slow_transactions.size}"
149
+ end
144
150
  end
145
151
  end
146
- end
147
-
148
- # Finds or creates the metric w/the given name in the metric_hash, and updates the time. Primarily used to
149
- # record sampled metrics. For instrumented methods, #record and #stop_recording are used.
150
- #
151
- # Options:
152
- # :scope => If provided, overrides the default scope.
153
- # :exclusive_time => Sets the exclusive time for the method. If not provided, uses +call_time+.
154
- def track!(metric_name, call_time, options = {})
155
- meta = ScoutApm::MetricMeta.new(metric_name)
156
- meta.scope = options[:scope] if options.has_key?(:scope)
157
- stat = metric_hash[meta] || ScoutApm::MetricStats.new
158
- stat.update!(call_time,options[:exclusive_time] || call_time)
159
- metric_hash[meta] = stat
160
- end
161
-
162
- # Combines old and current data
163
- def merge_data(old_data)
164
- {:metrics => merge_metrics(old_data[:metrics]), :slow_transactions => merge_slow_transactions(old_data[:slow_transactions])}
165
- end
166
-
167
- # Merges old and current data, clears the current in-memory metric hash, and returns
168
- # the merged data
169
- def merge_data_and_clear(old_data)
170
- merged = merge_data(old_data)
171
- self.metric_hash = {}
172
- # TODO - is this lock needed?
173
- @slow_transaction_lock.synchronize do
174
- self.slow_transactions = []
152
+
153
+ # Finds or creates the metric w/the given name in the metric_hash, and updates the time. Primarily used to
154
+ # record sampled metrics. For instrumented methods, #record and #stop_recording are used.
155
+ #
156
+ # Options:
157
+ # :scope => If provided, overrides the default scope.
158
+ # :exclusive_time => Sets the exclusive time for the method. If not provided, uses +call_time+.
159
+ def track!(metric_name, call_time, options = {})
160
+ meta = ScoutApm::MetricMeta.new(metric_name)
161
+ meta.scope = options[:scope] if options.has_key?(:scope)
162
+ stat = metric_hash[meta] || ScoutApm::MetricStats.new
163
+ stat.update!(call_time,options[:exclusive_time] || call_time)
164
+ metric_hash[meta] = stat
165
+ end
166
+
167
+ # Combines old and current data
168
+ def merge_data(old_data)
169
+ {
170
+ :metrics => merge_metrics(old_data[:metrics]),
171
+ :slow_transactions => merge_slow_transactions(old_data[:slow_transactions])
172
+ }
173
+ end
174
+
175
+ # Merges old and current data, clears the current in-memory metric hash, and returns
176
+ # the merged data
177
+ def merge_data_and_clear(old_data)
178
+ merged = merge_data(old_data)
179
+ self.metric_hash = {}
180
+ # TODO - is this lock needed?
181
+ @slow_transaction_lock.synchronize do
182
+ self.slow_transactions = []
183
+ end
184
+ merged
175
185
  end
176
- merged
177
- end
178
-
179
- def merge_metrics(old_metrics)
180
- old_metrics.each do |old_meta,old_stats|
181
- if stats = metric_hash[old_meta]
182
- metric_hash[old_meta] = stats.combine!(old_stats)
183
- elsif metric_hash.size < MAX_SIZE
184
- metric_hash[old_meta] = old_stats
186
+
187
+ def merge_metrics(old_metrics)
188
+ old_metrics.each do |old_meta,old_stats|
189
+ if stats = metric_hash[old_meta]
190
+ metric_hash[old_meta] = stats.combine!(old_stats)
191
+ elsif metric_hash.size < MAX_SIZE
192
+ metric_hash[old_meta] = old_stats
193
+ end
185
194
  end
195
+ metric_hash
186
196
  end
187
- metric_hash
188
- end
189
-
190
- # Merges slow_transactions together, removing transaction sample metrics from slow_transactions if the > MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS
191
- def merge_slow_transactions(old_slow_transactions)
192
- # need transaction lock here?
193
- self.slow_transactions += old_slow_transactions
194
- if trim_slow_transactions = self.slow_transactions[MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS..-1]
195
- ScoutApm::Agent.instance.logger.debug "Trimming metrics from #{trim_slow_transactions.size} slow_transactions."
196
- i = MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS
197
- trim_slow_transactions.each do |sample|
198
- self.slow_transactions[i] = sample.clear_metrics!
197
+
198
+ # Merges slow_transactions together, removing transaction sample metrics from slow_transactions if the > MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS
199
+ def merge_slow_transactions(old_slow_transactions)
200
+ # need transaction lock here?
201
+ self.slow_transactions += old_slow_transactions
202
+ if trim_slow_transactions = self.slow_transactions[MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS..-1]
203
+ ScoutApm::Agent.instance.logger.debug "Trimming metrics from #{trim_slow_transactions.size} slow_transactions."
204
+ i = MAX_SLOW_TRANSACTIONS_TO_STORE_METRICS
205
+ trim_slow_transactions.each do |sample|
206
+ self.slow_transactions[i] = sample.clear_metrics!
207
+ end
199
208
  end
209
+ self.slow_transactions
200
210
  end
201
- self.slow_transactions
202
- end
203
- end # class Store
211
+ end # class Store
212
+ end
@@ -0,0 +1,12 @@
1
+ module ScoutApm
2
+ module Utils
3
+ class Time
4
+ # Handles both integer (unix) time and Time objects
5
+ # example output: "09/10/15 04:34:28 -0600"
6
+ def self.to_s(time)
7
+ return to_s(::Time.at(time)) if time.is_a? Integer
8
+ time.strftime("%m/%d/%y %H:%M:%S %z")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "0.1.12"
2
+ VERSION = "0.1.13"
3
3
  end
4
4
 
data/lib/scout_apm.rb CHANGED
@@ -8,6 +8,7 @@ require 'openssl'
8
8
  require 'set'
9
9
  require 'socket'
10
10
  require 'yaml'
11
+ require 'thread'
11
12
 
12
13
  require 'scout_apm/version'
13
14
 
@@ -24,11 +25,21 @@ require 'scout_apm/framework_integrations/rails_3_or_4'
24
25
  require 'scout_apm/framework_integrations/sinatra'
25
26
  require 'scout_apm/framework_integrations/ruby'
26
27
 
28
+ require 'scout_apm/instruments/net_http'
29
+ require 'scout_apm/instruments/moped'
30
+ require 'scout_apm/instruments/mongoid'
31
+ require 'scout_apm/instruments/active_record'
32
+ require 'scout_apm/instruments/action_controller_rails_2'
33
+ require 'scout_apm/instruments/action_controller_rails_3'
34
+ require 'scout_apm/instruments/process/process_cpu'
35
+ require 'scout_apm/instruments/process/process_memory'
36
+
27
37
  require 'scout_apm/app_server_load'
28
38
 
29
39
  require 'scout_apm/utils/sql_sanitizer'
30
40
  require 'scout_apm/utils/null_logger'
31
41
  require 'scout_apm/utils/installed_gems'
42
+ require 'scout_apm/utils/time'
32
43
  require 'scout_apm/config'
33
44
  require 'scout_apm/environment'
34
45
  require 'scout_apm/agent'
@@ -46,9 +57,6 @@ require 'scout_apm/tracer'
46
57
  require 'scout_apm/context'
47
58
  require 'scout_apm/slow_transaction'
48
59
  require 'scout_apm/capacity'
49
- require 'scout_apm/instruments/process/process_cpu'
50
- require 'scout_apm/instruments/process/process_memory'
51
-
52
60
 
53
61
  require 'scout_apm/serializers/payload_serializer'
54
62
  require 'scout_apm/serializers/directive_serializer'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scout_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Haynes
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-09-01 00:00:00.000000000 Z
12
+ date: 2015-09-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -80,14 +80,14 @@ files:
80
80
  - lib/scout_apm/framework_integrations/rails_3_or_4.rb
81
81
  - lib/scout_apm/framework_integrations/ruby.rb
82
82
  - lib/scout_apm/framework_integrations/sinatra.rb
83
- - lib/scout_apm/instruments/active_record_instruments.rb
84
- - lib/scout_apm/instruments/mongoid_instruments.rb
85
- - lib/scout_apm/instruments/moped_instruments.rb
83
+ - lib/scout_apm/instruments/action_controller_rails_2.rb
84
+ - lib/scout_apm/instruments/action_controller_rails_3.rb
85
+ - lib/scout_apm/instruments/active_record.rb
86
+ - lib/scout_apm/instruments/mongoid.rb
87
+ - lib/scout_apm/instruments/moped.rb
86
88
  - lib/scout_apm/instruments/net_http.rb
87
89
  - lib/scout_apm/instruments/process/process_cpu.rb
88
90
  - lib/scout_apm/instruments/process/process_memory.rb
89
- - lib/scout_apm/instruments/rails/action_controller_instruments.rb
90
- - lib/scout_apm/instruments/rails3_or_4/action_controller_instruments.rb
91
91
  - lib/scout_apm/layaway.rb
92
92
  - lib/scout_apm/layaway_file.rb
93
93
  - lib/scout_apm/metric_meta.rb
@@ -112,6 +112,7 @@ files:
112
112
  - lib/scout_apm/utils/sql_sanitizer.rb
113
113
  - lib/scout_apm/utils/sql_sanitizer_regex.rb
114
114
  - lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb
115
+ - lib/scout_apm/utils/time.rb
115
116
  - lib/scout_apm/version.rb
116
117
  - scout_apm.gemspec
117
118
  - test/data/config_test_1.yml
@@ -1,10 +0,0 @@
1
- # Mongoid versions that use Moped should instrument Moped.
2
- if defined?(::Mongoid) and !defined?(::Moped)
3
- ScoutApm::Agent.instance.logger.debug "Instrumenting Mongoid"
4
- Mongoid::Collection.class_eval do
5
- include ScoutApm::Tracer
6
- (Mongoid::Collections::Operations::ALL - [:<<, :[]]).each do |method|
7
- instrument_method method, :metric_name => "MongoDB/\#{@klass}/#{method}"
8
- end
9
- end
10
- end
@@ -1,24 +0,0 @@
1
- if defined?(::Moped)
2
- ScoutApm::Agent.instance.logger.debug "Instrumenting Moped"
3
- Moped::Node.class_eval do
4
- include ScoutApm::Tracer
5
- def process_with_scout_instruments(operation, &callback)
6
- if operation.respond_to?(:collection)
7
- collection = operation.collection
8
- self.class.instrument("MongoDB/Process/#{collection}/#{operation.class.to_s.split('::').last}", :desc => scout_sanitize_log(operation.log_inspect)) do
9
- process_without_scout_instruments(operation, &callback)
10
- end
11
- end
12
- end
13
- alias_method :process_without_scout_instruments, :process
14
- alias_method :process, :process_with_scout_instruments
15
-
16
- # replaces values w/ ?
17
- def scout_sanitize_log(log)
18
- return nil if log.length > 1000 # safeguard - don't sanitize large SQL statements
19
- log.gsub(/(=>")((?:[^"]|"")*)"/) do
20
- $1 + '?' + '"'
21
- end
22
- end
23
- end
24
- end
@@ -1,48 +0,0 @@
1
- module ScoutApm
2
- module Instruments
3
- module ActionControllerInstruments
4
- def self.included(instrumented_class)
5
- ScoutApm::Agent.instance.logger.debug "Instrumenting #{instrumented_class.inspect}"
6
- instrumented_class.class_eval do
7
- unless instrumented_class.method_defined?(:perform_action_without_scout_instruments)
8
- alias_method :perform_action_without_scout_instruments, :perform_action
9
- alias_method :perform_action, :perform_action_with_scout_instruments
10
- private :perform_action
11
- end
12
- end
13
- end
14
-
15
- # In addition to instrumenting actions, this also sets the scope to the controller action name. The scope is later
16
- # applied to metrics recorded during this transaction. This lets us associate ActiveRecord calls with
17
- # specific controller actions.
18
- def perform_action_with_scout_instruments(*args, &block)
19
- scout_controller_action = "Controller/#{controller_path}/#{action_name}"
20
- self.class.scout_apm_trace(scout_controller_action, :uri => request.request_uri, :ip => request.remote_ip) do
21
- perform_action_without_scout_instruments(*args, &block)
22
- end
23
- end
24
- end
25
- end
26
- end
27
-
28
- if defined?(ActionController) && defined?(ActionController::Base)
29
- ActionController::Base.class_eval do
30
- include ScoutApm::Tracer
31
- include ::ScoutApm::Instruments::ActionControllerInstruments
32
-
33
- def rescue_action_with_scout(exception)
34
- ScoutApm::Agent.instance.store.track!("Errors/Request",1, :scope => nil)
35
- ScoutApm::Agent.instance.store.ignore_transaction!
36
- rescue_action_without_scout exception
37
- end
38
-
39
- alias_method :rescue_action_without_scout, :rescue_action
40
- alias_method :rescue_action, :rescue_action_with_scout
41
- protected :rescue_action
42
- end
43
- ScoutApm::Agent.instance.logger.debug "Instrumenting ActionView::Template"
44
- ActionView::Template.class_eval do
45
- include ::ScoutApm::Tracer
46
- instrument_method :render, :metric_name => 'View/#{path[%r{^(/.*/)?(.*)$},2]}/Rendering', :scope => true
47
- end
48
- end
@@ -1,41 +0,0 @@
1
- # Rails 3/4
2
- module ScoutApm
3
- module Instruments
4
- module ActionControllerInstruments
5
- # Instruments the action and tracks errors.
6
- def process_action(*args)
7
- scout_controller_action = "Controller/#{controller_path}/#{action_name}"
8
-
9
- self.class.scout_apm_trace(scout_controller_action, :uri => request.fullpath, :ip => request.remote_ip) do
10
- begin
11
- super
12
- rescue Exception
13
- ScoutApm::Agent.instance.store.track!("Errors/Request",1, :scope => nil)
14
- raise
15
- ensure
16
- Thread::current[:scout_apm_scope_name] = nil
17
- end
18
- end
19
- end
20
- end
21
- end
22
- end
23
-
24
- # ActionController::Base is a subclass of ActionController::Metal, so this instruments both
25
- # standard Rails requests + Metal.
26
- if defined?(ActionController) && defined?(ActionController::Metal)
27
- ScoutApm::Agent.instance.logger.debug "Instrumenting ActionController::Metal"
28
- ActionController::Metal.class_eval do
29
- include ScoutApm::Tracer
30
- include ::ScoutApm::Instruments::ActionControllerInstruments
31
- end
32
- end
33
-
34
- if defined?(ActionView) && defined?(ActionView::PartialRenderer)
35
- ScoutApm::Agent.instance.logger.debug "Instrumenting ActionView::PartialRenderer"
36
- ActionView::PartialRenderer.class_eval do
37
- include ScoutApm::Tracer
38
- instrument_method :render_partial, :metric_name => 'View/#{@template.virtual_path}/Rendering', :scope => true
39
- end
40
- end
41
-