newrelic_rpm 8.8.0 → 8.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +31 -3
  4. data/.simplecov +5 -0
  5. data/CHANGELOG.md +18 -0
  6. data/lib/new_relic/agent/agent/shutdown.rb +34 -0
  7. data/lib/new_relic/agent/agent/special_startup.rb +70 -0
  8. data/lib/new_relic/agent/agent/start_worker_thread.rb +163 -0
  9. data/lib/new_relic/agent/agent/startup.rb +196 -0
  10. data/lib/new_relic/agent/agent.rb +10 -439
  11. data/lib/new_relic/agent/agent_logger.rb +3 -5
  12. data/lib/new_relic/agent/autostart.rb +1 -1
  13. data/lib/new_relic/agent/commands/agent_command_router.rb +1 -1
  14. data/lib/new_relic/agent/configuration/default_source.rb +10 -10
  15. data/lib/new_relic/agent/configuration/manager.rb +2 -2
  16. data/lib/new_relic/agent/connect/request_builder.rb +1 -1
  17. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -1
  19. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +11 -3
  20. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +9 -2
  21. data/lib/new_relic/agent/instrumentation/sunspot.rb +2 -2
  22. data/lib/new_relic/agent/monitors/cross_app_monitor.rb +1 -1
  23. data/lib/new_relic/agent/pipe_channel_manager.rb +6 -1
  24. data/lib/new_relic/agent/pipe_service.rb +1 -1
  25. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +1 -1
  26. data/lib/new_relic/agent/sql_sampler.rb +1 -1
  27. data/lib/new_relic/agent/system_info.rb +59 -44
  28. data/lib/new_relic/agent/threading/thread_profile.rb +2 -2
  29. data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +1 -1
  30. data/lib/new_relic/agent/transaction_sampler.rb +1 -1
  31. data/lib/new_relic/agent.rb +1 -1
  32. data/lib/new_relic/coerce.rb +1 -1
  33. data/lib/new_relic/collection_helper.rb +1 -1
  34. data/lib/new_relic/dependency_detection.rb +2 -2
  35. data/lib/new_relic/local_environment.rb +1 -1
  36. data/lib/new_relic/metric_data.rb +1 -1
  37. data/lib/new_relic/metric_spec.rb +1 -1
  38. data/lib/new_relic/rack/browser_monitoring.rb +1 -1
  39. data/lib/new_relic/version.rb +1 -1
  40. data/lib/tasks/config.rake +4 -0
  41. data/lib/tasks/coverage_report.rake +22 -0
  42. data/lib/tasks/install.rake +4 -0
  43. data/lib/tasks/multiverse.rake +4 -0
  44. data/lib/tasks/tests.rake +4 -1
  45. data/newrelic.yml +1 -1
  46. data/newrelic_rpm.gemspec +4 -1
  47. metadata +36 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0eb3871a3ff66d8707dd01f40025d812d34904c02631d3a83af046bdbaeacdeb
4
- data.tar.gz: 4e73dfe935bcd268ad0969a2c076e83313e75c3f3f0b711a7cba8c3af1327677
3
+ metadata.gz: e16c313766a7d9c51bc1a1c3031f666747b4a3aefa773cf226d28510d90d6658
4
+ data.tar.gz: cb464a40400ce3b4a41178f737fa804952bfe22de66dc88f73deccaa256520a6
5
5
  SHA512:
6
- metadata.gz: 07566af3aff20a1fe5951fb36e34086f665e8788ecb7edfd2664213e73877e7a1c58d4447f2dd85efb75beeda0ce2f484c513d4a7a09c01bcbe4c20e8a5cba1a
7
- data.tar.gz: 577944d3712cdd9908d4a564346e7f4bd6fd5772fa00069d73acdb3d8a033621042c72346ddd4ca22585910f035116701f0f904dd8f40c8f0b1e9934bd787705
6
+ metadata.gz: 93915783c6110bbc027d03d614b5ad582ba0bf73b93933d4a93f11a7e698fd82436c74b3b941c27846e6e1ae408b7d8929b9c1d7dcae0e6103ed3ded2836c9c2
7
+ data.tar.gz: f7a5196e10ecd5dd88ed16b218cdcb760511d3747f1c821ccc7f4b6c5e22c28a1e08d581022513d04e6540d6d5cd62419cc587c05c8154d4a7abe6a574944a97
data/.gitignore CHANGED
@@ -15,6 +15,7 @@ tags
15
15
  *.swp
16
16
  *.swo
17
17
 
18
+ coverage
18
19
  /doc/
19
20
  /log/
20
21
  /lerg/
@@ -33,7 +34,9 @@ infinite_tracing/test/new_relic/infinite_tracing/log
33
34
  test/fixtures/cross_agent_tests/*/README.md
34
35
  node_modules/
35
36
  yarn.lock
37
+ package-lock.json
36
38
  errors.txt
37
39
  .history/
38
40
  vendor/
39
41
  Brewfile.lock.json
42
+ .github/actions/simplecov-report/lib/
data/.rubocop.yml CHANGED
@@ -2,9 +2,9 @@ require:
2
2
  - rubocop-performance
3
3
 
4
4
  AllCops:
5
- # Prevent RuboCop from exploding when it finds an older-than-2.4 .ruby-version
6
5
  TargetRubyVersion: 2.7
7
6
  Exclude: []
7
+ NewCops: enable
8
8
 
9
9
  Bundler/DuplicatedGem:
10
10
  Enabled: true
@@ -33,7 +33,7 @@ Bundler/InsecureProtocolSource:
33
33
  Bundler/OrderedGems:
34
34
  Enabled: false
35
35
 
36
- Gemspec/DateAssignment:
36
+ Gemspec/DeprecatedAttributeAssignment:
37
37
  Enabled: true
38
38
 
39
39
  Gemspec/DuplicatedAssignment:
@@ -44,6 +44,9 @@ Gemspec/DuplicatedAssignment:
44
44
  Gemspec/OrderedDependencies:
45
45
  Enabled: false
46
46
 
47
+ Gemspec/RequireMFA:
48
+ Enabled: false
49
+
47
50
  Gemspec/RequiredRubyVersion:
48
51
  Enabled: false
49
52
 
@@ -238,7 +241,7 @@ Layout/IndentationStyle:
238
241
  Layout/IndentationWidth:
239
242
  Enabled: true
240
243
  Width: 2
241
- IgnoredPatterns: []
244
+ AllowedPatterns: []
242
245
 
243
246
  Layout/InitialIndentation:
244
247
  Enabled: true
@@ -1317,6 +1320,12 @@ Style/EndBlock:
1317
1320
  Style/EndlessMethod:
1318
1321
  Enabled: false
1319
1322
 
1323
+ # The use of Dir.home should be preferred over ENV['HOME'], but as of
1324
+ # JRuby 9.3.3.0 the use of ENV['HOME'] is required to deliver the desired
1325
+ # functionality
1326
+ Style/EnvHome:
1327
+ Enabled: false
1328
+
1320
1329
  # Disabling for now
1321
1330
  Style/EvalWithLocation:
1322
1331
  Enabled: false
@@ -1333,6 +1342,11 @@ Style/ExplicitBlockArgument:
1333
1342
  Style/ExponentialNotation:
1334
1343
  Enabled: false
1335
1344
 
1345
+ # TODO: MAJOR VERSION - Re-enable FetchEnvVar after dropping support for Ruby 2.2
1346
+ # Ruby 2.3+ allows for ENV.fetch('KEY') { default }
1347
+ Style/FetchEnvVar:
1348
+ Enabled: false
1349
+
1336
1350
  Style/FloatDivision:
1337
1351
  Enabled: false
1338
1352
 
@@ -1446,6 +1460,13 @@ Style/LineEndConcatenation:
1446
1460
  Enabled: false
1447
1461
  # SafeAutoCorrect: false
1448
1462
 
1463
+ # TODO: OLD RUBIES - enable this cop after support for Ruby <= 2.5 has been
1464
+ # dropped. NewRelic::Agent::InfiniteTracing::Transformer.hash_to_attributes
1465
+ # currently does `values.map {}.to_h`. Newer Rubies should
1466
+ # use `values.to_h {}` instead.
1467
+ Style/MapToHash:
1468
+ Enabled: false
1469
+
1449
1470
  Style/MethodCallWithArgsParentheses:
1450
1471
  Enabled: false
1451
1472
 
@@ -1589,6 +1610,13 @@ Style/NumericPredicate:
1589
1610
  Style/OneLineConditional:
1590
1611
  Enabled: true
1591
1612
 
1613
+ # TODO: UNIT TESTS - tests relying on OpenStruct should be refactored to not
1614
+ # do so, given that the use of OpenStruct instances can
1615
+ # give a false sense of security with their extreme
1616
+ # flexibility that may not match realistic code behavior.
1617
+ Style/OpenStructUse:
1618
+ Enabled: false
1619
+
1592
1620
  Style/OptionHash:
1593
1621
  Enabled: false
1594
1622
 
data/.simplecov ADDED
@@ -0,0 +1,5 @@
1
+ SimpleCov.start do
2
+ enable_coverage :branch
3
+ SimpleCov.root(File.join(File.dirname(__FILE__), '/lib'))
4
+ track_files "**/*.rb"
5
+ end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
+
4
+ ## v8.9.0
5
+
6
+
7
+ * **Add support for Dalli 3.1.0 to Dalli 3.2.2**
8
+
9
+ Dalli versions 3.1.0 and above include breaking changes where the agent previously hooked into the gem. We have updated our instrumentation to correctly hook into Dalli 3.1.0 and above. At this time, 3.2.2 is the latest Dalli version and is confirmed to be supported.
10
+
11
+
12
+ * **Bugfix: Infinite Tracing hung on connection restart**
13
+
14
+ Previously, when using infinite tracing, the agent would intermittently encounter a deadlock when attempting to restart the infinite tracing connection. This bug would prevent the agent from sending all data types, including non-infinite-tracing-related data. This change reworks how we restart infinite tracing to prevent potential deadlocks.
15
+
16
+ * **Bugfix: Use read_nonblock instead of read on pipe**
17
+
18
+ Previously, our PipeChannelManager was using read which could cause Resque jobs to get stuck in some versions. This change updates the PipeChannelManager to use read_nonblock instead. This method can leverage error handling to allow the instrumentation to gracefully log a message and exit the stuck Resque job.
19
+
20
+
3
21
  ## v8.8.0
4
22
 
5
23
  * **Support Makara database adapters with ActiveRecord**
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module Shutdown
8
+ # Attempt a graceful shutdown of the agent, flushing any remaining
9
+ # data.
10
+ def shutdown
11
+ return unless started?
12
+ ::NewRelic::Agent.logger.info "Starting Agent shutdown"
13
+
14
+ stop_event_loop
15
+ trap_signals_for_litespeed
16
+ untraced_graceful_disconnect
17
+ revert_to_default_configuration
18
+
19
+ @started = nil
20
+ Control.reset
21
+ end
22
+
23
+ def untraced_graceful_disconnect
24
+ begin
25
+ NewRelic::Agent.disable_all_tracing do
26
+ graceful_disconnect
27
+ end
28
+ rescue => e
29
+ ::NewRelic::Agent.logger.error e
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module SpecialStartup
8
+ # If we're using a dispatcher that forks before serving
9
+ # requests, we need to wait until the children are forked
10
+ # before connecting, otherwise the parent process sends useless data
11
+ def using_forking_dispatcher?
12
+ # TODO: MAJOR VERSION - remove :rainbows
13
+ if [:puma, :passenger, :rainbows, :unicorn].include? Agent.config[:dispatcher]
14
+ ::NewRelic::Agent.logger.info "Deferring startup of agent reporting thread because #{Agent.config[:dispatcher]} may fork."
15
+ true
16
+ else
17
+ false
18
+ end
19
+ end
20
+
21
+ # Return true if we're using resque and it hasn't had a chance to (potentially)
22
+ # daemonize itself. This avoids hanging when there's a Thread started
23
+ # before Resque calls Process.daemon (Jira RUBY-857)
24
+ def defer_for_resque?
25
+ NewRelic::Agent.config[:dispatcher] == :resque &&
26
+ NewRelic::Agent::Instrumentation::Resque::Helper.resque_fork_per_job? &&
27
+ !PipeChannelManager.listener.started?
28
+ end
29
+
30
+ def in_resque_child_process?
31
+ defined?(@service) && @service.is_a?(PipeService)
32
+ end
33
+
34
+ def defer_for_delayed_job?
35
+ NewRelic::Agent.config[:dispatcher] == :delayed_job &&
36
+ !NewRelic::DelayedJobInjection.worker_name
37
+ end
38
+
39
+ # This matters when the following three criteria are met:
40
+ #
41
+ # 1. A Sinatra 'classic' application is being run
42
+ # 2. The app is being run by executing the main file directly, rather
43
+ # than via a config.ru file.
44
+ # 3. newrelic_rpm is required *after* sinatra
45
+ #
46
+ # In this case, the entire application runs from an at_exit handler in
47
+ # Sinatra, and if we were to install ours, it would be executed before
48
+ # the one in Sinatra, meaning that we'd shutdown the agent too early
49
+ # and never collect any data.
50
+ def sinatra_classic_app?
51
+ (
52
+ defined?(Sinatra::Application) &&
53
+ Sinatra::Application.respond_to?(:run) &&
54
+ Sinatra::Application.run?
55
+ )
56
+ end
57
+
58
+ def should_install_exit_handler?
59
+ return false unless Agent.config[:send_data_on_exit]
60
+ !sinatra_classic_app? || Agent.config[:force_install_exit_handler]
61
+ end
62
+
63
+ def install_exit_handler
64
+ return unless should_install_exit_handler?
65
+ NewRelic::Agent.logger.debug("Installing at_exit handler")
66
+ at_exit { shutdown }
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,163 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module StartWorkerThread
8
+ LOG_ONCE_KEYS_RESET_PERIOD = 60.0
9
+
10
+ TRANSACTION_EVENT_DATA = "transaction_event_data".freeze
11
+ CUSTOM_EVENT_DATA = "custom_event_data".freeze
12
+ ERROR_EVENT_DATA = "error_event_data".freeze
13
+ SPAN_EVENT_DATA = "span_event_data".freeze
14
+ LOG_EVENT_DATA = "log_event_data".freeze
15
+
16
+ # Try to launch the worker thread and connect to the server.
17
+ #
18
+ # See #connect for a description of connection_options.
19
+ def start_worker_thread(connection_options = {})
20
+ if disable = NewRelic::Agent.config[:disable_harvest_thread]
21
+ NewRelic::Agent.logger.info "Not starting Ruby Agent worker thread because :disable_harvest_thread is #{disable}"
22
+ return
23
+ end
24
+
25
+ ::NewRelic::Agent.logger.debug "Creating Ruby Agent worker thread."
26
+ @worker_thread = Threading::AgentThread.create('Worker Loop') do
27
+ deferred_work!(connection_options)
28
+ end
29
+ end
30
+
31
+ def create_event_loop
32
+ EventLoop.new
33
+ end
34
+
35
+ # If the @worker_thread encounters an error during the attempt to connect to the collector
36
+ # then the connect attempts enter an exponential backoff retry loop. To avoid potential
37
+ # race conditions with shutting down while also attempting to reconnect, we join the
38
+ # @worker_thread with a timeout threshold. This allows potentially connecting and flushing
39
+ # pending data to the server, but without waiting indefinitely for a reconnect to succeed.
40
+ # The use-case where this typically arises is in cronjob scheduled rake tasks where there's
41
+ # also some network stability/latency issues happening.
42
+ def stop_event_loop
43
+ @event_loop.stop if @event_loop
44
+ # Wait the end of the event loop thread.
45
+ if @worker_thread
46
+ unless @worker_thread.join(3)
47
+ ::NewRelic::Agent.logger.debug "Event loop thread did not stop within 3 seconds"
48
+ end
49
+ end
50
+ end
51
+
52
+ # Certain event types may sometimes need to be on the same interval as metrics,
53
+ # so we will check config assigned in EventHarvestConfig to determine the interval
54
+ # on which to report them
55
+ def interval_for event_type
56
+ interval = Agent.config[:"event_report_period.#{event_type}"]
57
+ :"#{interval}_second_harvest"
58
+ end
59
+
60
+ def create_and_run_event_loop
61
+ data_harvest = :"#{Agent.config[:data_report_period]}_second_harvest"
62
+ event_harvest = :"#{Agent.config[:event_report_period]}_second_harvest"
63
+
64
+ @event_loop = create_event_loop
65
+ @event_loop.on(data_harvest) do
66
+ transmit_data
67
+ end
68
+
69
+ @event_loop.on(interval_for TRANSACTION_EVENT_DATA) do
70
+ transmit_analytic_event_data
71
+ end
72
+ @event_loop.on(interval_for CUSTOM_EVENT_DATA) do
73
+ transmit_custom_event_data
74
+ end
75
+ @event_loop.on(interval_for ERROR_EVENT_DATA) do
76
+ transmit_error_event_data
77
+ end
78
+ @event_loop.on(interval_for SPAN_EVENT_DATA) do
79
+ transmit_span_event_data
80
+ end
81
+ @event_loop.on(interval_for LOG_EVENT_DATA) do
82
+ transmit_log_event_data
83
+ end
84
+
85
+ @event_loop.on(:reset_log_once_keys) do
86
+ ::NewRelic::Agent.logger.clear_already_logged
87
+ end
88
+ @event_loop.fire_every(Agent.config[:data_report_period], data_harvest)
89
+ @event_loop.fire_every(Agent.config[:event_report_period], event_harvest)
90
+ @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
91
+
92
+ @event_loop.run
93
+ end
94
+
95
+ # Handles the case where the server tells us to restart -
96
+ # this clears the data, clears connection attempts, and
97
+ # waits a while to reconnect.
98
+ def handle_force_restart(error)
99
+ ::NewRelic::Agent.logger.debug error.message
100
+ drop_buffered_data
101
+ @service.force_restart if @service
102
+ @connect_state = :pending
103
+ sleep 30
104
+ end
105
+
106
+ # when a disconnect is requested, stop the current thread, which
107
+ # is the worker thread that gathers data and talks to the
108
+ # server.
109
+ def handle_force_disconnect(error)
110
+ ::NewRelic::Agent.logger.warn "Agent received a ForceDisconnectException from the server, disconnecting. (#{error.message})"
111
+ disconnect
112
+ end
113
+
114
+ # Handles an unknown error in the worker thread by logging
115
+ # it and disconnecting the agent, since we are now in an
116
+ # unknown state.
117
+ def handle_other_error(error)
118
+ ::NewRelic::Agent.logger.error "Unhandled error in worker thread, disconnecting."
119
+ # These errors are fatal (that is, they will prevent the agent from
120
+ # reporting entirely), so we really want backtraces when they happen
121
+ ::NewRelic::Agent.logger.log_exception(:error, error)
122
+ disconnect
123
+ end
124
+
125
+ # a wrapper method to handle all the errors that can happen
126
+ # in the connection and worker thread system. This
127
+ # guarantees a no-throw from the background thread.
128
+ def catch_errors
129
+ yield
130
+ rescue NewRelic::Agent::ForceRestartException => e
131
+ handle_force_restart(e)
132
+ retry
133
+ rescue NewRelic::Agent::ForceDisconnectException => e
134
+ handle_force_disconnect(e)
135
+ rescue => e
136
+ handle_other_error(e)
137
+ end
138
+
139
+ # This is the method that is run in a new thread in order to
140
+ # background the harvesting and sending of data during the
141
+ # normal operation of the agent.
142
+ #
143
+ # Takes connection options that determine how we should
144
+ # connect to the server, and loops endlessly - typically we
145
+ # never return from this method unless we're shutting down
146
+ # the agent
147
+ def deferred_work!(connection_options)
148
+ catch_errors do
149
+ NewRelic::Agent.disable_all_tracing do
150
+ connect(connection_options)
151
+ if connected?
152
+ create_and_run_event_loop
153
+ # never reaches here unless there is a problem or
154
+ # the agent is exiting
155
+ else
156
+ ::NewRelic::Agent.logger.debug "No connection. Worker thread ending."
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,196 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module Startup
8
+ # True if we have initialized and completed 'start'
9
+ def started?
10
+ @started
11
+ end
12
+
13
+ # Check whether we have already started, which is an error condition
14
+ def already_started?
15
+ if started?
16
+ ::NewRelic::Agent.logger.error("Agent Started Already!")
17
+ true
18
+ end
19
+ end
20
+
21
+ # Logs a bunch of data and starts the agent, if needed
22
+ def start
23
+ return unless agent_should_start?
24
+
25
+ log_startup
26
+ check_config_and_start_agent
27
+ log_version_and_pid
28
+
29
+ events.subscribe(:initial_configuration_complete) do
30
+ log_ignore_url_regexes
31
+ end
32
+ end
33
+
34
+ # Sanity-check the agent configuration and start the agent,
35
+ # setting up the worker thread and the exit handler to shut
36
+ # down the agent
37
+ def check_config_and_start_agent
38
+ return unless monitoring? && has_correct_license_key?
39
+ return if using_forking_dispatcher?
40
+ setup_and_start_agent
41
+ end
42
+
43
+ # This is the shared method between the main agent startup and the
44
+ # after_fork call restarting the thread in deferred dispatchers.
45
+ #
46
+ # Treatment of @started and env report is important to get right.
47
+ def setup_and_start_agent(options = {})
48
+ @started = true
49
+ @harvester.mark_started
50
+
51
+ unless in_resque_child_process?
52
+ install_exit_handler
53
+ environment_for_connect
54
+ @harvest_samplers.load_samplers unless Agent.config[:disable_samplers]
55
+ end
56
+
57
+ connect_in_foreground if Agent.config[:sync_startup]
58
+ start_worker_thread(options)
59
+ end
60
+
61
+ # Log startup information that we almost always want to know
62
+ def log_startup
63
+ log_environment
64
+ log_dispatcher
65
+ log_app_name
66
+ end
67
+
68
+ # Log the environment the app thinks it's running in.
69
+ # Useful in debugging, as this is the key for config YAML lookups.
70
+ def log_environment
71
+ ::NewRelic::Agent.logger.info "Environment: #{NewRelic::Control.instance.env}"
72
+ end
73
+
74
+ # Logs the dispatcher to the log file to assist with
75
+ # debugging. When no debugger is present, logs this fact to
76
+ # assist with proper dispatcher detection
77
+ def log_dispatcher
78
+ dispatcher_name = Agent.config[:dispatcher].to_s
79
+
80
+ if dispatcher_name.empty?
81
+ ::NewRelic::Agent.logger.info 'No known dispatcher detected.'
82
+ else
83
+ ::NewRelic::Agent.logger.info "Dispatcher: #{dispatcher_name}"
84
+ end
85
+ end
86
+
87
+ def log_app_name
88
+ ::NewRelic::Agent.logger.info "Application: #{Agent.config[:app_name].join(", ")}"
89
+ end
90
+
91
+ def log_ignore_url_regexes
92
+ regexes = NewRelic::Agent.config[:'rules.ignore_url_regexes']
93
+
94
+ unless regexes.empty?
95
+ ::NewRelic::Agent.logger.info "Ignoring URLs that match the following regexes: #{regexes.map(&:inspect).join(", ")}."
96
+ end
97
+ end
98
+
99
+ # Classy logging of the agent version and the current pid,
100
+ # so we can disambiguate processes in the log file and make
101
+ # sure they're running a reasonable version
102
+ def log_version_and_pid
103
+ ::NewRelic::Agent.logger.debug "New Relic Ruby Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}"
104
+ end
105
+
106
+ # Logs the configured application names
107
+ def app_name_configured?
108
+ names = Agent.config[:app_name]
109
+ return names.respond_to?(:any?) && names.any?
110
+ end
111
+
112
+ # Connecting in the foreground blocks further startup of the
113
+ # agent until we have a connection - useful in cases where
114
+ # you're trying to log a very-short-running process and want
115
+ # to get statistics from before a server connection
116
+ # (typically 20 seconds) exists
117
+ def connect_in_foreground
118
+ NewRelic::Agent.disable_all_tracing { connect(:keep_retrying => false) }
119
+ end
120
+
121
+ # Warn the user if they have configured their agent not to
122
+ # send data, that way we can see this clearly in the log file
123
+ def monitoring?
124
+ if Agent.config[:monitor_mode]
125
+ true
126
+ else
127
+ ::NewRelic::Agent.logger.warn('Agent configured not to send data in this environment.')
128
+ false
129
+ end
130
+ end
131
+
132
+ # Tell the user when the license key is missing so they can
133
+ # fix it by adding it to the file
134
+ def has_license_key?
135
+ if Agent.config[:license_key] && Agent.config[:license_key].length > 0
136
+ true
137
+ else
138
+ ::NewRelic::Agent.logger.warn("No license key found. " +
139
+ "This often means your newrelic.yml file was not found, or it lacks a section for the running environment, '#{NewRelic::Control.instance.env}'. You may also want to try linting your newrelic.yml to ensure it is valid YML.")
140
+ false
141
+ end
142
+ end
143
+
144
+ # A correct license key exists and is of the proper length
145
+ def has_correct_license_key?
146
+ has_license_key? && correct_license_length
147
+ end
148
+
149
+ # A license key is an arbitrary 40 character string,
150
+ # usually looks something like a SHA1 hash
151
+ def correct_license_length
152
+ key = Agent.config[:license_key]
153
+
154
+ if key.length == 40
155
+ true
156
+ else
157
+ ::NewRelic::Agent.logger.error("Invalid license key: #{key}")
158
+ false
159
+ end
160
+ end
161
+
162
+ # Check to see if the agent should start, returning +true+ if it should.
163
+ def agent_should_start?
164
+ return false if already_started? || disabled?
165
+
166
+ if defer_for_delayed_job?
167
+ ::NewRelic::Agent.logger.debug "Deferring startup for DelayedJob"
168
+ return false
169
+ end
170
+
171
+ if defer_for_resque?
172
+ ::NewRelic::Agent.logger.debug "Deferring startup for Resque in case it daemonizes"
173
+ return false
174
+ end
175
+
176
+ unless app_name_configured?
177
+ NewRelic::Agent.logger.error "No application name configured.",
178
+ "The Agent cannot start without at least one. Please check your ",
179
+ "newrelic.yml and ensure that it is valid and has at least one ",
180
+ "value set for app_name in the #{NewRelic::Control.instance.env} ",
181
+ "environment."
182
+ return false
183
+ end
184
+
185
+ return true
186
+ end
187
+
188
+ # The agent is disabled when it is not force enabled by the
189
+ # 'agent_enabled' option (e.g. in a manual start), or
190
+ # enabled normally through the configuration file
191
+ def disabled?
192
+ !Agent.config[:agent_enabled]
193
+ end
194
+ end
195
+ end
196
+ end