newrelic_rpm 3.9.6.257 → 3.9.7.266
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 +45 -0
- data/lib/new_relic/agent.rb +0 -1
- data/lib/new_relic/agent/agent.rb +61 -22
- data/lib/new_relic/agent/agent_logger.rb +11 -9
- data/lib/new_relic/agent/configuration/default_source.rb +25 -2
- data/lib/new_relic/agent/cross_app_monitor.rb +15 -53
- data/lib/new_relic/agent/cross_app_tracing.rb +11 -3
- data/lib/new_relic/agent/custom_event_aggregator.rb +98 -0
- data/lib/new_relic/agent/event_buffer.rb +84 -0
- data/lib/new_relic/agent/harvester.rb +4 -15
- data/lib/new_relic/agent/hostname.rb +1 -9
- data/lib/new_relic/agent/inbound_request_monitor.rb +41 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +2 -2
- data/lib/new_relic/agent/instrumentation/queue_time.rb +0 -5
- data/lib/new_relic/agent/instrumentation/resque.rb +4 -9
- data/lib/new_relic/agent/javascript_instrumentor.rb +0 -12
- data/lib/new_relic/agent/method_tracer_helpers.rb +3 -1
- data/lib/new_relic/agent/new_relic_service.rb +1 -1
- data/lib/new_relic/agent/sampled_buffer.rb +13 -41
- data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +52 -24
- data/lib/new_relic/agent/sized_buffer.rb +23 -0
- data/lib/new_relic/agent/synthetics_monitor.rb +50 -0
- data/lib/new_relic/agent/system_info.rb +28 -0
- data/lib/new_relic/agent/transaction.rb +78 -9
- data/lib/new_relic/agent/transaction/synthetics_sample_buffer.rb +25 -0
- data/lib/new_relic/agent/{request_sampler.rb → transaction_event_aggregator.rb} +53 -19
- data/lib/new_relic/agent/transaction_sample_builder.rb +3 -1
- data/lib/new_relic/agent/transaction_sampler.rb +10 -0
- data/lib/new_relic/agent/transaction_state.rb +1 -9
- data/lib/new_relic/coerce.rb +8 -2
- data/lib/new_relic/control.rb +0 -1
- data/lib/new_relic/local_environment.rb +12 -8
- data/lib/new_relic/metric_spec.rb +11 -2
- data/lib/new_relic/rack/developer_mode.rb +9 -1
- data/lib/new_relic/transaction_sample.rb +4 -10
- data/lib/new_relic/version.rb +1 -1
- data/newrelic_rpm.gemspec +1 -0
- data/test/agent_helper.rb +15 -2
- data/test/environments/norails/Gemfile +1 -0
- data/test/environments/rails21/Gemfile +1 -0
- data/test/environments/rails22/Gemfile +1 -0
- data/test/environments/rails23/Gemfile +1 -0
- data/test/environments/rails30/Gemfile +1 -0
- data/test/environments/rails31/Gemfile +1 -0
- data/test/environments/rails32/Gemfile +2 -1
- data/test/environments/rails40/Gemfile +2 -1
- data/test/environments/rails41/Gemfile +3 -1
- data/test/environments/rails42/Gemfile +3 -1
- data/test/fixtures/cross_agent_tests/README.md +6 -2
- data/test/fixtures/cross_agent_tests/docker_container_id/README.md +6 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/cases.json +22 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-0.9.1.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.0.0.txt +10 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.3.txt +9 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/empty.txt +0 -0
- data/test/fixtures/cross_agent_tests/docker_container_id/lxc-containers-without-docker.txt +10 -0
- data/test/fixtures/cross_agent_tests/proc_meminfo/README.md +7 -0
- data/test/fixtures/cross_agent_tests/proc_meminfo/meminfo_4096MB.txt +47 -0
- data/test/fixtures/cross_agent_tests/rum_client_config.json +0 -80
- data/test/fixtures/cross_agent_tests/synthetics/synthetics.json +317 -0
- data/test/multiverse/lib/multiverse/runner.rb +1 -1
- data/test/multiverse/lib/multiverse/suite.rb +1 -0
- data/test/multiverse/suites/active_record/Envfile +42 -8
- data/test/multiverse/suites/active_record/ar_method_aliasing.rb +8 -4
- data/test/multiverse/suites/agent_only/audit_log_test.rb +0 -2
- data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +1 -2
- data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +5 -5
- data/test/multiverse/suites/agent_only/encoding_handling_test.rb +2 -0
- data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +8 -0
- data/test/multiverse/suites/agent_only/synthetics_test.rb +139 -0
- data/test/multiverse/suites/delayed_job/Envfile +79 -0
- data/test/multiverse/suites/delayed_job/before_suite.rb +33 -0
- data/test/multiverse/suites/delayed_job/config/newrelic.yml +18 -0
- data/test/multiverse/suites/delayed_job/delayed_job_sampler_test.rb +131 -0
- data/test/multiverse/suites/delayed_job/unsupported_backend_test.rb +24 -0
- data/test/multiverse/suites/high_security/high_security_test.rb +3 -10
- data/test/multiverse/suites/rails/Envfile +4 -4
- data/test/multiverse/suites/rails/request_statistics_test.rb +4 -4
- data/test/new_relic/agent/agent_test.rb +32 -4
- data/test/new_relic/agent/configuration/default_source_test.rb +6 -0
- data/test/new_relic/agent/cross_app_monitor_test.rb +23 -29
- data/test/new_relic/agent/custom_event_aggregator_test.rb +88 -0
- data/test/new_relic/agent/event_buffer_test_cases.rb +152 -0
- data/test/new_relic/agent/harvester_test.rb +5 -25
- data/test/new_relic/agent/hostname_test.rb +1 -1
- data/test/new_relic/agent/inbound_request_monitor_test.rb +49 -0
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +9 -9
- data/test/new_relic/agent/instrumentation/queue_time_test.rb +0 -19
- data/test/new_relic/agent/javascript_instrumentor_test.rb +0 -45
- data/test/new_relic/agent/new_relic_service_test.rb +17 -12
- data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -4
- data/test/new_relic/agent/sampled_buffer_test.rb +73 -145
- data/test/new_relic/agent/sized_buffer_test.rb +29 -0
- data/test/new_relic/agent/synthetics_monitor_test.rb +96 -0
- data/test/new_relic/agent/system_info_test.rb +19 -3
- data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +14 -8
- data/test/new_relic/agent/transaction/synthetics_sample_buffer_test.rb +38 -0
- data/test/new_relic/agent/{request_sampler_test.rb → transaction_event_aggregator_test.rb} +55 -4
- data/test/new_relic/agent/transaction_sampler_test.rb +33 -11
- data/test/new_relic/agent/transaction_state_test.rb +0 -1
- data/test/new_relic/agent/transaction_test.rb +121 -19
- data/test/new_relic/coerce_test.rb +38 -3
- data/test/new_relic/control_test.rb +1 -0
- data/test/new_relic/fake_collector.rb +6 -2
- data/test/new_relic/fake_external_server.rb +2 -6
- data/test/new_relic/fake_server.rb +46 -29
- data/test/new_relic/http_client_test_cases.rb +71 -2
- data/test/new_relic/local_environment_test.rb +78 -0
- data/test/new_relic/metric_parser/metric_parser_test.rb +2 -0
- data/test/new_relic/metric_spec_test.rb +43 -0
- data/test/new_relic/multiverse_helpers.rb +11 -18
- data/test/new_relic/rack/browser_monitoring_test.rb +1 -18
- data/test/new_relic/rack/developer_mode_test.rb +1 -1
- data/test/new_relic/transaction_sample_test.rb +14 -4
- data/test/performance/suites/rack_middleware.rb +3 -1
- data/test/test_helper.rb +33 -0
- metadata +48 -7
- metadata.gz.sig +0 -0
- data/lib/new_relic/agent/browser_token.rb +0 -41
- data/test/multiverse/suites/agent_only/before_suite.rb +0 -7
- data/test/new_relic/agent/browser_token_test.rb +0 -56
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,50 @@
|
|
1
1
|
# New Relic Ruby Agent Release Notes #
|
2
2
|
|
3
|
+
## v3.9.7 ##
|
4
|
+
|
5
|
+
* Support for New Relic Synthetics
|
6
|
+
|
7
|
+
The Ruby agent now gives you additional information for requests from New
|
8
|
+
Relic Synthetics. More transaction traces and events give you a clearer look
|
9
|
+
into how your applicaiton is performing around the world.
|
10
|
+
|
11
|
+
For more details, see https://docs.newrelic.com/docs/synthetics/new-relic-synthetics/getting-started/new-relic-synthetics
|
12
|
+
|
13
|
+
* Support for multiple job per fork gems with Resque
|
14
|
+
|
15
|
+
The resque-jobs-per-fork and resque-multi-job-forks gems alter Resque to
|
16
|
+
fork every N jobs instead of every job. This previously caused issues for
|
17
|
+
the Ruby agent, but those have been resolved. These gems are fully supported.
|
18
|
+
|
19
|
+
Running Resque with the FORK_PER_JOB=false environment variable setting is
|
20
|
+
also supported now.
|
21
|
+
|
22
|
+
For more details on our Resque support, see https://docs.newrelic.com/docs/agents/ruby-agent/background-jobs/resque-instrumentation
|
23
|
+
|
24
|
+
* Support agent when starting Resque Pool from Rake task
|
25
|
+
|
26
|
+
When running resque-pool with its provided rake tasks, the agent would not
|
27
|
+
start up properly. Thanks Tiago Sousa for the fix!
|
28
|
+
|
29
|
+
* Fix for DelayedJob + Rails 4.x queue depth metrics
|
30
|
+
|
31
|
+
The Ruby agent periodically records DelayedJob queuedepth as a metric, but
|
32
|
+
this didn't work properly in Rails 4.x applications. This has been fixed.
|
33
|
+
Thanks Jonathan del Strother for his help with the issue!
|
34
|
+
|
35
|
+
* Fix for failure in background transactions with rules.ignore_url_regexes
|
36
|
+
|
37
|
+
The recently added feature for ignoring transactions via URL regexes caused
|
38
|
+
errors for non-web transactions. This has been fixed.
|
39
|
+
|
40
|
+
* Rename the TransactionNamer.name method to TransactionNamer.name_for
|
41
|
+
|
42
|
+
The internal TransactionNamer class had a class method called 'name', with a
|
43
|
+
different signature than the existing Class#name method and could cause
|
44
|
+
problems when trying to introspect instances of the class.
|
45
|
+
|
46
|
+
Thanks to Dennis Taylor for contributing this fix!
|
47
|
+
|
3
48
|
## v3.9.6 ##
|
4
49
|
|
5
50
|
* Rails 4.2 ActiveJob support
|
data/lib/new_relic/agent.rb
CHANGED
@@ -76,7 +76,6 @@ module NewRelic
|
|
76
76
|
require 'new_relic/metric_spec'
|
77
77
|
require 'new_relic/metric_data'
|
78
78
|
require 'new_relic/collection_helper'
|
79
|
-
require 'new_relic/transaction_analysis'
|
80
79
|
require 'new_relic/transaction_sample'
|
81
80
|
require 'new_relic/url_rule'
|
82
81
|
require 'new_relic/noticed_error'
|
@@ -19,7 +19,9 @@ require 'new_relic/agent/database'
|
|
19
19
|
require 'new_relic/agent/commands/agent_command_router'
|
20
20
|
require 'new_relic/agent/event_listener'
|
21
21
|
require 'new_relic/agent/cross_app_monitor'
|
22
|
-
require 'new_relic/agent/
|
22
|
+
require 'new_relic/agent/synthetics_monitor'
|
23
|
+
require 'new_relic/agent/transaction_event_aggregator'
|
24
|
+
require 'new_relic/agent/custom_event_aggregator'
|
23
25
|
require 'new_relic/agent/sampler_collection'
|
24
26
|
require 'new_relic/agent/javascript_instrumentor'
|
25
27
|
require 'new_relic/agent/vm/monotonic_gc_profiler'
|
@@ -48,14 +50,19 @@ module NewRelic
|
|
48
50
|
@sql_sampler = NewRelic::Agent::SqlSampler.new
|
49
51
|
@agent_command_router = NewRelic::Agent::Commands::AgentCommandRouter.new(@events)
|
50
52
|
@cross_app_monitor = NewRelic::Agent::CrossAppMonitor.new(@events)
|
53
|
+
@synthetics_monitor = NewRelic::Agent::SyntheticsMonitor.new(@events)
|
51
54
|
@error_collector = NewRelic::Agent::ErrorCollector.new
|
52
55
|
@transaction_rules = NewRelic::Agent::RulesEngine.new
|
53
|
-
@request_sampler = NewRelic::Agent::RequestSampler.new(@events)
|
54
56
|
@harvest_samplers = NewRelic::Agent::SamplerCollection.new(@events)
|
55
57
|
@javascript_instrumentor = NewRelic::Agent::JavascriptInstrumentor.new(@events)
|
56
|
-
@harvester = NewRelic::Agent::Harvester.new(@events)
|
57
58
|
@monotonic_gc_profiler = NewRelic::Agent::VM::MonotonicGCProfiler.new
|
58
59
|
|
60
|
+
@harvester = NewRelic::Agent::Harvester.new(@events)
|
61
|
+
@after_fork_lock = Mutex.new
|
62
|
+
|
63
|
+
@transaction_event_aggregator = NewRelic::Agent::TransactionEventAggregator.new(@events)
|
64
|
+
@custom_event_aggregator = NewRelic::Agent::CustomEventAggregator.new
|
65
|
+
|
59
66
|
@connect_state = :pending
|
60
67
|
@connect_attempts = 0
|
61
68
|
@environment_report = nil
|
@@ -112,6 +119,7 @@ module NewRelic
|
|
112
119
|
attr_reader :harvest_lock
|
113
120
|
# GC::Profiler.total_time is not monotonic so we wrap it.
|
114
121
|
attr_reader :monotonic_gc_profiler
|
122
|
+
attr_reader :custom_event_aggregator
|
115
123
|
|
116
124
|
# This method should be called in a forked process after a fork.
|
117
125
|
# It assumes the parent process initialized the agent, but does
|
@@ -133,28 +141,22 @@ module NewRelic
|
|
133
141
|
# connection, this tells me to only try it once so this method returns
|
134
142
|
# quickly if there is some kind of latency with the server.
|
135
143
|
def after_fork(options={})
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
if channel_id = options[:report_to_channel]
|
141
|
-
@service = NewRelic::Agent::PipeService.new(channel_id)
|
142
|
-
if connected?
|
143
|
-
@connected_pid = Process.pid
|
144
|
-
else
|
145
|
-
::NewRelic::Agent.logger.debug("Child process #{Process.pid} not reporting to non-connected parent (process #{Process.ppid}).")
|
146
|
-
@service.shutdown(Time.now)
|
147
|
-
disconnect
|
148
|
-
end
|
144
|
+
needs_restart = false
|
145
|
+
@after_fork_lock.synchronize do
|
146
|
+
needs_restart = @harvester.needs_restart?
|
147
|
+
@harvester.mark_started
|
149
148
|
end
|
150
149
|
|
151
|
-
return if !
|
150
|
+
return if !needs_restart ||
|
151
|
+
!Agent.config[:agent_enabled] ||
|
152
152
|
!Agent.config[:monitor_mode] ||
|
153
|
-
disconnected?
|
154
|
-
@worker_thread && @worker_thread.alive?
|
153
|
+
disconnected?
|
155
154
|
|
156
155
|
::NewRelic::Agent.logger.debug "Starting the worker thread in #{Process.pid} (parent #{Process.ppid}) after forking."
|
157
156
|
|
157
|
+
channel_id = options[:report_to_channel]
|
158
|
+
install_pipe_service(channel_id) if channel_id
|
159
|
+
|
158
160
|
# Clear out locks and stats left over from parent process
|
159
161
|
reset_objects_with_locks
|
160
162
|
drop_buffered_data
|
@@ -162,6 +164,17 @@ module NewRelic
|
|
162
164
|
setup_and_start_agent(options)
|
163
165
|
end
|
164
166
|
|
167
|
+
def install_pipe_service(channel_id)
|
168
|
+
@service = NewRelic::Agent::PipeService.new(channel_id)
|
169
|
+
if connected?
|
170
|
+
@connected_pid = Process.pid
|
171
|
+
else
|
172
|
+
::NewRelic::Agent.logger.debug("Child process #{Process.pid} not reporting to non-connected parent (process #{Process.ppid}).")
|
173
|
+
@service.shutdown(Time.now)
|
174
|
+
disconnect
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
165
178
|
# True if we have initialized and completed 'start'
|
166
179
|
def started?
|
167
180
|
@started
|
@@ -514,7 +527,8 @@ module NewRelic
|
|
514
527
|
@stats_engine.reset!
|
515
528
|
@error_collector.reset!
|
516
529
|
@transaction_sampler.reset!
|
517
|
-
@
|
530
|
+
@transaction_event_aggregator.reset!
|
531
|
+
@custom_event_aggregator.reset!
|
518
532
|
@sql_sampler.reset!
|
519
533
|
end
|
520
534
|
|
@@ -531,6 +545,13 @@ module NewRelic
|
|
531
545
|
reset_harvest_locks
|
532
546
|
end
|
533
547
|
|
548
|
+
def flush_pipe_data
|
549
|
+
if connected? && @service.is_a?(::NewRelic::Agent::PipeService)
|
550
|
+
transmit_data
|
551
|
+
transmit_event_data
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
534
555
|
private
|
535
556
|
|
536
557
|
# All of this module used to be contained in the
|
@@ -577,6 +598,8 @@ module NewRelic
|
|
577
598
|
period
|
578
599
|
end
|
579
600
|
|
601
|
+
LOG_ONCE_KEYS_RESET_PERIOD = 60.0
|
602
|
+
|
580
603
|
def create_and_run_event_loop
|
581
604
|
@event_loop = create_event_loop
|
582
605
|
@event_loop.on(:report_data) do
|
@@ -585,8 +608,12 @@ module NewRelic
|
|
585
608
|
@event_loop.on(:report_event_data) do
|
586
609
|
transmit_event_data
|
587
610
|
end
|
611
|
+
@event_loop.on(:reset_log_once_keys) do
|
612
|
+
::NewRelic::Agent.logger.clear_already_logged
|
613
|
+
end
|
588
614
|
@event_loop.fire_every(Agent.config[:data_report_period], :report_data)
|
589
615
|
@event_loop.fire_every(report_period_for(:analytic_event_data), :report_event_data)
|
616
|
+
@event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
|
590
617
|
@event_loop.run
|
591
618
|
end
|
592
619
|
|
@@ -854,7 +881,7 @@ module NewRelic
|
|
854
881
|
when :metric_data then @stats_engine
|
855
882
|
when :transaction_sample_data then @transaction_sampler
|
856
883
|
when :error_data then @error_collector
|
857
|
-
when :analytic_event_data then @
|
884
|
+
when :analytic_event_data then @transaction_event_aggregator
|
858
885
|
when :sql_trace_data then @sql_sampler
|
859
886
|
end
|
860
887
|
end
|
@@ -978,6 +1005,9 @@ module NewRelic
|
|
978
1005
|
NewRelic::Agent.logger.warn("Failed to serialize data for #{endpoint}, discarding. Error: ", e)
|
979
1006
|
rescue UnrecoverableServerException => e
|
980
1007
|
NewRelic::Agent.logger.warn("#{endpoint} data was rejected by remote service, discarding. Error: ", e)
|
1008
|
+
rescue ServerConnectionException => e
|
1009
|
+
log_remote_unavailable(endpoint, e)
|
1010
|
+
container.merge!(items)
|
981
1011
|
rescue => e
|
982
1012
|
NewRelic::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
|
983
1013
|
container.merge!(items)
|
@@ -1012,7 +1042,8 @@ module NewRelic
|
|
1012
1042
|
end
|
1013
1043
|
|
1014
1044
|
def harvest_and_send_analytic_event_data
|
1015
|
-
harvest_and_send_from_container(@
|
1045
|
+
harvest_and_send_from_container(@transaction_event_aggregator, :analytic_event_data)
|
1046
|
+
harvest_and_send_from_container(@custom_event_aggregator, :analytic_event_data)
|
1016
1047
|
end
|
1017
1048
|
|
1018
1049
|
def check_for_and_handle_agent_commands
|
@@ -1020,11 +1051,19 @@ module NewRelic
|
|
1020
1051
|
@agent_command_router.check_for_and_handle_agent_commands
|
1021
1052
|
rescue ForceRestartException, ForceDisconnectException
|
1022
1053
|
raise
|
1054
|
+
rescue ServerConnectionException => e
|
1055
|
+
log_remote_unavailable(:get_agent_commands, e)
|
1023
1056
|
rescue => e
|
1024
1057
|
NewRelic::Agent.logger.info("Error during check_for_and_handle_agent_commands, will retry later: ", e)
|
1025
1058
|
end
|
1026
1059
|
end
|
1027
1060
|
|
1061
|
+
def log_remote_unavailable(endpoint, e)
|
1062
|
+
NewRelic::Agent.logger.debug("Unable to send #{endpoint} data, will try again later. Error: ", e)
|
1063
|
+
NewRelic::Agent.record_metric("Supportability/remote_unavailable", 0.0)
|
1064
|
+
NewRelic::Agent.record_metric("Supportability/remote_unavailable/#{endpoint.to_s}", 0.0)
|
1065
|
+
end
|
1066
|
+
|
1028
1067
|
def transmit_data
|
1029
1068
|
harvest_lock.synchronize do
|
1030
1069
|
transmit_data_already_locked
|
@@ -9,7 +9,10 @@ module NewRelic
|
|
9
9
|
module Agent
|
10
10
|
class AgentLogger
|
11
11
|
|
12
|
+
attr_reader :already_logged
|
13
|
+
|
12
14
|
def initialize(root = "", override_logger=nil)
|
15
|
+
clear_already_logged
|
13
16
|
create_log(root, override_logger)
|
14
17
|
set_log_level!
|
15
18
|
set_log_format!
|
@@ -40,10 +43,14 @@ module NewRelic
|
|
40
43
|
NUM_LOG_ONCE_KEYS = 1000
|
41
44
|
|
42
45
|
def log_once(level, key, *msgs)
|
43
|
-
|
46
|
+
# Since `already_logged` might change between calls, just grab it once
|
47
|
+
# and use it throughout this method.
|
48
|
+
logged = already_logged
|
49
|
+
|
50
|
+
return if logged.include?(key)
|
44
51
|
|
45
|
-
if
|
46
|
-
# The reason for preventing too many keys in `
|
52
|
+
if logged.size >= NUM_LOG_ONCE_KEYS && key.kind_of?(String)
|
53
|
+
# The reason for preventing too many keys in `logged` is for
|
47
54
|
# memory concerns.
|
48
55
|
# The reason for checking the type of the key is that we always want
|
49
56
|
# to allow symbols to log, since there are very few of them.
|
@@ -54,7 +61,7 @@ module NewRelic
|
|
54
61
|
return
|
55
62
|
end
|
56
63
|
|
57
|
-
|
64
|
+
logged[key] = true
|
58
65
|
self.send(level, *msgs)
|
59
66
|
end
|
60
67
|
|
@@ -140,11 +147,6 @@ module NewRelic
|
|
140
147
|
@log = ::NewRelic::Agent::NullLogger.new
|
141
148
|
end
|
142
149
|
|
143
|
-
def already_logged
|
144
|
-
@already_logged ||= {}
|
145
|
-
@already_logged
|
146
|
-
end
|
147
|
-
|
148
150
|
def clear_already_logged
|
149
151
|
@already_logged = {}
|
150
152
|
end
|
@@ -202,10 +202,13 @@ module NewRelic
|
|
202
202
|
case value
|
203
203
|
when String
|
204
204
|
value.split(',')
|
205
|
-
|
205
|
+
when Array
|
206
206
|
value
|
207
|
+
else
|
208
|
+
raise ArgumentError.new("Config value '#{value}' couldn't be turned into a list.")
|
207
209
|
end
|
208
210
|
end
|
211
|
+
|
209
212
|
end
|
210
213
|
|
211
214
|
AUTOSTART_BLACKLISTED_RAKE_TASKS = [
|
@@ -1079,6 +1082,7 @@ module NewRelic
|
|
1079
1082
|
:default => ['scheduler', 'run'],
|
1080
1083
|
:public => true,
|
1081
1084
|
:type => Array,
|
1085
|
+
:transform => DefaultSource.method(:convert_to_list),
|
1082
1086
|
:description => 'List of prefixes for heroku dyno names (such as "scheduler") to report as hostname without trailing dot and process ID.'
|
1083
1087
|
},
|
1084
1088
|
:labels => {
|
@@ -1112,7 +1116,26 @@ module NewRelic
|
|
1112
1116
|
:type => Array,
|
1113
1117
|
:transform => DefaultSource.rules_ignore,
|
1114
1118
|
:description => 'A list of patterns that will cause a transaction to be ignored if any of them match the URI.'
|
1115
|
-
|
1119
|
+
},
|
1120
|
+
:'synthetics.traces_limit' => {
|
1121
|
+
:default => 20,
|
1122
|
+
:public => false,
|
1123
|
+
:type => Fixnum,
|
1124
|
+
:description => 'Maximum number of synthetics transaction traces to hold for a given harvest'
|
1125
|
+
},
|
1126
|
+
:'synthetics.events_limit' => {
|
1127
|
+
:default => 200,
|
1128
|
+
:public => false,
|
1129
|
+
:type => Fixnum,
|
1130
|
+
:description => 'Maximum number of synthetics transaction events to hold for a given harvest'
|
1131
|
+
},
|
1132
|
+
:'custom_insights_events.max_samples_stored' => {
|
1133
|
+
:default => 1000,
|
1134
|
+
:public => true,
|
1135
|
+
:type => Fixnum,
|
1136
|
+
:description => 'Maximum number of custom Insights events buffered in memory at a time.',
|
1137
|
+
:dynamic_name => true
|
1138
|
+
}
|
1116
1139
|
}.freeze
|
1117
1140
|
|
1118
1141
|
end
|
@@ -4,51 +4,33 @@
|
|
4
4
|
|
5
5
|
require 'digest'
|
6
6
|
|
7
|
+
require 'new_relic/agent/inbound_request_monitor'
|
7
8
|
require 'new_relic/agent/transaction_state'
|
8
9
|
require 'new_relic/agent/threading/agent_thread'
|
9
10
|
|
10
11
|
module NewRelic
|
11
12
|
module Agent
|
13
|
+
class CrossAppMonitor < InboundRequestMonitor
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
NEWRELIC_ID_HEADER = 'X-NewRelic-ID'
|
15
|
+
NEWRELIC_ID_HEADER = 'X-NewRelic-ID'
|
16
|
+
NEWRELIC_TXN_HEADER = 'X-NewRelic-Transaction'
|
16
17
|
NEWRELIC_APPDATA_HEADER = 'X-NewRelic-App-Data'
|
17
|
-
NEWRELIC_TXN_HEADER = 'X-NewRelic-Transaction'
|
18
|
-
NEWRELIC_TXN_HEADER_KEYS = %W{
|
19
|
-
#{NEWRELIC_TXN_HEADER} HTTP_X_NEWRELIC_TRANSACTION X_NEWRELIC_TRANSACTION
|
20
|
-
}
|
21
|
-
NEWRELIC_ID_HEADER_KEYS = %W{
|
22
|
-
#{NEWRELIC_ID_HEADER} HTTP_X_NEWRELIC_ID X_NEWRELIC_ID
|
23
|
-
}
|
24
|
-
CONTENT_LENGTH_HEADER_KEYS = %w{Content-Length HTTP_CONTENT_LENGTH CONTENT_LENGTH}
|
25
|
-
|
26
|
-
attr_reader :obfuscator
|
27
|
-
|
28
|
-
def initialize(events = nil)
|
29
|
-
# When we're starting up for real in the agent, we get passed the events
|
30
|
-
# Other spots can pull from the agent, during startup the agent doesn't exist yet!
|
31
|
-
events ||= Agent.instance.events
|
32
|
-
|
33
|
-
events.subscribe(:finished_configuring) do
|
34
|
-
on_finished_configuring
|
35
|
-
end
|
36
|
-
end
|
37
18
|
|
38
|
-
|
39
|
-
|
40
|
-
|
19
|
+
NEWRELIC_ID_HEADER_KEY = 'HTTP_X_NEWRELIC_ID'.freeze
|
20
|
+
NEWRELIC_TXN_HEADER_KEY = 'HTTP_X_NEWRELIC_TRANSACTION'.freeze
|
21
|
+
CONTENT_LENGTH_HEADER_KEY = 'HTTP_CONTENT_LENGTH'.freeze
|
22
|
+
|
23
|
+
def on_finished_configuring(events)
|
24
|
+
register_event_listeners(events)
|
41
25
|
end
|
42
26
|
|
43
27
|
# Expected sequence of events:
|
44
28
|
# :before_call will save our cross application request id to the thread
|
45
|
-
# :start_transaction will get called when a transaction starts up
|
46
29
|
# :after_call will write our response headers/metrics and clean up the thread
|
47
|
-
def register_event_listeners
|
30
|
+
def register_event_listeners(events)
|
48
31
|
NewRelic::Agent.logger.
|
49
32
|
debug("Wiring up Cross Application Tracing to events after finished configuring")
|
50
33
|
|
51
|
-
events = Agent.instance.events
|
52
34
|
events.subscribe(:before_call) do |env| #THREAD_LOCAL_ACCESS
|
53
35
|
if should_process_request(env)
|
54
36
|
state = NewRelic::Agent::TransactionState.tl_get
|
@@ -72,11 +54,6 @@ module NewRelic
|
|
72
54
|
end
|
73
55
|
end
|
74
56
|
|
75
|
-
# This requires :encoding_key, so must wait until :finished_configuring
|
76
|
-
def setup_obfuscator
|
77
|
-
@obfuscator = NewRelic::Agent::Obfuscator.new(NewRelic::Agent.config[:encoding_key])
|
78
|
-
end
|
79
|
-
|
80
57
|
def save_client_cross_app_id(state, request_headers)
|
81
58
|
state.client_cross_app_id = decoded_id(request_headers)
|
82
59
|
end
|
@@ -86,9 +63,8 @@ module NewRelic
|
|
86
63
|
end
|
87
64
|
|
88
65
|
def save_referring_transaction_info(state, request_headers)
|
89
|
-
txn_header =
|
90
|
-
|
91
|
-
txn_info = NewRelic::JSONWrapper.load(txn_header)
|
66
|
+
txn_header = request_headers[NEWRELIC_TXN_HEADER_KEY] or return
|
67
|
+
txn_info = deserialize_header(txn_header, NEWRELIC_TXN_HEADER)
|
92
68
|
state.referring_transaction_info = txn_info
|
93
69
|
end
|
94
70
|
|
@@ -182,14 +158,14 @@ module NewRelic
|
|
182
158
|
end
|
183
159
|
|
184
160
|
def decoded_id(request)
|
185
|
-
encoded_id =
|
161
|
+
encoded_id = request[NEWRELIC_ID_HEADER_KEY]
|
186
162
|
return "" if encoded_id.nil?
|
187
163
|
|
188
164
|
obfuscator.deobfuscate(encoded_id)
|
189
165
|
end
|
190
166
|
|
191
167
|
def content_length_from_request(request)
|
192
|
-
|
168
|
+
request[CONTENT_LENGTH_HEADER_KEY] || -1
|
193
169
|
end
|
194
170
|
|
195
171
|
def hash_transaction_name(identifier)
|
@@ -202,20 +178,6 @@ module NewRelic
|
|
202
178
|
identifier = "#{app_name};#{txn_name}"
|
203
179
|
sprintf("%08x", rotated ^ hash_transaction_name(identifier))
|
204
180
|
end
|
205
|
-
|
206
|
-
private
|
207
|
-
|
208
|
-
def from_headers(request, try_keys)
|
209
|
-
# For lookups, upcase all our keys on both sides just to be safe
|
210
|
-
upcased_keys = try_keys.map{|k| k.upcase}
|
211
|
-
upcased_keys.each do |header|
|
212
|
-
found_key = request.keys.find { |k| k.upcase == header }
|
213
|
-
return request[found_key] unless found_key.nil?
|
214
|
-
end
|
215
|
-
nil
|
216
|
-
end
|
217
|
-
|
218
181
|
end
|
219
|
-
|
220
182
|
end
|
221
183
|
end
|