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.
Files changed (97) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +27 -4
  3. data/bin/nrdebug +10 -4
  4. data/lib/new_relic/agent.rb +33 -11
  5. data/lib/new_relic/agent/agent.rb +83 -120
  6. data/lib/new_relic/agent/agent_logger.rb +28 -16
  7. data/lib/new_relic/agent/audit_logger.rb +3 -4
  8. data/lib/new_relic/agent/autostart.rb +20 -8
  9. data/lib/new_relic/agent/commands/agent_command_router.rb +26 -17
  10. data/lib/new_relic/agent/commands/thread_profiler_session.rb +2 -2
  11. data/lib/new_relic/agent/configuration/default_source.rb +146 -59
  12. data/lib/new_relic/agent/configuration/manager.rb +3 -3
  13. data/lib/new_relic/agent/cross_app_monitor.rb +15 -40
  14. data/lib/new_relic/agent/cross_app_tracing.rb +20 -12
  15. data/lib/new_relic/agent/database.rb +24 -0
  16. data/lib/new_relic/agent/error_collector.rb +6 -2
  17. data/lib/new_relic/agent/instrumentation/merb/controller.rb +3 -1
  18. data/lib/new_relic/agent/javascript_instrumentor.rb +187 -0
  19. data/lib/new_relic/agent/new_relic_service.rb +30 -22
  20. data/lib/new_relic/agent/obfuscator.rb +48 -0
  21. data/lib/new_relic/agent/request_sampler.rb +5 -13
  22. data/lib/new_relic/agent/shim_agent.rb +1 -0
  23. data/lib/new_relic/agent/sql_sampler.rb +15 -5
  24. data/lib/new_relic/agent/stats_engine/metric_stats.rb +9 -4
  25. data/lib/new_relic/agent/transaction.rb +0 -1
  26. data/lib/new_relic/agent/transaction_sampler.rb +28 -16
  27. data/lib/new_relic/agent/transaction_state.rb +9 -0
  28. data/lib/new_relic/agent/transaction_timings.rb +5 -1
  29. data/lib/new_relic/agent/worker_loop.rb +0 -10
  30. data/lib/new_relic/cli/deployments.rb +1 -1
  31. data/lib/new_relic/control/instance_methods.rb +1 -1
  32. data/lib/new_relic/helper.rb +3 -1
  33. data/lib/new_relic/rack/browser_monitoring.rb +1 -2
  34. data/lib/new_relic/transaction_sample.rb +11 -13
  35. data/lib/newrelic_rpm.rb +1 -0
  36. data/test/agent_helper.rb +20 -5
  37. data/test/environments/lib/environments/runner.rb +1 -0
  38. data/test/helpers/file_searching.rb +28 -0
  39. data/test/multiverse/lib/multiverse/suite.rb +36 -19
  40. data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +49 -0
  41. data/test/multiverse/suites/agent_only/http_response_code_test.rb +2 -2
  42. data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +4 -2
  43. data/test/multiverse/suites/agent_only/service_timeout_test.rb +1 -1
  44. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +7 -4
  45. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +2 -1
  46. data/test/multiverse/suites/rails/error_tracing_test.rb +34 -4
  47. data/test/multiverse/suites/rails/ignore_test.rb +1 -1
  48. data/test/multiverse/suites/rails/request_statistics_test.rb +1 -3
  49. data/test/multiverse/suites/sequel/sequel_instrumentation_test.rb +10 -7
  50. data/test/multiverse/suites/sinatra/ignoring_test.rb +1 -1
  51. data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -1
  52. data/test/new_relic/agent/agent_logger_test.rb +108 -114
  53. data/test/new_relic/agent/agent_test.rb +139 -21
  54. data/test/new_relic/agent/audit_logger_test.rb +22 -20
  55. data/test/new_relic/agent/autostart_test.rb +3 -2
  56. data/test/new_relic/agent/commands/agent_command_router_test.rb +51 -32
  57. data/test/new_relic/agent/configuration/default_source_test.rb +8 -2
  58. data/test/new_relic/agent/configuration/manager_test.rb +5 -1
  59. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +57 -0
  60. data/test/new_relic/agent/cross_app_monitor_test.rb +10 -26
  61. data/test/new_relic/agent/database_test.rb +32 -0
  62. data/test/new_relic/agent/error_collector_test.rb +33 -16
  63. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +88 -71
  64. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
  65. data/test/new_relic/agent/javascript_instrumentor_test.rb +341 -0
  66. data/test/new_relic/agent/memcache_instrumentation_test.rb +91 -89
  67. data/test/new_relic/agent/method_tracer_test.rb +1 -1
  68. data/test/new_relic/agent/obfuscator_test.rb +77 -0
  69. data/test/new_relic/agent/pipe_channel_manager_test.rb +5 -5
  70. data/test/new_relic/agent/pipe_service_test.rb +1 -1
  71. data/test/new_relic/agent/request_sampler_test.rb +21 -11
  72. data/test/new_relic/agent/sql_sampler_test.rb +52 -8
  73. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +6 -6
  74. data/test/new_relic/agent/stats_engine_test.rb +18 -2
  75. data/test/new_relic/agent/transaction_sampler_test.rb +98 -53
  76. data/test/new_relic/agent/transaction_state_test.rb +44 -0
  77. data/test/new_relic/agent/transaction_test.rb +1 -1
  78. data/test/new_relic/agent/transaction_timings_test.rb +15 -5
  79. data/test/new_relic/agent/worker_loop_test.rb +0 -9
  80. data/test/new_relic/agent_test.rb +9 -21
  81. data/test/new_relic/data_container_tests.rb +72 -0
  82. data/test/new_relic/fake_collector.rb +69 -20
  83. data/test/new_relic/http_client_test_cases.rb +17 -2
  84. data/test/new_relic/license_test.rb +6 -15
  85. data/test/new_relic/multiverse_helpers.rb +2 -3
  86. data/test/new_relic/rack/browser_monitoring_test.rb +15 -37
  87. data/test/new_relic/transaction_sample_test.rb +92 -62
  88. data/test/performance/suites/rum_autoinsertion.rb +0 -3
  89. data/test/rum/x_ua_meta_tag_spaces_around_equals.result.html +10 -0
  90. data/test/rum/x_ua_meta_tag_spaces_around_equals.source.html +10 -0
  91. data/test/test_helper.rb +9 -5
  92. metadata +29 -11
  93. metadata.gz.sig +0 -0
  94. data/lib/new_relic/agent/beacon_configuration.rb +0 -37
  95. data/lib/new_relic/agent/browser_monitoring.rb +0 -257
  96. data/test/new_relic/agent/beacon_configuration_test.rb +0 -44
  97. 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