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
@@ -37,6 +37,11 @@ require 'new_relic/agent/adaptive_sampler'
37
37
  require 'new_relic/agent/connect/request_builder'
38
38
  require 'new_relic/agent/connect/response_handler'
39
39
 
40
+ require 'new_relic/agent/agent/start_worker_thread'
41
+ require 'new_relic/agent/agent/startup'
42
+ require 'new_relic/agent/agent/special_startup'
43
+ require 'new_relic/agent/agent/shutdown'
44
+
40
45
  module NewRelic
41
46
  module Agent
42
47
  # The Agent is a singleton that is instantiated when the plugin is
@@ -48,6 +53,11 @@ module NewRelic
48
53
  ::NewRelic::Agent.config
49
54
  end
50
55
 
56
+ include NewRelic::Agent::StartWorkerThread
57
+ include NewRelic::Agent::SpecialStartup
58
+ include NewRelic::Agent::Startup
59
+ include NewRelic::Agent::Shutdown
60
+
51
61
  def initialize
52
62
  @started = false
53
63
  @event_loop = nil
@@ -222,48 +232,11 @@ module NewRelic
222
232
  end
223
233
  end
224
234
 
225
- # True if we have initialized and completed 'start'
226
- def started?
227
- @started
228
- end
229
-
230
- # Attempt a graceful shutdown of the agent, flushing any remaining
231
- # data.
232
- def shutdown
233
- return unless started?
234
- ::NewRelic::Agent.logger.info "Starting Agent shutdown"
235
-
236
- stop_event_loop
237
- trap_signals_for_litespeed
238
- untraced_graceful_disconnect
239
- revert_to_default_configuration
240
-
241
- @started = nil
242
- Control.reset
243
- end
244
-
245
235
  def revert_to_default_configuration
246
236
  Agent.config.remove_config_type(:manual)
247
237
  Agent.config.remove_config_type(:server)
248
238
  end
249
239
 
250
- # If the @worker_thread encounters an error during the attempt to connect to the collector
251
- # then the connect attempts enter an exponential backoff retry loop. To avoid potential
252
- # race conditions with shutting down while also attempting to reconnect, we join the
253
- # @worker_thread with a timeout threshold. This allows potentially connecting and flushing
254
- # pending data to the server, but without waiting indefinitely for a reconnect to succeed.
255
- # The use-case where this typically arises is in cronjob scheduled rake tasks where there's
256
- # also some network stability/latency issues happening.
257
- def stop_event_loop
258
- @event_loop.stop if @event_loop
259
- # Wait the end of the event loop thread.
260
- if @worker_thread
261
- unless @worker_thread.join(3)
262
- ::NewRelic::Agent.logger.debug "Event loop thread did not stop within 3 seconds"
263
- end
264
- end
265
- end
266
-
267
240
  def trap_signals_for_litespeed
268
241
  # if litespeed, then ignore all future SIGUSR1 - it's
269
242
  # litespeed trying to shut us down
@@ -273,16 +246,6 @@ module NewRelic
273
246
  end
274
247
  end
275
248
 
276
- def untraced_graceful_disconnect
277
- begin
278
- NewRelic::Agent.disable_all_tracing do
279
- graceful_disconnect
280
- end
281
- rescue => e
282
- ::NewRelic::Agent.logger.error e
283
- end
284
- end
285
-
286
249
  # Sets a thread local variable as to whether we should or
287
250
  # should not record sql in the current thread. Returns the
288
251
  # previous value, if there is one
@@ -307,255 +270,6 @@ module NewRelic
307
270
  Tracer.state.pop_traced
308
271
  end
309
272
 
310
- # Herein lies the corpse of the former 'start' method. May
311
- # its unmatched flog score rest in pieces.
312
- module Start
313
- # Check whether we have already started, which is an error condition
314
- def already_started?
315
- if started?
316
- ::NewRelic::Agent.logger.error("Agent Started Already!")
317
- true
318
- end
319
- end
320
-
321
- # The agent is disabled when it is not force enabled by the
322
- # 'agent_enabled' option (e.g. in a manual start), or
323
- # enabled normally through the configuration file
324
- def disabled?
325
- !Agent.config[:agent_enabled]
326
- end
327
-
328
- # Log startup information that we almost always want to know
329
- def log_startup
330
- log_environment
331
- log_dispatcher
332
- log_app_name
333
- end
334
-
335
- # Log the environment the app thinks it's running in.
336
- # Useful in debugging, as this is the key for config YAML lookups.
337
- def log_environment
338
- ::NewRelic::Agent.logger.info "Environment: #{NewRelic::Control.instance.env}"
339
- end
340
-
341
- # Logs the dispatcher to the log file to assist with
342
- # debugging. When no debugger is present, logs this fact to
343
- # assist with proper dispatcher detection
344
- def log_dispatcher
345
- dispatcher_name = Agent.config[:dispatcher].to_s
346
-
347
- if dispatcher_name.empty?
348
- ::NewRelic::Agent.logger.info 'No known dispatcher detected.'
349
- else
350
- ::NewRelic::Agent.logger.info "Dispatcher: #{dispatcher_name}"
351
- end
352
- end
353
-
354
- def log_app_name
355
- ::NewRelic::Agent.logger.info "Application: #{Agent.config[:app_name].join(", ")}"
356
- end
357
-
358
- def log_ignore_url_regexes
359
- regexes = NewRelic::Agent.config[:'rules.ignore_url_regexes']
360
-
361
- unless regexes.empty?
362
- ::NewRelic::Agent.logger.info "Ignoring URLs that match the following regexes: #{regexes.map(&:inspect).join(", ")}."
363
- end
364
- end
365
-
366
- # Logs the configured application names
367
- def app_name_configured?
368
- names = Agent.config[:app_name]
369
- return names.respond_to?(:any?) && names.any?
370
- end
371
-
372
- # Connecting in the foreground blocks further startup of the
373
- # agent until we have a connection - useful in cases where
374
- # you're trying to log a very-short-running process and want
375
- # to get statistics from before a server connection
376
- # (typically 20 seconds) exists
377
- def connect_in_foreground
378
- NewRelic::Agent.disable_all_tracing { connect(:keep_retrying => false) }
379
- end
380
-
381
- # This matters when the following three criteria are met:
382
- #
383
- # 1. A Sinatra 'classic' application is being run
384
- # 2. The app is being run by executing the main file directly, rather
385
- # than via a config.ru file.
386
- # 3. newrelic_rpm is required *after* sinatra
387
- #
388
- # In this case, the entire application runs from an at_exit handler in
389
- # Sinatra, and if we were to install ours, it would be executed before
390
- # the one in Sinatra, meaning that we'd shutdown the agent too early
391
- # and never collect any data.
392
- def sinatra_classic_app?
393
- (
394
- defined?(Sinatra::Application) &&
395
- Sinatra::Application.respond_to?(:run) &&
396
- Sinatra::Application.run?
397
- )
398
- end
399
-
400
- def should_install_exit_handler?
401
- return false unless Agent.config[:send_data_on_exit]
402
- !sinatra_classic_app? || Agent.config[:force_install_exit_handler]
403
- end
404
-
405
- def install_exit_handler
406
- return unless should_install_exit_handler?
407
- NewRelic::Agent.logger.debug("Installing at_exit handler")
408
- at_exit { shutdown }
409
- end
410
-
411
- # Classy logging of the agent version and the current pid,
412
- # so we can disambiguate processes in the log file and make
413
- # sure they're running a reasonable version
414
- def log_version_and_pid
415
- ::NewRelic::Agent.logger.debug "New Relic Ruby Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}"
416
- end
417
-
418
- # Warn the user if they have configured their agent not to
419
- # send data, that way we can see this clearly in the log file
420
- def monitoring?
421
- if Agent.config[:monitor_mode]
422
- true
423
- else
424
- ::NewRelic::Agent.logger.warn('Agent configured not to send data in this environment.')
425
- false
426
- end
427
- end
428
-
429
- # Tell the user when the license key is missing so they can
430
- # fix it by adding it to the file
431
- def has_license_key?
432
- if Agent.config[:license_key] && Agent.config[:license_key].length > 0
433
- true
434
- else
435
- ::NewRelic::Agent.logger.warn("No license key found. " +
436
- "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.")
437
- false
438
- end
439
- end
440
-
441
- # A correct license key exists and is of the proper length
442
- def has_correct_license_key?
443
- has_license_key? && correct_license_length
444
- end
445
-
446
- # A license key is an arbitrary 40 character string,
447
- # usually looks something like a SHA1 hash
448
- def correct_license_length
449
- key = Agent.config[:license_key]
450
-
451
- if key.length == 40
452
- true
453
- else
454
- ::NewRelic::Agent.logger.error("Invalid license key: #{key}")
455
- false
456
- end
457
- end
458
-
459
- # If we're using a dispatcher that forks before serving
460
- # requests, we need to wait until the children are forked
461
- # before connecting, otherwise the parent process sends useless data
462
- def using_forking_dispatcher?
463
- # TODO: MAJOR VERSION - remove :rainbows
464
- if [:puma, :passenger, :rainbows, :unicorn].include? Agent.config[:dispatcher]
465
- ::NewRelic::Agent.logger.info "Deferring startup of agent reporting thread because #{Agent.config[:dispatcher]} may fork."
466
- true
467
- else
468
- false
469
- end
470
- end
471
-
472
- # Return true if we're using resque and it hasn't had a chance to (potentially)
473
- # daemonize itself. This avoids hanging when there's a Thread started
474
- # before Resque calls Process.daemon (Jira RUBY-857)
475
- def defer_for_resque?
476
- NewRelic::Agent.config[:dispatcher] == :resque &&
477
- NewRelic::Agent::Instrumentation::Resque::Helper.resque_fork_per_job? &&
478
- !PipeChannelManager.listener.started?
479
- end
480
-
481
- def in_resque_child_process?
482
- defined?(@service) && @service.is_a?(PipeService)
483
- end
484
-
485
- # Sanity-check the agent configuration and start the agent,
486
- # setting up the worker thread and the exit handler to shut
487
- # down the agent
488
- def check_config_and_start_agent
489
- return unless monitoring? && has_correct_license_key?
490
- return if using_forking_dispatcher?
491
- setup_and_start_agent
492
- end
493
-
494
- # This is the shared method between the main agent startup and the
495
- # after_fork call restarting the thread in deferred dispatchers.
496
- #
497
- # Treatment of @started and env report is important to get right.
498
- def setup_and_start_agent(options = {})
499
- @started = true
500
- @harvester.mark_started
501
-
502
- unless in_resque_child_process?
503
- install_exit_handler
504
- environment_for_connect
505
- @harvest_samplers.load_samplers unless Agent.config[:disable_samplers]
506
- end
507
-
508
- connect_in_foreground if Agent.config[:sync_startup]
509
- start_worker_thread(options)
510
- end
511
- end
512
-
513
- include Start
514
-
515
- def defer_for_delayed_job?
516
- NewRelic::Agent.config[:dispatcher] == :delayed_job &&
517
- !NewRelic::DelayedJobInjection.worker_name
518
- end
519
-
520
- # Check to see if the agent should start, returning +true+ if it should.
521
- def agent_should_start?
522
- return false if already_started? || disabled?
523
-
524
- if defer_for_delayed_job?
525
- ::NewRelic::Agent.logger.debug "Deferring startup for DelayedJob"
526
- return false
527
- end
528
-
529
- if defer_for_resque?
530
- ::NewRelic::Agent.logger.debug "Deferring startup for Resque in case it daemonizes"
531
- return false
532
- end
533
-
534
- unless app_name_configured?
535
- NewRelic::Agent.logger.error "No application name configured.",
536
- "The Agent cannot start without at least one. Please check your ",
537
- "newrelic.yml and ensure that it is valid and has at least one ",
538
- "value set for app_name in the #{NewRelic::Control.instance.env} ",
539
- "environment."
540
- return false
541
- end
542
-
543
- return true
544
- end
545
-
546
- # Logs a bunch of data and starts the agent, if needed
547
- def start
548
- return unless agent_should_start?
549
-
550
- log_startup
551
- check_config_and_start_agent
552
- log_version_and_pid
553
-
554
- events.subscribe(:initial_configuration_complete) do
555
- log_ignore_url_regexes
556
- end
557
- end
558
-
559
273
  # Clear out the metric data, errors, and transaction traces, etc.
560
274
  def drop_buffered_data
561
275
  @stats_engine.reset!
@@ -592,149 +306,6 @@ module NewRelic
592
306
 
593
307
  private
594
308
 
595
- # All of this module used to be contained in the
596
- # start_worker_thread method - this is an artifact of
597
- # refactoring and can be moved, renamed, etc at will
598
- module StartWorkerThread
599
- def create_event_loop
600
- EventLoop.new
601
- end
602
-
603
- LOG_ONCE_KEYS_RESET_PERIOD = 60.0
604
-
605
- # Certain event types may sometimes need to be on the same interval as metrics,
606
- # so we will check config assigned in EventHarvestConfig to determine the interval
607
- # on which to report them
608
- def interval_for event_type
609
- interval = Agent.config[:"event_report_period.#{event_type}"]
610
- :"#{interval}_second_harvest"
611
- end
612
-
613
- TRANSACTION_EVENT_DATA = "transaction_event_data".freeze
614
- CUSTOM_EVENT_DATA = "custom_event_data".freeze
615
- ERROR_EVENT_DATA = "error_event_data".freeze
616
- SPAN_EVENT_DATA = "span_event_data".freeze
617
- LOG_EVENT_DATA = "log_event_data".freeze
618
-
619
- def create_and_run_event_loop
620
- data_harvest = :"#{Agent.config[:data_report_period]}_second_harvest"
621
- event_harvest = :"#{Agent.config[:event_report_period]}_second_harvest"
622
-
623
- @event_loop = create_event_loop
624
- @event_loop.on(data_harvest) do
625
- transmit_data
626
- end
627
-
628
- @event_loop.on(interval_for TRANSACTION_EVENT_DATA) do
629
- transmit_analytic_event_data
630
- end
631
- @event_loop.on(interval_for CUSTOM_EVENT_DATA) do
632
- transmit_custom_event_data
633
- end
634
- @event_loop.on(interval_for ERROR_EVENT_DATA) do
635
- transmit_error_event_data
636
- end
637
- @event_loop.on(interval_for SPAN_EVENT_DATA) do
638
- transmit_span_event_data
639
- end
640
- @event_loop.on(interval_for LOG_EVENT_DATA) do
641
- transmit_log_event_data
642
- end
643
-
644
- @event_loop.on(:reset_log_once_keys) do
645
- ::NewRelic::Agent.logger.clear_already_logged
646
- end
647
- @event_loop.fire_every(Agent.config[:data_report_period], data_harvest)
648
- @event_loop.fire_every(Agent.config[:event_report_period], event_harvest)
649
- @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
650
-
651
- @event_loop.run
652
- end
653
-
654
- # Handles the case where the server tells us to restart -
655
- # this clears the data, clears connection attempts, and
656
- # waits a while to reconnect.
657
- def handle_force_restart(error)
658
- ::NewRelic::Agent.logger.debug error.message
659
- drop_buffered_data
660
- @service.force_restart if @service
661
- @connect_state = :pending
662
- sleep 30
663
- end
664
-
665
- # when a disconnect is requested, stop the current thread, which
666
- # is the worker thread that gathers data and talks to the
667
- # server.
668
- def handle_force_disconnect(error)
669
- ::NewRelic::Agent.logger.warn "Agent received a ForceDisconnectException from the server, disconnecting. (#{error.message})"
670
- disconnect
671
- end
672
-
673
- # Handles an unknown error in the worker thread by logging
674
- # it and disconnecting the agent, since we are now in an
675
- # unknown state.
676
- def handle_other_error(error)
677
- ::NewRelic::Agent.logger.error "Unhandled error in worker thread, disconnecting."
678
- # These errors are fatal (that is, they will prevent the agent from
679
- # reporting entirely), so we really want backtraces when they happen
680
- ::NewRelic::Agent.logger.log_exception(:error, error)
681
- disconnect
682
- end
683
-
684
- # a wrapper method to handle all the errors that can happen
685
- # in the connection and worker thread system. This
686
- # guarantees a no-throw from the background thread.
687
- def catch_errors
688
- yield
689
- rescue NewRelic::Agent::ForceRestartException => e
690
- handle_force_restart(e)
691
- retry
692
- rescue NewRelic::Agent::ForceDisconnectException => e
693
- handle_force_disconnect(e)
694
- rescue => e
695
- handle_other_error(e)
696
- end
697
-
698
- # This is the method that is run in a new thread in order to
699
- # background the harvesting and sending of data during the
700
- # normal operation of the agent.
701
- #
702
- # Takes connection options that determine how we should
703
- # connect to the server, and loops endlessly - typically we
704
- # never return from this method unless we're shutting down
705
- # the agent
706
- def deferred_work!(connection_options)
707
- catch_errors do
708
- NewRelic::Agent.disable_all_tracing do
709
- connect(connection_options)
710
- if connected?
711
- create_and_run_event_loop
712
- # never reaches here unless there is a problem or
713
- # the agent is exiting
714
- else
715
- ::NewRelic::Agent.logger.debug "No connection. Worker thread ending."
716
- end
717
- end
718
- end
719
- end
720
- end
721
- include StartWorkerThread
722
-
723
- # Try to launch the worker thread and connect to the server.
724
- #
725
- # See #connect for a description of connection_options.
726
- def start_worker_thread(connection_options = {})
727
- if disable = NewRelic::Agent.config[:disable_harvest_thread]
728
- NewRelic::Agent.logger.info "Not starting Ruby Agent worker thread because :disable_harvest_thread is #{disable}"
729
- return
730
- end
731
-
732
- ::NewRelic::Agent.logger.debug "Creating Ruby Agent worker thread."
733
- @worker_thread = Threading::AgentThread.create('Worker Loop') do
734
- deferred_work!(connection_options)
735
- end
736
- end
737
-
738
309
  # A shorthand for NewRelic::Control.instance
739
310
  def control
740
311
  NewRelic::Control.instance
@@ -83,11 +83,9 @@ module NewRelic
83
83
  # Allows for passing exceptions in explicitly, which format with backtrace
84
84
  def format_and_send(level, *msgs, &block)
85
85
  if block
86
- if @log.send("#{level}?")
87
- msgs = Array(block.call)
88
- else
89
- msgs = []
90
- end
86
+ return unless @log.send("#{level}?")
87
+
88
+ msgs = Array(block.call)
91
89
  end
92
90
 
93
91
  msgs.flatten.each do |item|
@@ -62,7 +62,7 @@ module NewRelic
62
62
  ::Rake.application.top_level_tasks
63
63
  rescue => e
64
64
  ::NewRelic::Agent.logger.debug("Not in Rake environment so skipping denylisted_rake_tasks check: #{e}")
65
- []
65
+ NewRelic::EMPTY_ARRAY
66
66
  end
67
67
  !(tasks & ::NewRelic::Agent.config[:'autostart.denylisted_rake_tasks'].split(/\s*,\s*/)).empty?
68
68
  end
@@ -113,7 +113,7 @@ module NewRelic
113
113
  end
114
114
  end
115
115
 
116
- SUCCESS_RESULT = {}.freeze
116
+ SUCCESS_RESULT = NewRelic::EMPTY_HASH
117
117
  ERROR_KEY = "error"
118
118
 
119
119
  def success
@@ -96,11 +96,11 @@ module NewRelic
96
96
  paths << File.join(NewRelic::Control.instance.root, "newrelic.yml.erb")
97
97
  end
98
98
 
99
- if ENV["HOME"]
100
- paths << File.join(ENV["HOME"], ".newrelic", "newrelic.yml")
101
- paths << File.join(ENV["HOME"], "newrelic.yml")
102
- paths << File.join(ENV["HOME"], ".newrelic", "newrelic.yml.erb")
103
- paths << File.join(ENV["HOME"], "newrelic.yml.erb")
99
+ if ENV['HOME']
100
+ paths << File.join(ENV['HOME'], ".newrelic", "newrelic.yml")
101
+ paths << File.join(ENV['HOME'], "newrelic.yml")
102
+ paths << File.join(ENV['HOME'], ".newrelic", "newrelic.yml.erb")
103
+ paths << File.join(ENV['HOME'], "newrelic.yml.erb")
104
104
  end
105
105
 
106
106
  # If we're packaged for warbler, we can tell from GEM_HOME
@@ -119,7 +119,7 @@ module NewRelic
119
119
  found_path = NewRelic::Agent.config[:config_search_paths].detect do |file|
120
120
  File.expand_path(file) if File.exist? file
121
121
  end
122
- found_path || ""
122
+ found_path || NewRelic::EMPTY_STR
123
123
  }
124
124
  end
125
125
 
@@ -242,7 +242,7 @@ module NewRelic
242
242
  case value
243
243
  when Array then value
244
244
  when String then value.split(SEMICOLON)
245
- else []
245
+ else NewRelic::EMPTY_ARRAY
246
246
  end
247
247
  end
248
248
 
@@ -517,9 +517,9 @@ When `true`, the agent captures HTTP request parameters and attaches them to tra
517
517
  :allowed_from_server => false,
518
518
  :transform => DefaultSource.method(:convert_to_regexp_list),
519
519
  :description => 'Specify an Array of Rake tasks to automatically instrument. ' \
520
- 'This configuration option converts the Array to a RegEx list. If you\'d like '\
521
- 'to allow all tasks by default, use `rake.tasks: [.+]`. No rake tasks will be '\
522
- 'instrumented unless they\'re added to this list. For more information, '\
520
+ 'This configuration option converts the Array to a RegEx list. If you\'d like ' \
521
+ 'to allow all tasks by default, use `rake.tasks: [.+]`. No rake tasks will be ' \
522
+ 'instrumented unless they\'re added to this list. For more information, ' \
523
523
  'visit the (New Relic Rake Instrumentation docs)[/docs/apm/agents/ruby-agent/background-jobs/rake-instrumentation].'
524
524
  },
525
525
  :'rake.connect_timeout' => {
@@ -253,7 +253,7 @@ module NewRelic
253
253
  end
254
254
  rescue => e
255
255
  NewRelic::Agent.logger.error(PARSING_LABELS_FAILURE, e)
256
- []
256
+ NewRelic::EMPTY_ARRAY
257
257
  end
258
258
 
259
259
  def parse_labels_from_string
@@ -293,7 +293,7 @@ module NewRelic
293
293
 
294
294
  unless valid_label_pairs?(pairs)
295
295
  NewRelic::Agent.logger.warn("#{MALFORMED_LABELS_WARNING}: #{labels || pairs}")
296
- return []
296
+ return NewRelic::EMPTY_ARRAY
297
297
  end
298
298
 
299
299
  pairs = limit_number_of_labels(pairs)
@@ -41,7 +41,7 @@ module NewRelic
41
41
  # particular) that can't seralize to JSON. Cope with that here and
42
42
  # clear out so downstream code doesn't have to check again.
43
43
  def sanitize_environment_report(environment_report)
44
- return [] unless @service.valid_to_marshal?(environment_report)
44
+ return NewRelic::EMPTY_ARRAY unless @service.valid_to_marshal?(environment_report)
45
45
  environment_report
46
46
  end
47
47
 
@@ -115,7 +115,7 @@ module NewRelic
115
115
  end
116
116
 
117
117
  SPACE = ' '.freeze
118
- EMPTY = [].freeze
118
+ EMPTY = NewRelic::EMPTY_ARRAY
119
119
 
120
120
  def split_name(name)
121
121
  if name && name.respond_to?(:split)
@@ -48,7 +48,7 @@ module NewRelic
48
48
  NR_DO_NOT_TRACE_KEY = :'@do_not_trace'
49
49
  NR_IGNORE_APDEX_KEY = :'@ignore_apdex'
50
50
  NR_IGNORE_ENDUSER_KEY = :'@ignore_enduser'
51
- NR_DEFAULT_OPTIONS = {}.freeze
51
+ NR_DEFAULT_OPTIONS = NewRelic::EMPTY_HASH
52
52
 
53
53
  # @api public
54
54
  module ClassMethods
@@ -58,10 +58,18 @@ module NewRelic
58
58
  ::Dalli::Server
59
59
  end.class_eval do
60
60
  include NewRelic::Agent::Instrumentation::Memcache::Tracer
61
- alias_method :send_multiget_without_newrelic_trace, :send_multiget
62
61
 
63
- def send_multiget keys
64
- send_multiget_with_newrelic_tracing(keys) { send_multiget_without_newrelic_trace keys }
62
+ # TODO: Dalli - 3.1.0 renamed send_multiget to piplined_get, but the method is otherwise the same
63
+ if Gem::Version.new(::Dalli::VERSION) >= Gem::Version.new('3.1.0')
64
+ alias_method :pipelined_get_without_newrelic_trace, :pipelined_get
65
+ def pipelined_get keys
66
+ send_multiget_with_newrelic_tracing(keys) { pipelined_get_without_newrelic_trace keys }
67
+ end
68
+ else
69
+ alias_method :send_multiget_without_newrelic_trace, :send_multiget
70
+ def send_multiget keys
71
+ send_multiget_with_newrelic_tracing(keys) { send_multiget_without_newrelic_trace keys }
72
+ end
65
73
  end
66
74
  end
67
75
  end
@@ -85,8 +85,15 @@ module NewRelic::Agent::Instrumentation
85
85
  extend Helper
86
86
  include NewRelic::Agent::Instrumentation::Memcache::Tracer
87
87
 
88
- def send_multiget keys
89
- send_multiget_with_newrelic_tracing(keys) { super }
88
+ # TODO: Dalli - 3.1.0 renamed send_multiget to piplined_get, but the method is otherwise the same
89
+ if Gem::Version.new(::Dalli::VERSION) >= Gem::Version.new('3.1.0')
90
+ def pipelined_get keys
91
+ send_multiget_with_newrelic_tracing(keys) { super }
92
+ end
93
+ else
94
+ def send_multiget keys
95
+ send_multiget_with_newrelic_tracing(keys) { super }
96
+ end
90
97
  end
91
98
  end
92
99
  end
@@ -11,8 +11,8 @@ DependencyDetection.defer do
11
11
 
12
12
  executes do
13
13
  ::NewRelic::Agent.logger.info 'Installing Rails Sunspot instrumentation'
14
- deprecation_msg = 'The instrumentation for Sunspot is deprecated.' \
15
- ' It will be removed in version 9.0.0.' \
14
+ deprecation_msg = 'The instrumentation for Sunspot is deprecated. ' \
15
+ 'It will be removed in version 9.0.0.'
16
16
 
17
17
  ::NewRelic::Agent.logger.log_once(
18
18
  :warn,