newrelic_rpm 3.9.0.229 → 3.9.1.236
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +4 -1
- data/CHANGELOG +73 -0
- data/install.rb +2 -2
- data/lib/new_relic/agent/agent.rb +8 -1
- data/lib/new_relic/agent/browser_token.rb +10 -7
- data/lib/new_relic/agent/configuration/default_source.rb +8 -1
- data/lib/new_relic/agent/configuration/high_security_source.rb +56 -0
- data/lib/new_relic/agent/configuration/manager.rb +35 -28
- data/lib/new_relic/agent/cross_app_monitor.rb +23 -0
- data/lib/new_relic/agent/cross_app_tracing.rb +34 -26
- data/lib/new_relic/agent/database.rb +7 -6
- data/lib/new_relic/agent/instrumentation/active_record.rb +18 -18
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/curb.rb +18 -15
- data/lib/new_relic/agent/instrumentation/excon/connection.rb +1 -1
- data/lib/new_relic/agent/instrumentation/excon/middleware.rb +7 -4
- data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -1
- data/lib/new_relic/agent/instrumentation/memcache.rb +9 -2
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +1 -1
- data/lib/new_relic/agent/instrumentation/net.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rails3/errors.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rails4/errors.rb +1 -1
- data/lib/new_relic/agent/instrumentation/typhoeus.rb +6 -4
- data/lib/new_relic/agent/javascript_instrumentor.rb +9 -1
- data/lib/new_relic/agent/new_relic_service.rb +7 -0
- data/lib/new_relic/agent/obfuscator.rb +3 -2
- data/lib/new_relic/agent/request_sampler.rb +17 -1
- data/lib/new_relic/agent/sql_sampler.rb +10 -6
- data/lib/new_relic/agent/traced_method_stack.rb +0 -12
- data/lib/new_relic/agent/transaction.rb +98 -10
- data/lib/new_relic/agent/transaction_sampler.rb +10 -3
- data/lib/new_relic/agent/transaction_state.rb +2 -12
- data/lib/new_relic/control/frameworks/sinatra.rb +0 -3
- data/lib/new_relic/control/instance_methods.rb +5 -0
- data/lib/new_relic/json_wrapper.rb +7 -1
- data/lib/new_relic/rack/browser_monitoring.rb +25 -4
- data/lib/new_relic/version.rb +1 -1
- data/newrelic_rpm.gemspec +0 -1
- data/test/agent_helper.rb +76 -0
- data/test/fixtures/cross_agent_tests/cat_map.json +299 -0
- data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +16 -0
- data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +30 -0
- data/test/multiverse/suites/agent_only/marshaling_test.rb +17 -17
- data/test/multiverse/suites/agent_only/testing_app.rb +10 -1
- data/test/multiverse/suites/deferred_instrumentation/config/newrelic.yml +0 -1
- data/test/multiverse/suites/high_security/Envfile +3 -0
- data/test/multiverse/suites/high_security/config/newrelic.yml +27 -0
- data/test/multiverse/suites/high_security/high_security_test.rb +64 -0
- data/test/multiverse/suites/rails/action_controller_live_rum_test.rb +39 -0
- data/test/multiverse/suites/rails/bad_instrumentation_test.rb +3 -1
- data/test/multiverse/suites/rails/parameter_capture_test.rb +0 -20
- data/test/new_relic/agent/agent/connect_test.rb +5 -10
- data/test/new_relic/agent/agent_test.rb +11 -0
- data/test/new_relic/agent/browser_token_test.rb +10 -6
- data/test/new_relic/agent/configuration/default_source_test.rb +6 -0
- data/test/new_relic/agent/configuration/high_security_source_test.rb +83 -0
- data/test/new_relic/agent/configuration/manager_test.rb +7 -2
- data/test/new_relic/agent/cross_app_monitor_test.rb +17 -1
- data/test/new_relic/agent/cross_app_tracing_test.rb +11 -10
- data/test/new_relic/agent/hostname_test.rb +1 -1
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +22 -0
- data/test/new_relic/agent/instrumentation/middleware_tracing_test.rb +37 -0
- data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +4 -2
- data/test/new_relic/agent/javascript_instrumentor_test.rb +42 -0
- data/test/new_relic/agent/memcache_instrumentation_test.rb +11 -5
- data/test/new_relic/agent/request_sampler_test.rb +9 -0
- data/test/new_relic/agent/sql_sampler_test.rb +46 -0
- data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +1 -0
- data/test/new_relic/agent/transaction_sampler_test.rb +64 -4
- data/test/new_relic/agent/transaction_state_test.rb +0 -75
- data/test/new_relic/agent/transaction_test.rb +142 -0
- data/test/new_relic/control/instance_methods_test.rb +24 -4
- data/test/new_relic/fake_collector.rb +6 -13
- data/test/new_relic/fake_external_server.rb +14 -1
- data/test/new_relic/http_client_test_cases.rb +69 -21
- data/test/new_relic/json_wrapper_test.rb +10 -5
- data/test/performance/suites/rack_middleware.rb +2 -1
- data/test/performance/suites/rum_autoinsertion.rb +17 -3
- data/test/script/path_hash.rb +49 -0
- data/test/test_helper.rb +0 -10
- metadata +12 -52
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
@@ -1 +1,4 @@
|
|
1
|
-
|
1
|
+
��eD�nqPWZ���\.��"���x"=�$S��z��3�R*����`�$�3��}�+�;�
|
2
|
+
������y,������pO�?t�yVoZӚm�7�U��u�8�Xϑ��"(��2wR��� ����*�yG~�R����4�ݬ�w�q
|
3
|
+
��`>T�q�#p�bie'?t�.q���[R�2��P�2y���LڟO�Ig �!��C��
|
4
|
+
��O�"��ba�
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,78 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes #
|
2
2
|
|
3
|
+
## v3.9.1 ##
|
4
|
+
|
5
|
+
* Ruby 1.8.7 users: upgrade or add JSON gem now
|
6
|
+
|
7
|
+
Ruby 1.8.7 is end-of-lifed, and not receiving security updates, so we strongly
|
8
|
+
encourage all users with apps on 1.8.7 to upgrade.
|
9
|
+
|
10
|
+
If you're not able to upgrade yet, be aware that a coming release of the Ruby
|
11
|
+
agent will require users of Ruby 1.8.7 to have the 'json' gem available within
|
12
|
+
their applications in order to continue sending data to New Relic.
|
13
|
+
|
14
|
+
For more details, see:
|
15
|
+
https://docs.newrelic.com/docs/ruby/ruby-1.8.7-support
|
16
|
+
|
17
|
+
* High security mode V2
|
18
|
+
|
19
|
+
The Ruby agent now supports V2 of New Relic's high security mode. To enable
|
20
|
+
it, you must add 'high_security: true' to your newrelic.yml file, *and* enable
|
21
|
+
high security mode through the New Relic web interface. The local agent
|
22
|
+
setting must be in agreement with the server-side setting, or the agent will
|
23
|
+
shut down and no data will be collected.
|
24
|
+
|
25
|
+
Customers who already had the server-side high security mode setting enabled
|
26
|
+
must add 'high_security: true' to their agent configuration files when
|
27
|
+
upgrading to this release.
|
28
|
+
|
29
|
+
For details on high security mode, see:
|
30
|
+
http://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
|
31
|
+
|
32
|
+
* Improved memcached instrumentation
|
33
|
+
|
34
|
+
More accurate instrumentation for the 'cas' command when using version 1.8.0
|
35
|
+
or later of the memcached gem. Previous versions of the agent would count all
|
36
|
+
time spent in the block given to 'cas' as memcache time, but 1.8.0 and later
|
37
|
+
allows us to more accurately measure just the time spent talking to memcache.
|
38
|
+
|
39
|
+
Many thanks to Francis Bogsanyi for contributing this change!
|
40
|
+
|
41
|
+
* Improved support for Rails apps launched from outside the app root directory
|
42
|
+
|
43
|
+
The Ruby agent attempts to resolve the location of its configuration file at
|
44
|
+
runtime relative to the directory that the host process is started from.
|
45
|
+
|
46
|
+
In cases where the host process was started from outside of the application's
|
47
|
+
root directory (for example, if the process is started from from '/'), it will
|
48
|
+
now also attempt to locate its configuration file based on the value of
|
49
|
+
Rails.root for Rails applications.
|
50
|
+
|
51
|
+
* Better compatibility with ActionController::Live
|
52
|
+
|
53
|
+
Browser Application Monitoring auto-injection can cause request failures under
|
54
|
+
certain circumstances when used with ActionController::Live, so the agent will
|
55
|
+
now automatically detect usage of ActionController::Live, and not attempt
|
56
|
+
auto-injection for those requests (even if auto-instrumentation is otherwise
|
57
|
+
enabled).
|
58
|
+
|
59
|
+
Many thanks to Rodrigo Rosenfeld Rosas for help diagnosing this issue!
|
60
|
+
|
61
|
+
* Fix for occasional spikes in external services time
|
62
|
+
|
63
|
+
Certain kinds of failures during HTTP reqeusts made by an application could
|
64
|
+
have previously resulted in the Ruby agent reporting erroneously large amounts
|
65
|
+
of time spent in outgoing HTTP requests. This issue manifested most obviously
|
66
|
+
in spikes on the 'Web external' band on the main overview graph. This issue
|
67
|
+
has now been fixed.
|
68
|
+
|
69
|
+
* Fix 'rake newrelic:install' for Rails 4 applications
|
70
|
+
|
71
|
+
The newrelic:install rake task was previously not working for Rails 4
|
72
|
+
applications and has been fixed.
|
73
|
+
|
74
|
+
Thanks to Murahashi Sanemat Kenichi for contributing this fix!
|
75
|
+
|
3
76
|
## v3.9.0 ##
|
4
77
|
|
5
78
|
* Rack middleware instrumentation
|
data/install.rb
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
# This file is distributed under New Relic's license terms.
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
4
|
|
5
|
-
if __FILE__ == $0 || $0 =~ /script\/plugin/
|
5
|
+
if __FILE__ == $0 || $0 =~ /script\/plugin/ || File.basename($0) == 'rake'
|
6
6
|
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
|
7
7
|
require 'new_relic/cli/command'
|
8
8
|
begin
|
9
9
|
NewRelic::Cli::Install.new(:quiet => true, :app_name => 'My Application').run
|
10
|
-
rescue NewRelic::Cli::CommandFailure => e
|
10
|
+
rescue NewRelic::Cli::Command::CommandFailure => e
|
11
11
|
$stderr.puts e.message
|
12
12
|
end
|
13
13
|
end
|
@@ -155,7 +155,7 @@ module NewRelic
|
|
155
155
|
disconnected? ||
|
156
156
|
@worker_thread && @worker_thread.alive?
|
157
157
|
|
158
|
-
::NewRelic::Agent.logger.debug "Starting the worker thread in #{
|
158
|
+
::NewRelic::Agent.logger.debug "Starting the worker thread in #{Process.pid} (parent #{Process.ppid}) after forking."
|
159
159
|
|
160
160
|
# Clear out locks and stats left over from parent process
|
161
161
|
reset_objects_with_locks
|
@@ -759,6 +759,7 @@ module NewRelic
|
|
759
759
|
:agent_version => NewRelic::VERSION::STRING,
|
760
760
|
:environment => @environment_report,
|
761
761
|
:settings => Agent.config.to_collector_hash,
|
762
|
+
:high_security => Agent.config[:high_security],
|
762
763
|
}
|
763
764
|
end
|
764
765
|
|
@@ -874,6 +875,8 @@ module NewRelic
|
|
874
875
|
query_server_for_configuration
|
875
876
|
@connected_pid = $$
|
876
877
|
@connect_state = :connected
|
878
|
+
rescue NewRelic::Agent::ForceDisconnectException => e
|
879
|
+
handle_force_disconnect(e)
|
877
880
|
rescue NewRelic::Agent::LicenseException => e
|
878
881
|
handle_license_error(e)
|
879
882
|
rescue NewRelic::Agent::UnrecoverableAgentException => e
|
@@ -888,6 +891,10 @@ module NewRelic
|
|
888
891
|
else
|
889
892
|
disconnect
|
890
893
|
end
|
894
|
+
rescue Exception => e
|
895
|
+
::NewRelic::Agent.logger.error "Exception of unexpected type during Agent#connect():", e
|
896
|
+
|
897
|
+
raise
|
891
898
|
end
|
892
899
|
|
893
900
|
# Who am I? Well, this method can tell you your hostname.
|
@@ -16,7 +16,9 @@ module NewRelic
|
|
16
16
|
s = agent_flag.split("=")
|
17
17
|
if s.length == 2
|
18
18
|
if s[0] == "tk" && s[1]
|
19
|
-
|
19
|
+
sanitized = sanitize_token(s[1])
|
20
|
+
return nil unless sanitized
|
21
|
+
ERB::Util.h(sanitized)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
else
|
@@ -24,14 +26,15 @@ module NewRelic
|
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
27
|
-
#
|
28
|
-
# and set the token to an empty string if any of them are found in the token so that
|
29
|
-
# potential XSS attacks via the token are avoided
|
29
|
+
# Remove any non-alphanumeric characters from the token to avoid XSS attacks.
|
30
30
|
def self.sanitize_token(token)
|
31
|
-
if (
|
32
|
-
|
31
|
+
if token.match(/[^a-zA-Z0-9]/)
|
32
|
+
::NewRelic::Agent.logger.log_once(:warn, :invalid_browser_token,
|
33
|
+
"Invalid characters found in browser token.")
|
34
|
+
nil
|
35
|
+
else
|
36
|
+
token
|
33
37
|
end
|
34
|
-
token
|
35
38
|
end
|
36
39
|
end
|
37
40
|
end
|
@@ -33,10 +33,17 @@ module NewRelic
|
|
33
33
|
File.join("config","newrelic.yml"),
|
34
34
|
File.join("newrelic.yml")
|
35
35
|
]
|
36
|
+
|
37
|
+
if NewRelic::Control.instance.root
|
38
|
+
paths << File.join(NewRelic::Control.instance.root, "config", "newrelic.yml")
|
39
|
+
paths << File.join(NewRelic::Control.instance.root, "newrelic.yml")
|
40
|
+
end
|
41
|
+
|
36
42
|
if ENV["HOME"]
|
37
43
|
paths << File.join(ENV["HOME"], ".newrelic", "newrelic.yml")
|
38
44
|
paths << File.join(ENV["HOME"], "newrelic.yml")
|
39
45
|
end
|
46
|
+
|
40
47
|
paths
|
41
48
|
}
|
42
49
|
end
|
@@ -892,7 +899,7 @@ module NewRelic
|
|
892
899
|
},
|
893
900
|
:'analytics_events.max_samples_stored' => {
|
894
901
|
:default => 1200,
|
895
|
-
:public =>
|
902
|
+
:public => true,
|
896
903
|
:type => Fixnum,
|
897
904
|
:description => 'Maximum number of request events recorded by the analytics event sampling in a single harvest.'
|
898
905
|
},
|
@@ -0,0 +1,56 @@
|
|
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 'new_relic/agent/configuration'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Configuration
|
10
|
+
class HighSecuritySource < DottedHash
|
11
|
+
def initialize(local_settings)
|
12
|
+
super({
|
13
|
+
:ssl => true,
|
14
|
+
|
15
|
+
:capture_params => false,
|
16
|
+
:'resque.capture_params' => false,
|
17
|
+
:'sidekiq.capture_params' => false,
|
18
|
+
|
19
|
+
# These aren't strictly necessary as add_custom_parameters is
|
20
|
+
# directly responsible for ignoring incoming param, but we disallow
|
21
|
+
# attributes by these settings just to be safe
|
22
|
+
:'transaction_tracer.capture_attributes' => false,
|
23
|
+
:'error_collector.capture_attributes' => false,
|
24
|
+
:'browser_monitoring.capture_attributes' => false,
|
25
|
+
:'analytics_events.capture_attributes' => false,
|
26
|
+
|
27
|
+
:'transaction_tracer.record_sql' => record_sql_setting(local_settings, :'transaction_tracer.record_sql'),
|
28
|
+
:'slow_sql.record_sql' => record_sql_setting(local_settings, :'slow_sql.record_sql'),
|
29
|
+
:'mongo.obfuscate_queries' => true
|
30
|
+
})
|
31
|
+
end
|
32
|
+
|
33
|
+
OFF = "off".freeze
|
34
|
+
RAW = "raw".freeze
|
35
|
+
OBFUSCATED = "obfuscated".freeze
|
36
|
+
|
37
|
+
SET_TO_OBFUSCATED = [RAW, OBFUSCATED]
|
38
|
+
|
39
|
+
def record_sql_setting(local_settings, key)
|
40
|
+
original_value = local_settings[key]
|
41
|
+
result = if SET_TO_OBFUSCATED.include?(original_value)
|
42
|
+
OBFUSCATED
|
43
|
+
else
|
44
|
+
OFF
|
45
|
+
end
|
46
|
+
|
47
|
+
if result != original_value
|
48
|
+
NewRelic::Agent.logger.info("Disabling setting #{key}='#{original_value}' because high security mode is enabled. Value will be '#{result}'")
|
49
|
+
end
|
50
|
+
|
51
|
+
result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -8,6 +8,7 @@ require 'new_relic/agent/configuration/yaml_source'
|
|
8
8
|
require 'new_relic/agent/configuration/default_source'
|
9
9
|
require 'new_relic/agent/configuration/server_source'
|
10
10
|
require 'new_relic/agent/configuration/environment_source'
|
11
|
+
require 'new_relic/agent/configuration/high_security_source'
|
11
12
|
|
12
13
|
module NewRelic
|
13
14
|
module Agent
|
@@ -52,11 +53,12 @@ module NewRelic
|
|
52
53
|
|
53
54
|
def remove_config_type(sym)
|
54
55
|
source = case sym
|
55
|
-
when :
|
56
|
-
when :
|
57
|
-
when :
|
58
|
-
when :
|
59
|
-
when :
|
56
|
+
when :high_security then @high_security_source
|
57
|
+
when :environment then @environment_source
|
58
|
+
when :server then @server_source
|
59
|
+
when :manual then @manual_source
|
60
|
+
when :yaml then @yaml_source
|
61
|
+
when :default then @default_source
|
60
62
|
end
|
61
63
|
|
62
64
|
remove_config(source)
|
@@ -64,11 +66,12 @@ module NewRelic
|
|
64
66
|
|
65
67
|
def remove_config(source)
|
66
68
|
case source
|
67
|
-
when
|
68
|
-
when
|
69
|
-
when
|
70
|
-
when
|
71
|
-
when
|
69
|
+
when HighSecuritySource then @high_security_source = nil
|
70
|
+
when EnvironmentSource then @environment_source = nil
|
71
|
+
when ServerSource then @server_source = nil
|
72
|
+
when ManualSource then @manual_source = nil
|
73
|
+
when YamlSource then @yaml_source = nil
|
74
|
+
when DefaultSource then @default_source = nil
|
72
75
|
else
|
73
76
|
@configs_for_testing.delete_if {|src,lvl| src == source}
|
74
77
|
end
|
@@ -84,11 +87,12 @@ module NewRelic
|
|
84
87
|
|
85
88
|
invoke_callbacks(:add, source)
|
86
89
|
case source
|
87
|
-
when
|
88
|
-
when
|
89
|
-
when
|
90
|
-
when
|
91
|
-
when
|
90
|
+
when HighSecuritySource then @high_security_source = source
|
91
|
+
when EnvironmentSource then @environment_source = source
|
92
|
+
when ServerSource then @server_source = source
|
93
|
+
when ManualSource then @manual_source = source
|
94
|
+
when YamlSource then @yaml_source = source
|
95
|
+
when DefaultSource then @default_source = source
|
92
96
|
else
|
93
97
|
NewRelic::Agent.logger.warn("Invalid config format; config will be ignored: #{source}")
|
94
98
|
end
|
@@ -187,13 +191,14 @@ module NewRelic
|
|
187
191
|
|
188
192
|
# Generally only useful during initial construction and tests
|
189
193
|
def reset_to_defaults
|
190
|
-
@
|
191
|
-
@
|
192
|
-
@
|
193
|
-
@
|
194
|
-
@
|
194
|
+
@high_security_source = nil
|
195
|
+
@environment_source = EnvironmentSource.new
|
196
|
+
@server_source = nil
|
197
|
+
@manual_source = nil
|
198
|
+
@yaml_source = nil
|
199
|
+
@default_source = DefaultSource.new
|
195
200
|
|
196
|
-
@configs_for_testing
|
201
|
+
@configs_for_testing = []
|
197
202
|
|
198
203
|
reset_cache
|
199
204
|
end
|
@@ -213,12 +218,13 @@ module NewRelic
|
|
213
218
|
end
|
214
219
|
|
215
220
|
def delete_all_configs_for_testing
|
216
|
-
@
|
217
|
-
@
|
218
|
-
@
|
219
|
-
@
|
220
|
-
@
|
221
|
-
@
|
221
|
+
@high_security_source = nil
|
222
|
+
@environment_source = nil
|
223
|
+
@server_source = nil
|
224
|
+
@manual_source = nil
|
225
|
+
@yaml_source = nil
|
226
|
+
@default_source = nil
|
227
|
+
@configs_for_testing = []
|
222
228
|
end
|
223
229
|
|
224
230
|
def num_configs_for_testing
|
@@ -232,7 +238,8 @@ module NewRelic
|
|
232
238
|
private
|
233
239
|
|
234
240
|
def config_stack
|
235
|
-
stack = [@
|
241
|
+
stack = [@high_security_source,
|
242
|
+
@environment_source,
|
236
243
|
@server_source,
|
237
244
|
@manual_source,
|
238
245
|
@yaml_source,
|
@@ -2,6 +2,8 @@
|
|
2
2
|
# This file is distributed under New Relic's license terms.
|
3
3
|
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
4
|
|
5
|
+
require 'digest'
|
6
|
+
|
5
7
|
require 'new_relic/agent/transaction_state'
|
6
8
|
require 'new_relic/agent/threading/agent_thread'
|
7
9
|
|
@@ -102,6 +104,16 @@ module NewRelic
|
|
102
104
|
return info[1]
|
103
105
|
end
|
104
106
|
|
107
|
+
def client_referring_transaction_trip_id(state)
|
108
|
+
info = state.referring_transaction_info or return nil
|
109
|
+
return info[2]
|
110
|
+
end
|
111
|
+
|
112
|
+
def client_referring_transaction_path_hash(state)
|
113
|
+
info = state.referring_transaction_info or return nil
|
114
|
+
return info[3].is_a?(String) && info[3]
|
115
|
+
end
|
116
|
+
|
105
117
|
def insert_response_header(state, request_headers, response_headers)
|
106
118
|
unless state.client_cross_app_id.nil?
|
107
119
|
txn = state.current_transaction
|
@@ -183,6 +195,17 @@ module NewRelic
|
|
183
195
|
from_headers(request, CONTENT_LENGTH_HEADER_KEYS) || -1
|
184
196
|
end
|
185
197
|
|
198
|
+
def hash_transaction_name(identifier)
|
199
|
+
Digest::MD5.digest(identifier).unpack("@12N").first & 0xffffffff
|
200
|
+
end
|
201
|
+
|
202
|
+
def path_hash(txn_name, seed)
|
203
|
+
rotated = ((seed << 1) | (seed >> 31)) & 0xffffffff
|
204
|
+
app_name = NewRelic::Agent.config.app_names.first
|
205
|
+
identifier = "#{app_name};#{txn_name}"
|
206
|
+
sprintf("%08x", rotated ^ hash_transaction_name(identifier))
|
207
|
+
end
|
208
|
+
|
186
209
|
private
|
187
210
|
|
188
211
|
def from_headers(request, try_keys)
|
@@ -33,14 +33,16 @@ module NewRelic
|
|
33
33
|
# See the documentation for +start_trace+ for an explanation of what
|
34
34
|
# +request+ should look like.
|
35
35
|
#
|
36
|
-
def
|
37
|
-
|
36
|
+
def tl_trace_http_request(request)
|
37
|
+
state = NewRelic::Agent::TransactionState.tl_get
|
38
|
+
return yield unless state.is_execution_traced?
|
38
39
|
|
39
40
|
begin
|
40
|
-
t0
|
41
|
+
t0 = Time.now
|
42
|
+
segment = start_trace(state, t0, request)
|
41
43
|
response = yield
|
42
44
|
ensure
|
43
|
-
finish_trace( t0, segment, request, response
|
45
|
+
finish_trace(state, t0, segment, request, response)
|
44
46
|
end
|
45
47
|
|
46
48
|
return response
|
@@ -60,19 +62,20 @@ module NewRelic
|
|
60
62
|
# * []=(key, val) - Set an HTTP request header by name
|
61
63
|
# * uri - Full URI of the request
|
62
64
|
#
|
63
|
-
# This method
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
inject_request_headers(request) if cross_app_enabled?
|
70
|
-
segment = NewRelic::Agent::TracedMethodStack.tl_push_frame(:http_request, t0)
|
65
|
+
# This method returns the transaction segment if it was sucessfully pushed.
|
66
|
+
def start_trace(state, t0, request)
|
67
|
+
inject_request_headers(state, request) if cross_app_enabled?
|
68
|
+
stack = state.traced_method_stack
|
69
|
+
segment = stack.push_frame(state, :http_request, t0)
|
71
70
|
|
72
|
-
return
|
71
|
+
return segment
|
73
72
|
rescue => err
|
74
73
|
NewRelic::Agent.logger.error "Uncaught exception while tracing HTTP request", err
|
75
|
-
return
|
74
|
+
return nil
|
75
|
+
rescue Exception => e
|
76
|
+
NewRelic::Agent.logger.debug "Unexpected exception raised while tracing HTTP request", e
|
77
|
+
|
78
|
+
raise e
|
76
79
|
end
|
77
80
|
|
78
81
|
|
@@ -87,7 +90,7 @@ module NewRelic
|
|
87
90
|
# * [](key) - Reads response headers.
|
88
91
|
# * to_hash - Converts response headers to a Hash
|
89
92
|
#
|
90
|
-
def finish_trace(t0, segment, request, response)
|
93
|
+
def finish_trace(state, t0, segment, request, response)
|
91
94
|
t1 = Time.now
|
92
95
|
duration = t1.to_f - t0.to_f
|
93
96
|
|
@@ -98,8 +101,8 @@ module NewRelic
|
|
98
101
|
metrics = metrics_for(request, response)
|
99
102
|
scoped_metric = metrics.pop
|
100
103
|
|
101
|
-
stats_engine.
|
102
|
-
scoped_metric, metrics, duration)
|
104
|
+
stats_engine.record_scoped_and_unscoped_metrics(
|
105
|
+
state, scoped_metric, metrics, duration)
|
103
106
|
|
104
107
|
# If we don't have segment, something failed during start_trace so
|
105
108
|
# the current segment isn't the HTTP call it should have been.
|
@@ -111,7 +114,10 @@ module NewRelic
|
|
111
114
|
ensure
|
112
115
|
# If we have a segment, always pop the traced method stack to avoid
|
113
116
|
# an inconsistent state, which prevents tracing of whole transaction.
|
114
|
-
|
117
|
+
if segment
|
118
|
+
stack = state.traced_method_stack
|
119
|
+
stack.pop_frame(state, segment, scoped_metric, t1)
|
120
|
+
end
|
115
121
|
end
|
116
122
|
rescue NewRelic::Agent::CrossAppTracing::Error => err
|
117
123
|
NewRelic::Agent.logger.debug "while cross app tracing", err
|
@@ -150,17 +156,20 @@ module NewRelic
|
|
150
156
|
end
|
151
157
|
|
152
158
|
# Inject the X-Process header into the outgoing +request+.
|
153
|
-
def inject_request_headers(request)
|
159
|
+
def inject_request_headers(state, request)
|
154
160
|
cross_app_id = NewRelic::Agent.config[:cross_process_id] or
|
155
161
|
raise NewRelic::Agent::CrossAppTracing::Error, "no cross app ID configured"
|
156
162
|
|
157
|
-
state = NewRelic::Agent::TransactionState.tl_get
|
158
163
|
state.is_cross_app_caller = true
|
159
164
|
txn_guid = state.request_guid
|
160
|
-
|
165
|
+
if state.current_transaction
|
166
|
+
trip_id = state.current_transaction.cat_trip_id(state)
|
167
|
+
path_hash = state.current_transaction.cat_path_hash(state)
|
168
|
+
end
|
169
|
+
txn_data = NewRelic::JSONWrapper.dump([txn_guid, false, trip_id, path_hash])
|
161
170
|
|
162
|
-
request[
|
163
|
-
request[
|
171
|
+
request[NR_ID_HEADER] = obfuscator.obfuscate(cross_app_id)
|
172
|
+
request[NR_TXN_HEADER] = obfuscator.obfuscate(txn_data)
|
164
173
|
|
165
174
|
rescue NewRelic::Agent::CrossAppTracing::Error => err
|
166
175
|
NewRelic::Agent.logger.debug "Not injecting x-process header", err
|
@@ -169,8 +178,8 @@ module NewRelic
|
|
169
178
|
def add_transaction_trace_parameters(request, response)
|
170
179
|
filtered_uri = ::NewRelic::Agent::HTTPClients::URIUtil.filter_uri(request.uri)
|
171
180
|
transaction_sampler.add_segment_parameters(:uri => filtered_uri)
|
172
|
-
if response && response_is_crossapp?(
|
173
|
-
add_cat_transaction_trace_parameters(
|
181
|
+
if response && response_is_crossapp?(response)
|
182
|
+
add_cat_transaction_trace_parameters(response)
|
174
183
|
end
|
175
184
|
end
|
176
185
|
|
@@ -201,7 +210,6 @@ module NewRelic
|
|
201
210
|
metrics.concat metrics_for_regular_request( request )
|
202
211
|
end
|
203
212
|
else
|
204
|
-
NewRelic::Agent.logger.debug "Response doesn't have CAT headers."
|
205
213
|
metrics.concat metrics_for_regular_request( request )
|
206
214
|
end
|
207
215
|
|