newrelic_rpm 3.4.2.1 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of newrelic_rpm might be problematic. Click here for more details.
- data/CHANGELOG +47 -2
- data/lib/new_relic/agent.rb +5 -5
- data/lib/new_relic/agent/agent.rb +88 -177
- data/lib/new_relic/agent/beacon_configuration.rb +33 -47
- data/lib/new_relic/agent/browser_monitoring.rb +26 -33
- data/lib/new_relic/agent/configuration/defaults.rb +21 -13
- data/lib/new_relic/agent/configuration/manager.rb +28 -14
- data/lib/new_relic/agent/configuration/server_source.rb +8 -5
- data/lib/new_relic/agent/database.rb +37 -22
- data/lib/new_relic/agent/error_collector.rb +32 -31
- data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +4 -3
- data/lib/new_relic/agent/new_relic_service.rb +21 -19
- data/lib/new_relic/agent/pipe_channel_manager.rb +13 -13
- data/lib/new_relic/agent/sql_sampler.rb +9 -28
- data/lib/new_relic/agent/stats_engine/gc_profiler.rb +21 -24
- data/lib/new_relic/agent/stats_engine/transactions.rb +20 -12
- data/lib/new_relic/agent/transaction_sample_builder.rb +5 -3
- data/lib/new_relic/agent/transaction_sampler.rb +43 -47
- data/lib/new_relic/control/frameworks/rails.rb +9 -4
- data/lib/new_relic/control/frameworks/rails3.rb +10 -0
- data/lib/new_relic/noticed_error.rb +18 -8
- data/lib/new_relic/rack.rb +4 -0
- data/lib/new_relic/rack/browser_monitoring.rb +2 -0
- data/lib/new_relic/rack/error_collector.rb +56 -0
- data/lib/new_relic/version.rb +3 -3
- data/newrelic.yml +0 -12
- data/newrelic_rpm.gemspec +6 -3
- data/test/new_relic/agent/agent/connect_test.rb +78 -113
- data/test/new_relic/agent/agent/start_test.rb +2 -2
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +6 -33
- data/test/new_relic/agent/agent_test.rb +20 -6
- data/test/new_relic/agent/agent_test_controller_test.rb +7 -5
- data/test/new_relic/agent/beacon_configuration_test.rb +54 -60
- data/test/new_relic/agent/browser_monitoring_test.rb +88 -74
- data/test/new_relic/agent/configuration/manager_test.rb +21 -21
- data/test/new_relic/agent/configuration/server_source_test.rb +21 -4
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
- data/test/new_relic/agent/mock_scope_listener.rb +3 -0
- data/test/new_relic/agent/new_relic_service_test.rb +56 -17
- data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -1
- data/test/new_relic/agent/rpm_agent_test.rb +1 -0
- data/test/new_relic/agent/stats_engine_test.rb +12 -7
- data/test/new_relic/agent/transaction_sampler_test.rb +106 -102
- data/test/new_relic/agent_test.rb +10 -9
- data/test/new_relic/control_test.rb +1 -17
- data/test/new_relic/rack/browser_monitoring_test.rb +11 -5
- data/test/new_relic/rack/error_collector_test.rb +74 -0
- data/test/test_helper.rb +1 -1
- metadata +9 -7
@@ -12,52 +12,38 @@ module NewRelic
|
|
12
12
|
# the static portion of the RUM footer - this part does not vary
|
13
13
|
# by which request is in progress
|
14
14
|
attr_reader :browser_timing_static_footer
|
15
|
-
|
16
|
-
# the application id we include in the javascript -
|
17
|
-
# crossreferences with the application id on the collectors
|
18
|
-
attr_reader :application_id
|
19
15
|
|
20
|
-
# the key used for browser monitoring. This is different from
|
21
|
-
# the account key
|
22
|
-
attr_reader :browser_monitoring_key
|
23
|
-
|
24
|
-
# which beacon we should report to - set by startup of the agent
|
25
|
-
attr_reader :beacon
|
26
|
-
|
27
|
-
# whether RUM is enabled or not - determined based on server and
|
28
|
-
# local config
|
29
|
-
attr_reader :rum_enabled
|
30
|
-
|
31
|
-
# whether JSONP is used to communicate with the Beacon or not
|
32
|
-
attr_reader :rum_jsonp
|
33
|
-
|
34
16
|
# RUM footer command used for 'finish' - based on whether JSONP is
|
35
17
|
# being used. 'nrfj' for JSONP, otherwise 'nrf2'
|
36
18
|
attr_reader :finish_command
|
37
|
-
|
19
|
+
|
38
20
|
# A static javascript header that is identical for every account
|
39
21
|
# and application
|
40
22
|
JS_HEADER = "<script type=\"text/javascript\">var NREUMQ=NREUMQ||[];NREUMQ.push([\"mark\",\"firstbyte\",new Date().getTime()]);</script>"
|
41
|
-
|
23
|
+
|
42
24
|
# Creates a new browser configuration data. Argument is a hash
|
43
25
|
# of configuration values from the server
|
44
|
-
def initialize
|
45
|
-
@browser_monitoring_key = connect_data['browser_key']
|
46
|
-
@application_id = connect_data['application_id']
|
47
|
-
@beacon = connect_data['beacon']
|
48
|
-
@rum_enabled = connect_data['rum.enabled']
|
49
|
-
@rum_enabled = true if @rum_enabled.nil?
|
50
|
-
NewRelic::Control.instance.log.warn("Real User Monitoring is disabled for this agent. Edit your configuration to change this.") unless @rum_enabled
|
26
|
+
def initialize
|
51
27
|
@browser_timing_header = build_browser_timing_header
|
52
28
|
NewRelic::Control.instance.log.debug("Browser timing header: #{@browser_timing_header.inspect}")
|
53
|
-
@browser_timing_static_footer = build_load_file_js
|
29
|
+
@browser_timing_static_footer = build_load_file_js
|
54
30
|
NewRelic::Control.instance.log.debug("Browser timing static footer: #{@browser_timing_static_footer.inspect}")
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
31
|
+
if Agent.config[:'rum.jsonp']
|
32
|
+
NewRelic::Control.instance.log.debug("Real User Monitoring is using JSONP protocol")
|
33
|
+
@finish_command = 'nrfj'
|
34
|
+
else
|
35
|
+
@finish_command = 'nrf2'
|
36
|
+
end
|
37
|
+
|
38
|
+
if !Agent.config[:'rum.enabled']
|
39
|
+
NewRelic::Control.instance.log.warn("Real User Monitoring is disabled for this agent. Edit your configuration to change this.")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def enabled?
|
44
|
+
Agent.config[:'rum.enabled'] && !!Agent.config[:beacon]
|
59
45
|
end
|
60
|
-
|
46
|
+
|
61
47
|
# returns a memoized version of the bytes in the license key for
|
62
48
|
# obscuring transaction names in the javascript
|
63
49
|
def license_bytes
|
@@ -67,26 +53,28 @@ module NewRelic
|
|
67
53
|
end
|
68
54
|
@license_bytes
|
69
55
|
end
|
70
|
-
|
56
|
+
|
71
57
|
# returns a snippet of text that does not change
|
72
58
|
# per-transaction. Is empty when rum is disabled, or we are not
|
73
59
|
# including the episodes file dynamically (i.e. the user
|
74
60
|
# includes it themselves)
|
75
|
-
def build_load_file_js
|
61
|
+
def build_load_file_js
|
76
62
|
js = <<-EOS
|
77
63
|
if (!NREUMQ.f) { NREUMQ.f=function() {
|
78
64
|
NREUMQ.push(["load",new Date().getTime()]);
|
79
65
|
EOS
|
80
|
-
|
81
|
-
if
|
82
|
-
|
66
|
+
|
67
|
+
if Agent.config[:'rum.load_episodes_file'] &&
|
68
|
+
Agent.config[:'rum.load_episodes_file'] != ''
|
83
69
|
js << <<-EOS
|
84
|
-
var e=document.createElement(
|
85
|
-
e.type
|
70
|
+
var e=document.createElement("script");
|
71
|
+
e.type="text/javascript";
|
72
|
+
e.src=(("http:"===document.location.protocol)?"http:":"https:") + "//" +
|
73
|
+
"#{Agent.config[:episodes_file]}";
|
86
74
|
document.body.appendChild(e);
|
87
75
|
EOS
|
88
76
|
end
|
89
|
-
|
77
|
+
|
90
78
|
js << <<-EOS
|
91
79
|
if(NREUMQ.a)NREUMQ.a();
|
92
80
|
};
|
@@ -101,12 +89,12 @@ EOS
|
|
101
89
|
def javascript_header
|
102
90
|
JS_HEADER.dup
|
103
91
|
end
|
104
|
-
|
92
|
+
|
105
93
|
# Returns the header string, properly html-safed if needed
|
106
94
|
def build_browser_timing_header
|
107
|
-
return "" if
|
108
|
-
return "" if
|
109
|
-
|
95
|
+
return "" if !enabled?
|
96
|
+
return "" if Agent.config[:browser_key].nil?
|
97
|
+
|
110
98
|
value = javascript_header
|
111
99
|
if value.respond_to?(:html_safe)
|
112
100
|
value.html_safe
|
@@ -117,5 +105,3 @@ EOS
|
|
117
105
|
end
|
118
106
|
end
|
119
107
|
end
|
120
|
-
|
121
|
-
|
@@ -5,25 +5,22 @@ module NewRelic
|
|
5
5
|
# This module contains support for Real User Monitoring - the
|
6
6
|
# javascript generation and configuration
|
7
7
|
module BrowserMonitoring
|
8
|
-
|
9
|
-
|
10
8
|
class DummyMetricFrame
|
11
9
|
def initialize
|
12
10
|
@attributes = {}
|
13
11
|
end
|
14
|
-
|
12
|
+
|
15
13
|
def user_attributes
|
16
14
|
@attributes
|
17
15
|
end
|
18
|
-
|
16
|
+
|
19
17
|
def queue_time
|
20
18
|
0.0
|
21
19
|
end
|
22
20
|
end
|
23
|
-
|
21
|
+
|
24
22
|
@@dummy_metric_frame = DummyMetricFrame.new
|
25
|
-
|
26
|
-
|
23
|
+
|
27
24
|
# This method returns a string suitable for inclusion in a page
|
28
25
|
# - known as 'manual instrumentation' for Real User
|
29
26
|
# Monitoring. Can return either a script tag with associated
|
@@ -34,8 +31,8 @@ module NewRelic
|
|
34
31
|
# page as is reasonably possible - that is, before any style or
|
35
32
|
# javascript inclusions, but after any header-related meta tags
|
36
33
|
def browser_timing_header
|
37
|
-
if NewRelic::Agent.instance.beacon_configuration.nil? ||
|
38
|
-
!NewRelic::Agent.is_transaction_traced? ||
|
34
|
+
if NewRelic::Agent.instance.beacon_configuration.nil? ||
|
35
|
+
!NewRelic::Agent.is_transaction_traced? ||
|
39
36
|
!NewRelic::Agent.is_execution_traced? ||
|
40
37
|
NewRelic::Agent::TransactionInfo.get.ignore_end_user?
|
41
38
|
return ""
|
@@ -54,16 +51,17 @@ module NewRelic
|
|
54
51
|
# page as is reasonably possible.
|
55
52
|
def browser_timing_footer
|
56
53
|
config = NewRelic::Agent.instance.beacon_configuration
|
57
|
-
|
58
|
-
if config.nil? ||
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
|
55
|
+
if config.nil? ||
|
56
|
+
!config.enabled? ||
|
57
|
+
Agent.config[:browser_key].nil? ||
|
58
|
+
Agent.config[:browser_key].empty? ||
|
59
|
+
!NewRelic::Agent.is_transaction_traced? ||
|
60
|
+
!NewRelic::Agent.is_execution_traced? ||
|
61
|
+
NewRelic::Agent::TransactionInfo.get.ignore_end_user?
|
62
|
+
return ""
|
65
63
|
end
|
66
|
-
|
64
|
+
|
67
65
|
generate_footer_js(config)
|
68
66
|
end
|
69
67
|
|
@@ -114,7 +112,7 @@ module NewRelic
|
|
114
112
|
|
115
113
|
response['X-NewRelic-Beacon-Url'] = beacon_url(request)
|
116
114
|
|
117
|
-
payload = %[ ["#{config
|
115
|
+
payload = %[ ["#{Agent.config[:application_id]}","#{obfuscate(config, browser_monitoring_transaction_name)}",#{browser_monitoring_queue_time},#{browser_monitoring_app_time}] ]
|
118
116
|
response['X-NewRelic-App-Server-Metrics'] = payload
|
119
117
|
end
|
120
118
|
end
|
@@ -126,24 +124,19 @@ module NewRelic
|
|
126
124
|
end
|
127
125
|
|
128
126
|
def beacon_url(request)
|
129
|
-
|
130
|
-
"#{request.scheme || 'http'}://#{config.beacon}/mobile/1/#{config.browser_monitoring_key}"
|
127
|
+
"#{request.scheme || 'http'}://#{Agent.config[:beacon]}/mobile/1/#{Agent.config[:browser_key]}"
|
131
128
|
end
|
132
129
|
|
133
130
|
private
|
134
131
|
|
135
132
|
def generate_footer_js(config)
|
136
133
|
if browser_monitoring_start_time
|
137
|
-
|
138
|
-
beacon = config.beacon
|
139
|
-
license_key = config.browser_monitoring_key
|
140
|
-
|
141
|
-
footer_js_string(config, beacon, license_key, application_id)
|
134
|
+
footer_js_string(config)
|
142
135
|
else
|
143
136
|
''
|
144
137
|
end
|
145
138
|
end
|
146
|
-
|
139
|
+
|
147
140
|
def metric_frame_attribute(key)
|
148
141
|
current_metric_frame.user_attributes[key] || ""
|
149
142
|
end
|
@@ -153,19 +146,19 @@ module NewRelic
|
|
153
146
|
return txn.guid if txn.include_guid?
|
154
147
|
""
|
155
148
|
end
|
156
|
-
|
149
|
+
|
157
150
|
def tt_token
|
158
151
|
return NewRelic::Agent::TransactionInfo.get.token
|
159
152
|
end
|
160
|
-
|
161
|
-
def footer_js_string(config
|
153
|
+
|
154
|
+
def footer_js_string(config)
|
162
155
|
obfuscated_transaction_name = obfuscate(config, browser_monitoring_transaction_name)
|
163
|
-
|
156
|
+
|
164
157
|
user = obfuscate(config, metric_frame_attribute(:user))
|
165
158
|
account = obfuscate(config, metric_frame_attribute(:account))
|
166
159
|
product = obfuscate(config, metric_frame_attribute(:product))
|
167
|
-
|
168
|
-
html_safe_if_needed("<script type=\"text/javascript\">#{config.browser_timing_static_footer}NREUMQ.push([\"#{config.finish_command}\",\"#{beacon}\",\"#{
|
160
|
+
|
161
|
+
html_safe_if_needed("<script type=\"text/javascript\">#{config.browser_timing_static_footer}NREUMQ.push([\"#{config.finish_command}\",\"#{Agent.config[:beacon]}\",\"#{Agent.config[:browser_key]}\",#{Agent.config[:application_id]},\"#{obfuscated_transaction_name}\",#{browser_monitoring_queue_time},#{browser_monitoring_app_time},new Date().getTime(),\"#{tt_guid}\",\"#{tt_token}\",\"#{user}\",\"#{account}\",\"#{product}\"]);</script>")
|
169
162
|
end
|
170
163
|
|
171
164
|
def html_safe_if_needed(string)
|
@@ -21,18 +21,20 @@ module NewRelic
|
|
21
21
|
:multi_homed => false,
|
22
22
|
:high_security => false,
|
23
23
|
|
24
|
-
:host
|
25
|
-
:api_host
|
26
|
-
:port
|
27
|
-
:api_port
|
28
|
-
:ssl
|
29
|
-
:verify_certificate
|
30
|
-
:sync_startup
|
31
|
-
:send_data_on_exit
|
32
|
-
:post_size_limit
|
33
|
-
:timeout
|
34
|
-
:force_send
|
35
|
-
:send_environment_info
|
24
|
+
:host => 'collector.newrelic.com',
|
25
|
+
:api_host => 'rpm.newrelic.com',
|
26
|
+
:port => Proc.new { self[:ssl] ? 443 : 80 },
|
27
|
+
:api_port => Proc.new { self[:port] },
|
28
|
+
:ssl => false,
|
29
|
+
:verify_certificate => false,
|
30
|
+
:sync_startup => false,
|
31
|
+
:send_data_on_exit => true,
|
32
|
+
:post_size_limit => 2 * 1024 * 1024, # 2 megs
|
33
|
+
:timeout => 2 * 60, # 2 minutes
|
34
|
+
:force_send => false,
|
35
|
+
:send_environment_info => true,
|
36
|
+
:start_channel_listener => false,
|
37
|
+
:data_report_period => 60,
|
36
38
|
|
37
39
|
:log_file_name => 'newrelic_agent.log',
|
38
40
|
:log_file_path => 'log/',
|
@@ -59,6 +61,7 @@ module NewRelic
|
|
59
61
|
:'transaction_tracer.record_sql' => 'obfuscated',
|
60
62
|
:'transaction_tracer.limit_segments' => 4000,
|
61
63
|
:'transaction_tracer.random_sample' => false,
|
64
|
+
:sample_rate => 10,
|
62
65
|
|
63
66
|
:'slow_sql.enabled' => Proc.new { self[:'transaction_tracer.enabled'] },
|
64
67
|
:'slow_sql.stack_trace_threshold' => Proc.new { self[:'transaction_tracer.stack_trace_threshold'] },
|
@@ -68,7 +71,12 @@ module NewRelic
|
|
68
71
|
|
69
72
|
:'error_collector.enabled' => true,
|
70
73
|
:'error_collector.capture_source' => true,
|
71
|
-
:'error_collector.ignore_errors' => 'ActionController::RoutingError'
|
74
|
+
:'error_collector.ignore_errors' => 'ActionController::RoutingError',
|
75
|
+
|
76
|
+
:'rum.enabled' => true,
|
77
|
+
:'rum.jsonp' => true,
|
78
|
+
:'rum.load_episodes_file' => true,
|
79
|
+
:'browser_monitoring.auto_instrument' => Proc.new { self[:'rum.enabled'] }
|
72
80
|
}.freeze
|
73
81
|
end
|
74
82
|
end
|
@@ -15,11 +15,13 @@ module NewRelic
|
|
15
15
|
def initialize
|
16
16
|
@config_stack = [ EnvironmentSource.new, DEFAULTS ]
|
17
17
|
@cache = Hash.new {|hash,key| hash[key] = self.fetch(key) }
|
18
|
+
@callbacks = Hash.new {|hash,key| hash[key] = [] }
|
18
19
|
end
|
19
20
|
|
20
21
|
def apply_config(source, level=0)
|
22
|
+
invoke_callbacks(:add, source)
|
21
23
|
@config_stack.insert(level, source.freeze)
|
22
|
-
|
24
|
+
reset_cache
|
23
25
|
end
|
24
26
|
|
25
27
|
def remove_config(source=nil)
|
@@ -28,7 +30,8 @@ module NewRelic
|
|
28
30
|
else
|
29
31
|
@config_stack.delete(source)
|
30
32
|
end
|
31
|
-
|
33
|
+
reset_cache
|
34
|
+
invoke_callbacks(:remove, source)
|
32
35
|
end
|
33
36
|
|
34
37
|
def replace_or_add_config(source, level=0)
|
@@ -49,9 +52,7 @@ module NewRelic
|
|
49
52
|
@config_stack.each do |config|
|
50
53
|
next unless config
|
51
54
|
accessor = key.to_sym
|
52
|
-
if config.
|
53
|
-
return config.send(accessor)
|
54
|
-
elsif config.has_key?(accessor)
|
55
|
+
if config.has_key?(accessor)
|
55
56
|
if config[accessor].respond_to?(:call)
|
56
57
|
return instance_eval(&config[accessor])
|
57
58
|
else
|
@@ -62,6 +63,26 @@ module NewRelic
|
|
62
63
|
nil
|
63
64
|
end
|
64
65
|
|
66
|
+
def register_callback(key, &proc)
|
67
|
+
@callbacks[key] << proc
|
68
|
+
proc.call(@cache[key])
|
69
|
+
end
|
70
|
+
|
71
|
+
def invoke_callbacks(direction, source)
|
72
|
+
return unless source
|
73
|
+
source.keys.each do |key|
|
74
|
+
if @cache[key] != source[key]
|
75
|
+
@callbacks[key].each do |proc|
|
76
|
+
if direction == :add
|
77
|
+
proc.call(source[key])
|
78
|
+
else
|
79
|
+
proc.call(@cache[key])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
65
86
|
def flattened_config
|
66
87
|
@config_stack.reverse.inject({}) do |flat,layer|
|
67
88
|
thawed_layer = layer.dup
|
@@ -69,7 +90,7 @@ module NewRelic
|
|
69
90
|
begin
|
70
91
|
thawed_layer[k] = instance_eval(&v) if v.respond_to?(:call)
|
71
92
|
rescue => e
|
72
|
-
NewRelic::Control.instance.log.debug("#{e.class.name} : #{e.message} - when
|
93
|
+
NewRelic::Control.instance.log.debug("#{e.class.name} : #{e.message} - when accessing config key #{k}")
|
73
94
|
thawed_layer[k] = nil
|
74
95
|
end
|
75
96
|
thawed_layer.delete(:config)
|
@@ -78,13 +99,6 @@ module NewRelic
|
|
78
99
|
end
|
79
100
|
end
|
80
101
|
|
81
|
-
def exclude_rails_config(hash, key)
|
82
|
-
if defined?(::Rails::Configuration) &&
|
83
|
-
hash[key].kind_of?(::Rails::Configuration)
|
84
|
-
hash.delete(key)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
102
|
def app_names
|
89
103
|
case self[:app_name]
|
90
104
|
when Array then self[:app_name]
|
@@ -93,7 +107,7 @@ module NewRelic
|
|
93
107
|
end
|
94
108
|
end
|
95
109
|
|
96
|
-
def
|
110
|
+
def reset_cache
|
97
111
|
@cache = Hash.new {|hash,key| hash[key] = self.fetch(key) }
|
98
112
|
end
|
99
113
|
end
|
@@ -3,6 +3,14 @@ module NewRelic
|
|
3
3
|
module Configuration
|
4
4
|
class ServerSource < DottedHash
|
5
5
|
def initialize(hash)
|
6
|
+
if hash['agent_config']
|
7
|
+
if hash['agent_config']['transaction_tracer.transaction_threshold'] =~ /apdex_f/i
|
8
|
+
# when value is "apdex_f" remove the config and defer to default
|
9
|
+
hash['agent_config'].delete('transaction_tracer.transaction_threshold')
|
10
|
+
end
|
11
|
+
super(hash.delete('agent_config'))
|
12
|
+
end
|
13
|
+
|
6
14
|
string_map = [
|
7
15
|
['collect_traces', 'transaction_tracer.enabled'],
|
8
16
|
['collect_traces', 'slow_sql.enabled'],
|
@@ -11,11 +19,6 @@ module NewRelic
|
|
11
19
|
hash[pair[1]] = hash[pair[0]] if hash[pair[0]] != nil
|
12
20
|
end
|
13
21
|
|
14
|
-
if hash['transaction_tracer.transaction_threshold'] =~ /apdex_f/i
|
15
|
-
# when value is "apdex_f" remove the config and defer to default
|
16
|
-
hash.delete('transaction_tracer.transaction_threshold')
|
17
|
-
end
|
18
|
-
|
19
22
|
super
|
20
23
|
end
|
21
24
|
end
|
@@ -14,27 +14,42 @@ module NewRelic
|
|
14
14
|
"Rows",
|
15
15
|
"Extra"
|
16
16
|
].freeze
|
17
|
-
|
17
|
+
|
18
18
|
module Agent
|
19
19
|
module Database
|
20
20
|
extend self
|
21
|
-
|
21
|
+
|
22
22
|
def obfuscate_sql(sql)
|
23
23
|
Obfuscator.instance.obfuscator.call(sql)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def set_sql_obfuscator(type, &block)
|
27
27
|
Obfuscator.instance.set_sql_obfuscator(type, &block)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
|
+
def record_sql_method
|
31
|
+
case Agent.config[:'transaction_tracer.record_sql'].to_s
|
32
|
+
when 'off'
|
33
|
+
:off
|
34
|
+
when 'none'
|
35
|
+
:off
|
36
|
+
when 'false'
|
37
|
+
:off
|
38
|
+
when 'raw'
|
39
|
+
:raw
|
40
|
+
else
|
41
|
+
:obfuscated
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
30
45
|
def get_connection(config)
|
31
46
|
ConnectionManager.instance.get_connection(config)
|
32
47
|
end
|
33
|
-
|
48
|
+
|
34
49
|
def close_connections
|
35
50
|
ConnectionManager.instance.close_connections
|
36
51
|
end
|
37
|
-
|
52
|
+
|
38
53
|
# Perform this in the runtime environment of a managed
|
39
54
|
# application, to explain the sql statement executed within a
|
40
55
|
# segment of a transaction sample. Returns an array of
|
@@ -50,7 +65,7 @@ module NewRelic
|
|
50
65
|
explain_sql = explain_statement(statement, connection_config)
|
51
66
|
return explain_sql || []
|
52
67
|
end
|
53
|
-
|
68
|
+
|
54
69
|
def explain_statement(statement, config)
|
55
70
|
if is_select?(statement)
|
56
71
|
handle_exception_in_explain do
|
@@ -63,12 +78,12 @@ module NewRelic
|
|
63
78
|
end
|
64
79
|
end
|
65
80
|
end
|
66
|
-
|
81
|
+
|
67
82
|
def process_resultset(items)
|
68
83
|
# The resultset type varies for different drivers. Only thing you can count on is
|
69
84
|
# that it implements each. Also: can't use select_rows because the native postgres
|
70
85
|
# driver doesn't know that method.
|
71
|
-
|
86
|
+
|
72
87
|
headers = []
|
73
88
|
values = []
|
74
89
|
if items.respond_to?(:each_hash)
|
@@ -88,7 +103,7 @@ module NewRelic
|
|
88
103
|
else
|
89
104
|
values = [items]
|
90
105
|
end
|
91
|
-
|
106
|
+
|
92
107
|
headers = nil if headers.empty?
|
93
108
|
[headers, values]
|
94
109
|
end
|
@@ -104,14 +119,14 @@ module NewRelic
|
|
104
119
|
# double exception. throw up your hands
|
105
120
|
end
|
106
121
|
end
|
107
|
-
|
122
|
+
|
108
123
|
def is_select?(statement)
|
109
124
|
# split the string into at most two segments on the
|
110
125
|
# system-defined field separator character
|
111
126
|
first_word, rest_of_statement = statement.split($;, 2)
|
112
127
|
(first_word.upcase == 'SELECT')
|
113
128
|
end
|
114
|
-
|
129
|
+
|
115
130
|
class ConnectionManager
|
116
131
|
include Singleton
|
117
132
|
|
@@ -121,11 +136,11 @@ module NewRelic
|
|
121
136
|
# the sql
|
122
137
|
def get_connection(config)
|
123
138
|
@connections ||= {}
|
124
|
-
|
139
|
+
|
125
140
|
connection = @connections[config]
|
126
|
-
|
141
|
+
|
127
142
|
return connection if connection
|
128
|
-
|
143
|
+
|
129
144
|
begin
|
130
145
|
connection = ActiveRecord::Base.send("#{config[:adapter]}_connection", config)
|
131
146
|
@connections[config] = connection
|
@@ -135,7 +150,7 @@ module NewRelic
|
|
135
150
|
nil
|
136
151
|
end
|
137
152
|
end
|
138
|
-
|
153
|
+
|
139
154
|
# Closes all the connections in the internal connection cache
|
140
155
|
def close_connections
|
141
156
|
@connections ||= {}
|
@@ -145,16 +160,16 @@ module NewRelic
|
|
145
160
|
rescue
|
146
161
|
end
|
147
162
|
end
|
148
|
-
|
163
|
+
|
149
164
|
@connections = {}
|
150
165
|
end
|
151
166
|
end
|
152
167
|
|
153
168
|
class Obfuscator
|
154
169
|
include Singleton
|
155
|
-
|
170
|
+
|
156
171
|
attr_reader :obfuscator
|
157
|
-
|
172
|
+
|
158
173
|
def initialize
|
159
174
|
reset
|
160
175
|
end
|
@@ -162,7 +177,7 @@ module NewRelic
|
|
162
177
|
def reset
|
163
178
|
@obfuscator = method(:default_sql_obfuscator)
|
164
179
|
end
|
165
|
-
|
180
|
+
|
166
181
|
# Sets the sql obfuscator used to clean up sql when sending it
|
167
182
|
# to the server. Possible types are:
|
168
183
|
#
|
@@ -185,7 +200,7 @@ module NewRelic
|
|
185
200
|
fail "unknown sql_obfuscator type #{type}"
|
186
201
|
end
|
187
202
|
end
|
188
|
-
|
203
|
+
|
189
204
|
def default_sql_obfuscator(sql)
|
190
205
|
stmt = sql.kind_of?(Statement) ? sql : Statement.new(sql)
|
191
206
|
adapter = stmt.adapter
|
@@ -215,7 +230,7 @@ module NewRelic
|
|
215
230
|
end
|
216
231
|
end
|
217
232
|
|
218
|
-
class Statement < String
|
233
|
+
class Statement < String
|
219
234
|
attr_accessor :adapter
|
220
235
|
end
|
221
236
|
end
|