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.
- 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
data/lib/scout_apm/store.rb
CHANGED
@@ -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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
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
|
-
#
|
79
|
-
|
80
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
#
|
91
|
-
|
92
|
-
|
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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
133
|
-
end
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
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
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
merged
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
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
|
-
|
202
|
-
|
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
|
data/lib/scout_apm/version.rb
CHANGED
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.
|
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-
|
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/
|
84
|
-
- lib/scout_apm/instruments/
|
85
|
-
- lib/scout_apm/instruments/
|
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
|
-
|