newrelic_rpm 3.7.0.174.beta → 3.7.0.177
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +27 -4
- data/bin/nrdebug +10 -4
- data/lib/new_relic/agent.rb +33 -11
- data/lib/new_relic/agent/agent.rb +83 -120
- data/lib/new_relic/agent/agent_logger.rb +28 -16
- data/lib/new_relic/agent/audit_logger.rb +3 -4
- data/lib/new_relic/agent/autostart.rb +20 -8
- data/lib/new_relic/agent/commands/agent_command_router.rb +26 -17
- data/lib/new_relic/agent/commands/thread_profiler_session.rb +2 -2
- data/lib/new_relic/agent/configuration/default_source.rb +146 -59
- data/lib/new_relic/agent/configuration/manager.rb +3 -3
- data/lib/new_relic/agent/cross_app_monitor.rb +15 -40
- data/lib/new_relic/agent/cross_app_tracing.rb +20 -12
- data/lib/new_relic/agent/database.rb +24 -0
- data/lib/new_relic/agent/error_collector.rb +6 -2
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +3 -1
- data/lib/new_relic/agent/javascript_instrumentor.rb +187 -0
- data/lib/new_relic/agent/new_relic_service.rb +30 -22
- data/lib/new_relic/agent/obfuscator.rb +48 -0
- data/lib/new_relic/agent/request_sampler.rb +5 -13
- data/lib/new_relic/agent/shim_agent.rb +1 -0
- data/lib/new_relic/agent/sql_sampler.rb +15 -5
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +9 -4
- data/lib/new_relic/agent/transaction.rb +0 -1
- data/lib/new_relic/agent/transaction_sampler.rb +28 -16
- data/lib/new_relic/agent/transaction_state.rb +9 -0
- data/lib/new_relic/agent/transaction_timings.rb +5 -1
- data/lib/new_relic/agent/worker_loop.rb +0 -10
- data/lib/new_relic/cli/deployments.rb +1 -1
- data/lib/new_relic/control/instance_methods.rb +1 -1
- data/lib/new_relic/helper.rb +3 -1
- data/lib/new_relic/rack/browser_monitoring.rb +1 -2
- data/lib/new_relic/transaction_sample.rb +11 -13
- data/lib/newrelic_rpm.rb +1 -0
- data/test/agent_helper.rb +20 -5
- data/test/environments/lib/environments/runner.rb +1 -0
- data/test/helpers/file_searching.rb +28 -0
- data/test/multiverse/lib/multiverse/suite.rb +36 -19
- data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +49 -0
- data/test/multiverse/suites/agent_only/http_response_code_test.rb +2 -2
- data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +4 -2
- data/test/multiverse/suites/agent_only/service_timeout_test.rb +1 -1
- data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +7 -4
- data/test/multiverse/suites/agent_only/thread_profiling_test.rb +2 -1
- data/test/multiverse/suites/rails/error_tracing_test.rb +34 -4
- data/test/multiverse/suites/rails/ignore_test.rb +1 -1
- data/test/multiverse/suites/rails/request_statistics_test.rb +1 -3
- data/test/multiverse/suites/sequel/sequel_instrumentation_test.rb +10 -7
- data/test/multiverse/suites/sinatra/ignoring_test.rb +1 -1
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -1
- data/test/new_relic/agent/agent_logger_test.rb +108 -114
- data/test/new_relic/agent/agent_test.rb +139 -21
- data/test/new_relic/agent/audit_logger_test.rb +22 -20
- data/test/new_relic/agent/autostart_test.rb +3 -2
- data/test/new_relic/agent/commands/agent_command_router_test.rb +51 -32
- data/test/new_relic/agent/configuration/default_source_test.rb +8 -2
- data/test/new_relic/agent/configuration/manager_test.rb +5 -1
- data/test/new_relic/agent/configuration/orphan_configuration_test.rb +57 -0
- data/test/new_relic/agent/cross_app_monitor_test.rb +10 -26
- data/test/new_relic/agent/database_test.rb +32 -0
- data/test/new_relic/agent/error_collector_test.rb +33 -16
- data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +88 -71
- data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
- data/test/new_relic/agent/javascript_instrumentor_test.rb +341 -0
- data/test/new_relic/agent/memcache_instrumentation_test.rb +91 -89
- data/test/new_relic/agent/method_tracer_test.rb +1 -1
- data/test/new_relic/agent/obfuscator_test.rb +77 -0
- data/test/new_relic/agent/pipe_channel_manager_test.rb +5 -5
- data/test/new_relic/agent/pipe_service_test.rb +1 -1
- data/test/new_relic/agent/request_sampler_test.rb +21 -11
- data/test/new_relic/agent/sql_sampler_test.rb +52 -8
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +6 -6
- data/test/new_relic/agent/stats_engine_test.rb +18 -2
- data/test/new_relic/agent/transaction_sampler_test.rb +98 -53
- data/test/new_relic/agent/transaction_state_test.rb +44 -0
- data/test/new_relic/agent/transaction_test.rb +1 -1
- data/test/new_relic/agent/transaction_timings_test.rb +15 -5
- data/test/new_relic/agent/worker_loop_test.rb +0 -9
- data/test/new_relic/agent_test.rb +9 -21
- data/test/new_relic/data_container_tests.rb +72 -0
- data/test/new_relic/fake_collector.rb +69 -20
- data/test/new_relic/http_client_test_cases.rb +17 -2
- data/test/new_relic/license_test.rb +6 -15
- data/test/new_relic/multiverse_helpers.rb +2 -3
- data/test/new_relic/rack/browser_monitoring_test.rb +15 -37
- data/test/new_relic/transaction_sample_test.rb +92 -62
- data/test/performance/suites/rum_autoinsertion.rb +0 -3
- data/test/rum/x_ua_meta_tag_spaces_around_equals.result.html +10 -0
- data/test/rum/x_ua_meta_tag_spaces_around_equals.source.html +10 -0
- data/test/test_helper.rb +9 -5
- metadata +29 -11
- metadata.gz.sig +0 -0
- data/lib/new_relic/agent/beacon_configuration.rb +0 -37
- data/lib/new_relic/agent/browser_monitoring.rb +0 -257
- data/test/new_relic/agent/beacon_configuration_test.rb +0 -44
- data/test/new_relic/agent/browser_monitoring_test.rb +0 -474
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
|
5
|
-
module NewRelic
|
6
|
-
module Agent
|
7
|
-
# This class contains the configuration data for setting up RUM
|
8
|
-
# headers and footers - acts as a cache of this data so we don't
|
9
|
-
# need to look it up or reconfigure it every request
|
10
|
-
class BeaconConfiguration
|
11
|
-
|
12
|
-
# Creates a new browser configuration data. Argument is a hash
|
13
|
-
# of configuration values from the server
|
14
|
-
def initialize
|
15
|
-
::NewRelic::Agent.logger.debug("JS agent loader version: #{Agent.config[:'browser_monitoring.loader_version']}")
|
16
|
-
|
17
|
-
if !Agent.config[:'rum.enabled']
|
18
|
-
::NewRelic::Agent.logger.debug("Real User Monitoring is disabled for this agent. Edit your configuration to change this.")
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def enabled?
|
23
|
-
Agent.config[:'rum.enabled'] && !!Agent.config[:beacon]
|
24
|
-
end
|
25
|
-
|
26
|
-
# returns a memoized version of the bytes in the license key for
|
27
|
-
# obscuring transaction names in the javascript
|
28
|
-
def license_bytes
|
29
|
-
if @license_bytes.nil?
|
30
|
-
@license_bytes = []
|
31
|
-
Agent.config[:license_key].each_byte {|byte| @license_bytes << byte}
|
32
|
-
end
|
33
|
-
@license_bytes
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,257 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
|
5
|
-
require 'base64'
|
6
|
-
require 'new_relic/agent/beacon_configuration'
|
7
|
-
require 'new_relic/agent/transaction_timings'
|
8
|
-
|
9
|
-
module NewRelic
|
10
|
-
module Agent
|
11
|
-
# This module contains support for Real User Monitoring - the
|
12
|
-
# javascript generation and configuration
|
13
|
-
#
|
14
|
-
# @api public
|
15
|
-
module BrowserMonitoring
|
16
|
-
include NewRelic::Coerce
|
17
|
-
|
18
|
-
class DummyTransaction
|
19
|
-
|
20
|
-
attr_reader :custom_parameters
|
21
|
-
attr_accessor :start_time
|
22
|
-
|
23
|
-
def initialize
|
24
|
-
@custom_parameters = {}
|
25
|
-
end
|
26
|
-
|
27
|
-
def queue_time
|
28
|
-
0.0
|
29
|
-
end
|
30
|
-
|
31
|
-
def timings
|
32
|
-
NewRelic::Agent::TransactionTimings.new(0.0, NewRelic::Agent::TransactionState.get)
|
33
|
-
end
|
34
|
-
|
35
|
-
def name
|
36
|
-
::NewRelic::Agent::UNKNOWN_METRIC
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
@@dummy_txn = DummyTransaction.new
|
41
|
-
|
42
|
-
# This method returns a string suitable for inclusion in a page
|
43
|
-
# - known as 'manual instrumentation' for Real User
|
44
|
-
# Monitoring. Can return either a script tag with associated
|
45
|
-
# javascript, or in the case of disabled Real User Monitoring,
|
46
|
-
# an empty string
|
47
|
-
#
|
48
|
-
# This is the header string - it should be placed as high in the
|
49
|
-
# page as is reasonably possible - that is, before any style or
|
50
|
-
# javascript inclusions, but after any header-related meta tags
|
51
|
-
#
|
52
|
-
# @api public
|
53
|
-
#
|
54
|
-
def browser_timing_header
|
55
|
-
insert_js? ? header_js_string : ""
|
56
|
-
end
|
57
|
-
|
58
|
-
# This method returns a string suitable for inclusion in a page
|
59
|
-
# - known as 'manual instrumentation' for Real User
|
60
|
-
# Monitoring. Can return either a script tag with associated
|
61
|
-
# javascript, or in the case of disabled Real User Monitoring,
|
62
|
-
# an empty string
|
63
|
-
#
|
64
|
-
# This is the footer string - it should be placed as low in the
|
65
|
-
# page as is reasonably possible.
|
66
|
-
#
|
67
|
-
# @api public
|
68
|
-
#
|
69
|
-
def browser_timing_footer
|
70
|
-
if insert_js?
|
71
|
-
NewRelic::Agent::Transaction.freeze_name
|
72
|
-
generate_footer_js(NewRelic::Agent.instance.beacon_configuration)
|
73
|
-
else
|
74
|
-
""
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
module_function
|
79
|
-
|
80
|
-
def obfuscate(config, text)
|
81
|
-
obfuscated = ""
|
82
|
-
if defined?(::Encoding::ASCII_8BIT)
|
83
|
-
obfuscated.force_encoding(::Encoding::ASCII_8BIT)
|
84
|
-
end
|
85
|
-
key_bytes = config.license_bytes
|
86
|
-
index = 0
|
87
|
-
text.each_byte{|byte|
|
88
|
-
obfuscated.concat((byte ^ key_bytes[index % 13].to_i))
|
89
|
-
index+=1
|
90
|
-
}
|
91
|
-
|
92
|
-
[obfuscated].pack("m0").gsub("\n", '')
|
93
|
-
end
|
94
|
-
|
95
|
-
def browser_monitoring_transaction_name
|
96
|
-
current_timings.transaction_name || ::NewRelic::Agent::UNKNOWN_METRIC
|
97
|
-
end
|
98
|
-
|
99
|
-
def current_transaction
|
100
|
-
NewRelic::Agent::TransactionState.get.transaction || @@dummy_txn
|
101
|
-
end
|
102
|
-
|
103
|
-
def current_timings
|
104
|
-
NewRelic::Agent::TransactionState.get.timings
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
# Check whether RUM header and footer should be generated. Log the
|
110
|
-
# reason if they shouldn't.
|
111
|
-
def insert_js?
|
112
|
-
if NewRelic::Agent.instance.beacon_configuration.nil?
|
113
|
-
::NewRelic::Agent.logger.debug "Beacon configuration is nil. Skipping browser instrumentation."
|
114
|
-
false
|
115
|
-
elsif ! NewRelic::Agent.instance.beacon_configuration.enabled?
|
116
|
-
::NewRelic::Agent.logger.debug "Beacon configuration is disabled. Skipping browser instrumentation."
|
117
|
-
::NewRelic::Agent.logger.debug NewRelic::Agent.instance.beacon_configuration.inspect
|
118
|
-
false
|
119
|
-
elsif Agent.config[:browser_key].nil? || Agent.config[:browser_key].empty?
|
120
|
-
::NewRelic::Agent.logger.debug "Browser key is not set. Skipping browser instrumentation."
|
121
|
-
false
|
122
|
-
elsif ! NewRelic::Agent.is_transaction_traced?
|
123
|
-
::NewRelic::Agent.logger.debug "Transaction is not traced. Skipping browser instrumentation."
|
124
|
-
false
|
125
|
-
elsif ! NewRelic::Agent.is_execution_traced?
|
126
|
-
::NewRelic::Agent.logger.debug "Execution is not traced. Skipping browser instrumentation."
|
127
|
-
false
|
128
|
-
elsif NewRelic::Agent::TransactionState.get.request_ignore_enduser
|
129
|
-
::NewRelic::Agent.logger.debug "Ignore end user for this transaction is set. Skipping browser instrumentation."
|
130
|
-
false
|
131
|
-
else
|
132
|
-
true
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def generate_footer_js(config)
|
137
|
-
if current_transaction.start_time
|
138
|
-
footer_js_string(config)
|
139
|
-
else
|
140
|
-
''
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def tt_guid
|
145
|
-
state = NewRelic::Agent::TransactionState.get
|
146
|
-
return state.request_guid if include_guid?(state)
|
147
|
-
""
|
148
|
-
end
|
149
|
-
|
150
|
-
def include_guid?(state)
|
151
|
-
state.request_token &&
|
152
|
-
state.timings.app_time_in_seconds > state.transaction.apdex_t
|
153
|
-
end
|
154
|
-
|
155
|
-
def tt_token
|
156
|
-
return NewRelic::Agent::TransactionState.get.request_token
|
157
|
-
end
|
158
|
-
|
159
|
-
def js_agent_loader
|
160
|
-
Agent.config[:js_agent_loader].to_s
|
161
|
-
end
|
162
|
-
|
163
|
-
def has_loader?
|
164
|
-
!js_agent_loader.empty?
|
165
|
-
end
|
166
|
-
|
167
|
-
# NOTE: Internal prototyping often overrides this, so leave name stable!
|
168
|
-
def header_js_string
|
169
|
-
return "" unless has_loader?
|
170
|
-
html_safe_if_needed("\n<script type=\"text/javascript\">#{js_agent_loader}</script>")
|
171
|
-
end
|
172
|
-
|
173
|
-
# NOTE: Internal prototyping often overrides this, so leave name stable!
|
174
|
-
def footer_js_string(config)
|
175
|
-
data = js_data(config)
|
176
|
-
html_safe_if_needed("\n<script type=\"text/javascript\">window.NREUM||(NREUM={});NREUM.info=#{NewRelic.json_dump(data)}</script>")
|
177
|
-
end
|
178
|
-
|
179
|
-
BEACON_KEY = "beacon".freeze
|
180
|
-
ERROR_BEACON_KEY = "errorBeacon".freeze
|
181
|
-
LICENSE_KEY_KEY = "licenseKey".freeze
|
182
|
-
APPLICATIONID_KEY = "applicationID".freeze
|
183
|
-
TRANSACTION_NAME_KEY = "transactionName".freeze
|
184
|
-
QUEUE_TIME_KEY = "queueTime".freeze
|
185
|
-
APPLICATION_TIME_KEY = "applicationTime".freeze
|
186
|
-
TT_GUID_KEY = "ttGuid".freeze
|
187
|
-
AGENT_TOKEN_KEY = "agentToken".freeze
|
188
|
-
AGENT_KEY = "agent".freeze
|
189
|
-
EXTRA_KEY = "extra".freeze
|
190
|
-
|
191
|
-
# NOTE: Internal prototyping may override this, so leave name stable!
|
192
|
-
def js_data(config)
|
193
|
-
{
|
194
|
-
BEACON_KEY => NewRelic::Agent.config[:beacon],
|
195
|
-
ERROR_BEACON_KEY => NewRelic::Agent.config[:error_beacon],
|
196
|
-
LICENSE_KEY_KEY => NewRelic::Agent.config[:browser_key],
|
197
|
-
APPLICATIONID_KEY => NewRelic::Agent.config[:application_id],
|
198
|
-
TRANSACTION_NAME_KEY => obfuscate(config, browser_monitoring_transaction_name),
|
199
|
-
QUEUE_TIME_KEY => current_timings.queue_time_in_millis,
|
200
|
-
APPLICATION_TIME_KEY => current_timings.app_time_in_millis,
|
201
|
-
TT_GUID_KEY => tt_guid,
|
202
|
-
AGENT_TOKEN_KEY => tt_token,
|
203
|
-
AGENT_KEY => NewRelic::Agent.config[:js_agent_file],
|
204
|
-
EXTRA_KEY => obfuscate(config, format_extra_data(extra_data))
|
205
|
-
}
|
206
|
-
end
|
207
|
-
|
208
|
-
ANALYTICS_ENABLED = :'analytics_events.enabled'
|
209
|
-
ANALYTICS_TXN_ENABLED = :'analytics_events.transactions.enabled'
|
210
|
-
ANALYTICS_TXN_IN_PAGE = :'capture_attributes.page_view_events'
|
211
|
-
|
212
|
-
# NOTE: Internal prototyping may override this, so leave name stable!
|
213
|
-
def extra_data
|
214
|
-
return {} unless include_custom_parameters_in_extra?
|
215
|
-
current_transaction.custom_parameters.dup
|
216
|
-
end
|
217
|
-
|
218
|
-
def include_custom_parameters_in_extra?
|
219
|
-
NewRelic::Agent.config[ANALYTICS_ENABLED] &&
|
220
|
-
NewRelic::Agent.config[ANALYTICS_TXN_ENABLED] &&
|
221
|
-
NewRelic::Agent.config[ANALYTICS_TXN_IN_PAGE]
|
222
|
-
end
|
223
|
-
|
224
|
-
# Format the props using semicolon separated pairs separated by '=':
|
225
|
-
# product=pro;user=bill@microsoft.com
|
226
|
-
def format_extra_data(extra_props)
|
227
|
-
extra_props = event_params(extra_props)
|
228
|
-
extra_props.map do |k, v|
|
229
|
-
key = escape_special_characters(k)
|
230
|
-
value = format_value(v)
|
231
|
-
"#{key}=#{value}"
|
232
|
-
end.join(';')
|
233
|
-
end
|
234
|
-
|
235
|
-
def escape_special_characters(string)
|
236
|
-
string.to_s.tr("\";=", "':-" )
|
237
|
-
end
|
238
|
-
|
239
|
-
def format_value(v)
|
240
|
-
# flag numeric values with `#' prefix
|
241
|
-
if v.is_a? Numeric
|
242
|
-
value = "##{v}"
|
243
|
-
else
|
244
|
-
value = escape_special_characters(v)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
def html_safe_if_needed(string)
|
249
|
-
if string.respond_to?(:html_safe)
|
250
|
-
string.html_safe
|
251
|
-
else
|
252
|
-
string
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
|
5
|
-
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
6
|
-
require "new_relic/agent/beacon_configuration"
|
7
|
-
|
8
|
-
class NewRelic::Agent::BeaconConfigurationTest < Test::Unit::TestCase
|
9
|
-
def test_initialize_basic
|
10
|
-
with_config(:application_id => 'an application id',
|
11
|
-
:beacon => 'beacon', :'rum.enabled' => true) do
|
12
|
-
bc = NewRelic::Agent::BeaconConfiguration.new
|
13
|
-
assert_equal true, bc.enabled?
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_initialize_with_real_data
|
18
|
-
with_config(:browser_key => 'a key', :application_id => 'an application id',
|
19
|
-
:beacon => 'beacon', :'rum.enabled' => true) do
|
20
|
-
bc = NewRelic::Agent::BeaconConfiguration.new
|
21
|
-
assert bc.enabled?
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
ARRAY_OF_A = [97] * 40
|
26
|
-
|
27
|
-
def test_license_bytes
|
28
|
-
with_config(:license_key => 'a' * 40) do
|
29
|
-
bc = NewRelic::Agent::BeaconConfiguration.new
|
30
|
-
assert_equal(ARRAY_OF_A, bc.license_bytes)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_license_bytes_are_memoized
|
35
|
-
with_config(:license_key => 'a' * 40) do
|
36
|
-
bc = NewRelic::Agent::BeaconConfiguration.new
|
37
|
-
assert_equal(ARRAY_OF_A, bc.license_bytes)
|
38
|
-
|
39
|
-
NewRelic::Agent.config.apply_config(:license_key => 'b' * 40)
|
40
|
-
assert_equal(ARRAY_OF_A, bc.license_bytes)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
@@ -1,474 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
|
5
|
-
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
6
|
-
require "new_relic/agent/browser_monitoring"
|
7
|
-
require "new_relic/rack/browser_monitoring"
|
8
|
-
require 'base64'
|
9
|
-
|
10
|
-
class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
|
11
|
-
include NewRelic::Agent::BrowserMonitoring
|
12
|
-
|
13
|
-
def setup
|
14
|
-
@config = {
|
15
|
-
:beacon => 'beacon',
|
16
|
-
:browser_key => 'browserKey',
|
17
|
-
:application_id => '5, 6', # collector can return app multiple ids
|
18
|
-
:'rum.enabled' => true,
|
19
|
-
:license_key => "\0" # no-op obfuscation key
|
20
|
-
}
|
21
|
-
NewRelic::Agent.config.apply_config(@config)
|
22
|
-
NewRelic::Agent.instance.instance_eval do
|
23
|
-
@beacon_configuration = NewRelic::Agent::BeaconConfiguration.new
|
24
|
-
end
|
25
|
-
|
26
|
-
# By default we expect our transaction to have a start time
|
27
|
-
# All sorts of basics don't output without this setup initially
|
28
|
-
NewRelic::Agent::TransactionState.reset(nil)
|
29
|
-
current_transaction.start_time = Time.now
|
30
|
-
end
|
31
|
-
|
32
|
-
def teardown
|
33
|
-
NewRelic::Agent::TransactionState.clear
|
34
|
-
NewRelic::Agent.config.remove_config(@config)
|
35
|
-
mocha_teardown
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_js_errors_beta_default_gets_default_loader
|
39
|
-
assert_equal "rum", NewRelic::Agent.config[:'browser_monitoring.loader']
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_js_errors_beta_gets_full_loader
|
43
|
-
with_config(:js_errors_beta => true) do
|
44
|
-
assert_equal "full", NewRelic::Agent.config[:'browser_monitoring.loader']
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_js_errors_beta_off_gets_default_loader
|
49
|
-
with_config(:js_errors_beta => false) do
|
50
|
-
assert_equal "rum", NewRelic::Agent.config[:'browser_monitoring.loader']
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_auto_instrumentation_config_defaults_to_enabled
|
55
|
-
assert NewRelic::Agent.config[:'browser_monitoring.auto_instrument']
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_start_time_reset_each_request_when_auto_instrument_is_disabled
|
59
|
-
controller = Object.new
|
60
|
-
def controller.perform_action_without_newrelic_trace(method, options={});
|
61
|
-
# noop; instrument me
|
62
|
-
end
|
63
|
-
def controller.newrelic_metric_path; "foo"; end
|
64
|
-
controller.extend ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
65
|
-
controller.extend ::NewRelic::Agent::BrowserMonitoring
|
66
|
-
|
67
|
-
with_config(:'browser_monitoring.auto_instrument' => false) do
|
68
|
-
controller.perform_action_with_newrelic_trace(:index)
|
69
|
-
first_request_start_time = current_transaction.start_time
|
70
|
-
|
71
|
-
controller.perform_action_with_newrelic_trace(:index)
|
72
|
-
second_request_start_time = current_transaction.start_time
|
73
|
-
|
74
|
-
# assert that these aren't the same time object
|
75
|
-
# the start time should be reinitialized each request to the controller
|
76
|
-
assert !(first_request_start_time.equal? second_request_start_time)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_browser_timing_header_with_no_beacon_configuration
|
81
|
-
NewRelic::Agent.instance.stubs(:beacon_configuration).returns( nil)
|
82
|
-
assert_equal "", browser_timing_header
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_browser_timing_header_with_rum_enabled_false
|
86
|
-
with_config(:'rum.enabled' => false) do
|
87
|
-
NewRelic::Agent.instance.stubs(:beacon_configuration).returns(NewRelic::Agent::BeaconConfiguration.new)
|
88
|
-
assert_equal "", browser_timing_header
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def test_browser_timing_header_disable_all_tracing
|
93
|
-
NewRelic::Agent.disable_all_tracing do
|
94
|
-
assert_equal "", browser_timing_header
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_browser_timing_header_disable_transaction_tracing
|
99
|
-
NewRelic::Agent.disable_transaction_tracing do
|
100
|
-
assert_equal "", browser_timing_header
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def test_browser_timing_header_without_loader
|
105
|
-
with_config(:js_agent_loader => '') do
|
106
|
-
assert_equal "", browser_timing_header
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_browser_timing_header_without_rum_enabled
|
111
|
-
with_config(:js_agent_loader => 'loader', :'rum.enabled' => false) do
|
112
|
-
assert_equal "", browser_timing_header
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def test_browser_timing_header_with_loader
|
117
|
-
with_config(:js_agent_loader => 'loader') do
|
118
|
-
assert_has_js_agent_loader(browser_timing_header)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def assert_has_js_agent_loader(header)
|
123
|
-
assert_equal("\n<script type=\"text/javascript\">loader</script>",
|
124
|
-
header,
|
125
|
-
"expected new JS agent loader 'loader' but saw '#{header}'")
|
126
|
-
end
|
127
|
-
|
128
|
-
BEGINNING_OF_FOOTER = '<script type="text/javascript">window.NREUM||(NREUM={});NREUM.info='
|
129
|
-
END_OF_FOOTER = '}</script>'
|
130
|
-
|
131
|
-
def test_browser_timing_footer
|
132
|
-
with_config(:license_key => 'a' * 13) do
|
133
|
-
browser_timing_header
|
134
|
-
footer = browser_timing_footer
|
135
|
-
assert_has_text(BEGINNING_OF_FOOTER, footer)
|
136
|
-
assert_has_text(END_OF_FOOTER, footer)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def assert_has_text(snippet, footer)
|
141
|
-
assert(footer.include?(snippet), "Expected footer to include snippet: #{snippet}, but instead was #{footer}")
|
142
|
-
end
|
143
|
-
|
144
|
-
def test_browser_timing_footer_with_no_browser_key_rum_enabled
|
145
|
-
with_config(:browser_key => '') do
|
146
|
-
browser_timing_header
|
147
|
-
NewRelic::Agent.instance.stubs(:beacon_configuration).returns(NewRelic::Agent::BeaconConfiguration.new)
|
148
|
-
footer = browser_timing_footer
|
149
|
-
assert_equal "", footer
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def test_browser_timing_footer_with_no_browser_key_rum_disabled
|
154
|
-
with_config(:'rum.enabled' => false) do
|
155
|
-
browser_timing_header
|
156
|
-
NewRelic::Agent.instance.stubs(:beacon_configuration).returns(NewRelic::Agent::BeaconConfiguration.new)
|
157
|
-
footer = browser_timing_footer
|
158
|
-
assert_equal "", footer
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def test_browser_timing_footer_with_rum_enabled_not_specified
|
163
|
-
footer = browser_timing_footer
|
164
|
-
beginning_snippet = BEGINNING_OF_FOOTER
|
165
|
-
assert_has_text(BEGINNING_OF_FOOTER, footer)
|
166
|
-
assert_has_text(END_OF_FOOTER, footer)
|
167
|
-
end
|
168
|
-
|
169
|
-
def test_browser_timing_footer_with_no_beacon_configuration
|
170
|
-
browser_timing_header
|
171
|
-
NewRelic::Agent.instance.stubs(:beacon_configuration).returns( nil)
|
172
|
-
footer = browser_timing_footer
|
173
|
-
assert_equal "", footer
|
174
|
-
end
|
175
|
-
|
176
|
-
def test_browser_timing_footer_disable_all_tracing
|
177
|
-
browser_timing_header
|
178
|
-
footer = nil
|
179
|
-
NewRelic::Agent.disable_all_tracing do
|
180
|
-
footer = browser_timing_footer
|
181
|
-
end
|
182
|
-
assert_equal "", footer
|
183
|
-
end
|
184
|
-
|
185
|
-
def test_browser_timing_footer_disable_transaction_tracing
|
186
|
-
browser_timing_header
|
187
|
-
footer = nil
|
188
|
-
NewRelic::Agent.disable_transaction_tracing do
|
189
|
-
footer = browser_timing_footer
|
190
|
-
end
|
191
|
-
assert_equal "", footer
|
192
|
-
end
|
193
|
-
|
194
|
-
def test_browser_timing_footer_browser_key_missing
|
195
|
-
with_config(:browser_key => '') do
|
196
|
-
fake_config = mock('beacon configuration')
|
197
|
-
NewRelic::Agent.instance.stubs(:beacon_configuration).returns(fake_config)
|
198
|
-
fake_config.expects(:nil?).returns(false)
|
199
|
-
fake_config.expects(:enabled?).returns(true)
|
200
|
-
self.expects(:generate_footer_js).never
|
201
|
-
assert_equal('', browser_timing_footer, "should not return a footer when there is no key")
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def test_generate_footer_js_null_case
|
206
|
-
current_transaction.start_time = nil
|
207
|
-
assert_equal('', generate_footer_js(NewRelic::Agent.instance.beacon_configuration), "should not send javascript when there is no start time")
|
208
|
-
end
|
209
|
-
|
210
|
-
def test_generate_footer_js_with_start_time
|
211
|
-
with_config(:browser_key => 'a' * 40) do
|
212
|
-
fake_bc = mock('beacon configuration')
|
213
|
-
NewRelic::Agent.instance.stubs(:beacon_configuration).returns(fake_bc)
|
214
|
-
self.expects(:footer_js_string).with(NewRelic::Agent.instance.beacon_configuration).returns('footer js')
|
215
|
-
assert_equal('footer js', generate_footer_js(NewRelic::Agent.instance.beacon_configuration),
|
216
|
-
'should generate and return the footer JS when there is a start time')
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_browser_timing_footer_with_loader
|
221
|
-
with_config(:js_agent_loader => 'loader') do
|
222
|
-
footer = browser_timing_footer
|
223
|
-
beginning_snippet = "\n<script type=\"text/javascript\">window.NREUM||(NREUM={});NREUM.info={\""
|
224
|
-
ending_snippet = '}</script>'
|
225
|
-
assert(footer.include?(beginning_snippet),
|
226
|
-
"expected footer to include beginning snippet: '#{beginning_snippet}', but was '#{footer}'")
|
227
|
-
assert(footer.include?(ending_snippet),
|
228
|
-
"expected footer to include ending snippet: '#{ending_snippet}', but was '#{footer}'")
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def test_browser_monitoring_transaction_name_basic
|
233
|
-
txn = NewRelic::Agent::Transaction.new
|
234
|
-
txn.name = 'a transaction name'
|
235
|
-
NewRelic::Agent::TransactionState.get.transaction = txn
|
236
|
-
|
237
|
-
assert_equal('a transaction name', browser_monitoring_transaction_name, "should take the value from the thread local")
|
238
|
-
end
|
239
|
-
|
240
|
-
def test_browser_monitoring_transaction_name_empty
|
241
|
-
txn = NewRelic::Agent::Transaction.new
|
242
|
-
txn.name = ''
|
243
|
-
NewRelic::Agent::TransactionState.get.transaction = txn
|
244
|
-
|
245
|
-
assert_equal('', browser_monitoring_transaction_name, "should take the value even when it is empty")
|
246
|
-
end
|
247
|
-
|
248
|
-
def test_browser_monitoring_transaction_name_nil
|
249
|
-
assert_equal('(unknown)', browser_monitoring_transaction_name, "should fill in a default when it is nil")
|
250
|
-
end
|
251
|
-
|
252
|
-
def test_browser_monitoring_transaction_name_when_tt_disabled
|
253
|
-
with_config(:'transaction_tracer.enabled' => false) do
|
254
|
-
in_transaction('disabled_transactions') do
|
255
|
-
self.class.inspect
|
256
|
-
end
|
257
|
-
|
258
|
-
assert_match(/disabled_transactions/, browser_monitoring_transaction_name,
|
259
|
-
"should name transaction when transaction tracing disabled")
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
def test_extra_data
|
264
|
-
in_transaction do
|
265
|
-
with_config(ANALYTICS_TXN_IN_PAGE => true) do
|
266
|
-
NewRelic::Agent.add_custom_parameters({:boo => "hoo"})
|
267
|
-
assert_equal({:boo => "hoo"}, extra_data)
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
def test_extra_data_outside_transaction
|
273
|
-
NewRelic::Agent.add_custom_parameters({:boo => "hoo"})
|
274
|
-
assert extra_data.empty?
|
275
|
-
end
|
276
|
-
|
277
|
-
def test_format
|
278
|
-
assert_formatted({:a => "1", "b" => 2}, "a=1", "b=#2")
|
279
|
-
end
|
280
|
-
|
281
|
-
def test_format_extra_data_escaping
|
282
|
-
assert_formatted({"semi;colon" => "gets;escaped"}, "semi:colon=gets:escaped")
|
283
|
-
assert_formatted({"equal=key" => "equal=value"}, "equal-key=equal-value")
|
284
|
-
assert_formatted({'"quoted"' => '"marks"'}, %Q['quoted'='marks'])
|
285
|
-
end
|
286
|
-
|
287
|
-
def test_format_extra_data_disallowed_types
|
288
|
-
assert_formatted_empty({"nested" => { "hashes?" => "nope" }})
|
289
|
-
assert_formatted_empty({"lists" => ["are", "they", "allowed?", "nope"]})
|
290
|
-
end
|
291
|
-
|
292
|
-
def assert_formatted(data, *expected)
|
293
|
-
result = format_extra_data(data).split(";")
|
294
|
-
expected.each do |expect|
|
295
|
-
assert_includes(result, expect)
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
def assert_formatted_empty(data)
|
300
|
-
result = format_extra_data(data)
|
301
|
-
assert_equal("", result)
|
302
|
-
end
|
303
|
-
|
304
|
-
def test_footer_js_data
|
305
|
-
freeze_time
|
306
|
-
in_transaction do
|
307
|
-
with_config(ANALYTICS_TXN_IN_PAGE => true) do
|
308
|
-
NewRelic::Agent.set_user_attributes(:user => "user")
|
309
|
-
|
310
|
-
txn = NewRelic::Agent::Transaction.current
|
311
|
-
txn.stubs(:queue_time).returns(0)
|
312
|
-
txn.stubs(:start_time).returns(Time.now - 10)
|
313
|
-
txn.name = 'most recent transaction'
|
314
|
-
|
315
|
-
state = NewRelic::Agent::TransactionState.get
|
316
|
-
state.request_token = '0123456789ABCDEF'
|
317
|
-
state.request_guid = 'ABC'
|
318
|
-
|
319
|
-
data = js_data(NewRelic::Agent.instance.beacon_configuration)
|
320
|
-
expected = {
|
321
|
-
"beacon" => "beacon",
|
322
|
-
"errorBeacon" => nil,
|
323
|
-
"licenseKey" => "browserKey",
|
324
|
-
"applicationID" => "5, 6",
|
325
|
-
"transactionName" => pack("most recent transaction"),
|
326
|
-
"queueTime" => 0,
|
327
|
-
"applicationTime" => 10000,
|
328
|
-
"ttGuid" => "ABC",
|
329
|
-
"agentToken" => "0123456789ABCDEF",
|
330
|
-
"agent" => nil,
|
331
|
-
"extra" => pack("user=user")
|
332
|
-
}
|
333
|
-
|
334
|
-
assert_equal(expected, data)
|
335
|
-
|
336
|
-
js = footer_js_string(NewRelic::Agent.instance.beacon_configuration)
|
337
|
-
expected.each do |key, value|
|
338
|
-
assert_match(/"#{key.to_s}":#{formatted_for_matching(value)}/, js)
|
339
|
-
end
|
340
|
-
end
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
ANALYTICS_ENABLED = :'analytics_events.enabled'
|
345
|
-
ANALYTICS_TXN_ENABLED = :'analytics_events.transactions.enabled'
|
346
|
-
ANALYTICS_TXN_IN_PAGE = :'capture_attributes.page_view_events'
|
347
|
-
|
348
|
-
def test_js_data_doesnt_pick_up_extras_by_default
|
349
|
-
in_transaction do
|
350
|
-
NewRelic::Agent.add_custom_parameters({:boo => "hoo"})
|
351
|
-
assert_extra_data_is("")
|
352
|
-
end
|
353
|
-
end
|
354
|
-
|
355
|
-
def test_js_data_picks_up_extras_when_configured
|
356
|
-
in_transaction do
|
357
|
-
with_config(ANALYTICS_ENABLED => true,
|
358
|
-
ANALYTICS_TXN_ENABLED => true,
|
359
|
-
ANALYTICS_TXN_IN_PAGE => true) do
|
360
|
-
NewRelic::Agent.add_custom_parameters({:boo => "hoo"})
|
361
|
-
assert_extra_data_is("boo=hoo")
|
362
|
-
end
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
def test_js_data_ignores_extras_if_no_analytics
|
367
|
-
in_transaction do
|
368
|
-
with_config(ANALYTICS_ENABLED => false,
|
369
|
-
ANALYTICS_TXN_ENABLED => true,
|
370
|
-
ANALYTICS_TXN_IN_PAGE => true) do
|
371
|
-
NewRelic::Agent.add_custom_parameters({:boo => "hoo"})
|
372
|
-
assert_extra_data_is("")
|
373
|
-
end
|
374
|
-
end
|
375
|
-
end
|
376
|
-
|
377
|
-
def test_js_data_ignores_extras_if_no_transaction_analytics
|
378
|
-
in_transaction do
|
379
|
-
with_config(ANALYTICS_ENABLED => true,
|
380
|
-
ANALYTICS_TXN_ENABLED => false,
|
381
|
-
ANALYTICS_TXN_IN_PAGE => true) do
|
382
|
-
NewRelic::Agent.add_custom_parameters({:boo => "hoo"})
|
383
|
-
assert_extra_data_is("")
|
384
|
-
end
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
def test_js_data_ignores_extras_if_not_allowed_in_page
|
389
|
-
in_transaction do
|
390
|
-
with_config(ANALYTICS_ENABLED => true,
|
391
|
-
ANALYTICS_TXN_ENABLED => true,
|
392
|
-
ANALYTICS_TXN_IN_PAGE => false) do
|
393
|
-
NewRelic::Agent.add_custom_parameters({:boo => "hoo"})
|
394
|
-
assert_extra_data_is("")
|
395
|
-
end
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
def assert_extra_data_is(expected)
|
400
|
-
data = js_data(NewRelic::Agent.instance.beacon_configuration)
|
401
|
-
assert_equal pack(expected), data["extra"]
|
402
|
-
end
|
403
|
-
|
404
|
-
def pack(text)
|
405
|
-
[text].pack("m0").gsub("\n", "")
|
406
|
-
end
|
407
|
-
|
408
|
-
def formatted_for_matching(value)
|
409
|
-
case value
|
410
|
-
when String
|
411
|
-
%Q["#{value}"]
|
412
|
-
when NilClass
|
413
|
-
"null"
|
414
|
-
else
|
415
|
-
value
|
416
|
-
end
|
417
|
-
end
|
418
|
-
|
419
|
-
def test_html_safe_if_needed_unsafed
|
420
|
-
string = mock('string')
|
421
|
-
# here to handle 1.9 encoding - we stub this out because it should
|
422
|
-
# be handled automatically and is outside the scope of this test
|
423
|
-
string.stubs(:respond_to?).with(:encoding).returns(false)
|
424
|
-
string.expects(:respond_to?).with(:html_safe).returns(false)
|
425
|
-
assert_equal(string, html_safe_if_needed(string))
|
426
|
-
end
|
427
|
-
|
428
|
-
def test_html_safe_if_needed_safed
|
429
|
-
string = mock('string')
|
430
|
-
string.expects(:respond_to?).with(:html_safe).returns(true)
|
431
|
-
string.expects(:html_safe).returns(string)
|
432
|
-
# here to handle 1.9 encoding - we stub this out because it should
|
433
|
-
# be handled automatically and is outside the scope of this test
|
434
|
-
string.stubs(:respond_to?).with(:encoding).returns(false)
|
435
|
-
assert_equal(string, html_safe_if_needed(string))
|
436
|
-
end
|
437
|
-
|
438
|
-
def test_obfuscate_basic
|
439
|
-
text = 'a happy piece of small text'
|
440
|
-
key = (1..40).to_a
|
441
|
-
NewRelic::Agent.instance.beacon_configuration.expects(:license_bytes).returns(key)
|
442
|
-
output = obfuscate(NewRelic::Agent.instance.beacon_configuration, text)
|
443
|
-
assert_equal('YCJrZXV2fih5Y25vaCFtZSR2a2ZkZSp/aXV1', output, "should output obfuscated text")
|
444
|
-
end
|
445
|
-
|
446
|
-
def test_obfuscate_long_string
|
447
|
-
text = 'a happy piece of small text' * 5
|
448
|
-
key = (1..40).to_a
|
449
|
-
NewRelic::Agent.instance.beacon_configuration.expects(:license_bytes).returns(key)
|
450
|
-
output = obfuscate(NewRelic::Agent.instance.beacon_configuration, text)
|
451
|
-
assert_equal('YCJrZXV2fih5Y25vaCFtZSR2a2ZkZSp/aXV1YyNsZHZ3cSl6YmluZCJsYiV1amllZit4aHl2YiRtZ3d4cCp7ZWhiZyNrYyZ0ZWhmZyx5ZHp3ZSVuZnh5cyt8ZGRhZiRqYCd7ZGtnYC11Z3twZCZvaXl6cix9aGdgYSVpYSh6Z2pgYSF2Znxx', output, "should output obfuscated text")
|
452
|
-
end
|
453
|
-
|
454
|
-
def test_obfuscate_utf8
|
455
|
-
text = "foooooééoooo - blah"
|
456
|
-
key = (1..40).to_a
|
457
|
-
NewRelic::Agent.instance.beacon_configuration.expects(:license_bytes).returns(key).at_least_once
|
458
|
-
output = obfuscate(NewRelic::Agent.instance.beacon_configuration, text)
|
459
|
-
assert_equal('Z21sa2ppxKHKo2RjYm4iLiRnamZg', output, "should output obfuscated text")
|
460
|
-
|
461
|
-
unoutput = obfuscate(NewRelic::Agent.instance.beacon_configuration, Base64.decode64(output))
|
462
|
-
assert_equal Base64.encode64(text).gsub("\n", ''), unoutput
|
463
|
-
end
|
464
|
-
|
465
|
-
def test_freezes_transaction_name_when_footer_is_written
|
466
|
-
with_config(:license_key => 'a' * 13) do
|
467
|
-
in_transaction do
|
468
|
-
assert !NewRelic::Agent::Transaction.current.name_frozen?
|
469
|
-
browser_timing_footer
|
470
|
-
assert NewRelic::Agent::Transaction.current.name_frozen?
|
471
|
-
end
|
472
|
-
end
|
473
|
-
end
|
474
|
-
end
|