Module: NewRelic::Agent::Agent::InstanceMethods::Connect

Included in:
NewRelic::Agent::Agent::InstanceMethods
Defined in:
lib/new_relic/agent/agent.rb

Overview

This module is an artifact of a refactoring of the connect method - all of its methods are used in that context, so it can be refactored at will. It should be fully tested

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#connect_attemptsObject

number of attempts we’ve made to contact the server



601
602
603
# File 'lib/new_relic/agent/agent.rb', line 601

def connect_attempts
  @connect_attempts
end

#connect_retry_periodObject

the frequency with which we should try to connect to the server at the moment.



599
600
601
# File 'lib/new_relic/agent/agent.rb', line 599

def connect_retry_period
  @connect_retry_period
end

Instance Method Details

#apdex_fObject

apdex_f is always 4 times the apdex_t



793
794
795
# File 'lib/new_relic/agent/agent.rb', line 793

def apdex_f
  (4 * NewRelic::Control.instance.apdex_t).to_f
end

#apdex_f_threshold?Boolean

If the transaction threshold is set to the string ‘apdex_f’, we use 4 times the apdex_t value to record transactions. This gears well with using apdex since you will attempt to send any transactions that register as ‘failing’

Returns:

  • (Boolean)


801
802
803
# File 'lib/new_relic/agent/agent.rb', line 801

def apdex_f_threshold?
  @transaction_sampler.config.fetch('transaction_threshold', '') =~ /apdex_f/i
end

#config_transaction_tracerObject

this entire method should be done on the transaction sampler object, rather than here. We should pass in the sampler config.



756
757
758
759
760
761
762
763
764
765
766
767
768
# File 'lib/new_relic/agent/agent.rb', line 756

def config_transaction_tracer
  # Reconfigure the transaction tracer
  @transaction_sampler.configure!
  @sql_sampler.configure!
  @should_send_samples = @config_should_send_samples = @transaction_sampler.config.fetch('enabled', true)
  @should_send_random_samples = @transaction_sampler.config.fetch('random_sample', false)
  set_sql_recording!

  # default to 2.0, string 'apdex_f' will turn into your
  # apdex * 4
  @slowest_transaction_threshold = @transaction_sampler.config.fetch('transaction_threshold', 2.0).to_f
  @slowest_transaction_threshold = apdex_f if apdex_f_threshold?
end

#configure_error_collector!(server_enabled) ⇒ Object

Configures the error collector if the server says that we are allowed to send errors. Pretty simple, and logs at debug whether errors will or will not be sent.



726
727
728
729
730
731
732
733
734
735
736
# File 'lib/new_relic/agent/agent.rb', line 726

def configure_error_collector!(server_enabled)
  # Reinitialize the error collector
  @error_collector = NewRelic::Agent::ErrorCollector.new
  # Ask for permission to collect error data
  enabled = if error_collector.config_enabled && server_enabled
              error_collector.enabled = true
            else
              error_collector.enabled = false
            end
  log.debug "Errors will #{enabled ? '' : 'not '}be sent to the New Relic service."
end

#configure_transaction_tracer!(server_enabled, sample_rate) ⇒ Object

Enables or disables the transaction tracer and sets its options based on the options provided to the method.



773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
# File 'lib/new_relic/agent/agent.rb', line 773

def configure_transaction_tracer!(server_enabled, sample_rate)
  # Ask the server for permission to send transaction samples.
  # determined by subscription license.
  @transaction_sampler.config['enabled'] = server_enabled
  @sql_sampler.configure!
  @should_send_samples = @config_should_send_samples && server_enabled
  
  if @should_send_samples
    # I don't think this is ever true, but...
    enable_random_samples!(sample_rate) if @should_send_random_samples
    
    @transaction_sampler.slow_capture_threshold = @slowest_transaction_threshold
    
    log.debug "Transaction tracing threshold is #{@slowest_transaction_threshold} seconds."
  else
    log.debug "Transaction traces will not be sent to the New Relic service."
  end
end

#connect_settingsObject

Initializes the hash of settings that we send to the server. Returns a literal hash containing the options



702
703
704
705
706
707
708
709
710
711
712
713
# File 'lib/new_relic/agent/agent.rb', line 702

def connect_settings
  {
    :pid => $$,
    :host => @local_host,
    :app_name => control.app_names,
    :language => 'ruby',
    :agent_version => NewRelic::VERSION::STRING,
    :environment => environment_for_connect,
    :settings => control.settings,
    :validate => validate_settings
  }
end

#connect_to_serverObject

Does some simple logging to make sure that our seed and token for verification are correct, then returns the connect data passed back from the server



718
719
720
721
# File 'lib/new_relic/agent/agent.rb', line 718

def connect_to_server
  log_seed_token
  connect_data = invoke_remote(:connect, connect_settings)
end

#disconnectObject

Disconnect just sets connected to false, which prevents the agent from trying to connect again



605
606
607
608
# File 'lib/new_relic/agent/agent.rb', line 605

def disconnect
  @connected = false
  true
end

#enable_random_samples!(sample_rate) ⇒ Object

Random sampling is enabled based on a sample rate, which is the n in “every 1/n transactions is added regardless of its length”.

uses a sane default for sampling rate if the sampling rate is zero, since the collector currently sends ‘0’ as a sampling rate for all accounts, which is probably for legacy reasons



746
747
748
749
750
751
# File 'lib/new_relic/agent/agent.rb', line 746

def enable_random_samples!(sample_rate)
  sample_rate = 10 unless sample_rate.to_i > 0
  @transaction_sampler.random_sampling = true
  @transaction_sampler.sampling_rate = sample_rate
  log.info "Transaction sampling enabled, rate = #{@transaction_sampler.sampling_rate}"
end

#environment_for_connectObject

Checks whether we should send environment info, and if so, returns the snapshot from the local environment



685
686
687
# File 'lib/new_relic/agent/agent.rb', line 685

def environment_for_connect
  control['send_environment_info'] != false ? control.local_env.snapshot : []
end

#finish_setup(config_data) ⇒ Object

Takes a hash of configuration data returned from the server and uses it to set local variables and to initialize various parts of the agent that are configured separately.

Can accommodate most arbitrary data - anything extra is ignored unless we say to do something with it here.



859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
# File 'lib/new_relic/agent/agent.rb', line 859

def finish_setup(config_data)
  @agent_id = config_data['agent_run_id']
  @report_period = config_data['data_report_period']
  @url_rules = config_data['url_rules']
  @beacon_configuration = BeaconConfiguration.new(config_data)
  @server_side_config_enabled = config_data['listen_to_server_config']

  if @server_side_config_enabled
    log.info "Using config from server"
    log.debug "Server provided config: #{config_data.inspect}"
  end

  control.merge_server_side_config(config_data) if @server_side_config_enabled
  config_transaction_tracer
  log_connection!(config_data)
  configure_transaction_tracer!(config_data['collect_traces'], config_data['sample_rate'])
  configure_error_collector!(config_data['collect_errors'])
end

#get_retry_periodObject

Retry period is a minute for each failed attempt that we’ve made. This should probably do some sort of sane TCP backoff to prevent hammering the server, but a minute for each attempt seems to work reasonably well.



627
628
629
630
# File 'lib/new_relic/agent/agent.rb', line 627

def get_retry_period
  return 600 if self.connect_attempts > 6
  connect_attempts * 60
end

#handle_license_error(error) ⇒ Object

When the server sends us an error with the license key, we want to tell the user that something went wrong, and let them know where to go to get a valid license key

After this runs, it disconnects the agent so that it will no longer try to connect to the server, saving the application and the server load



668
669
670
671
672
# File 'lib/new_relic/agent/agent.rb', line 668

def handle_license_error(error)
  log.error error.message
  log.info "Visit NewRelic.com to obtain a valid license key, or to upgrade your account."
  disconnect
end

#increment_retry_period!Object

:nodoc:



632
633
634
# File 'lib/new_relic/agent/agent.rb', line 632

def increment_retry_period! #:nodoc:
  self.connect_retry_period=(get_retry_period)
end

#log_connection!(config_data) ⇒ Object

Logs when we connect to the server, for debugging purposes

  • makes sure we know if an agent has not connected



880
881
882
883
884
# File 'lib/new_relic/agent/agent.rb', line 880

def log_connection!(config_data)
  control.log! "Connected to NewRelic Service at #{@collector}"
  log.debug "Agent Run       = #{@agent_id}."
  log.debug "Connection data = #{config_data.inspect}"
end

#log_error(error) ⇒ Object

When we have a problem connecting to the server, we need to tell the user what happened, since this is not an error we can handle gracefully.



656
657
658
659
# File 'lib/new_relic/agent/agent.rb', line 656

def log_error(error)
  log.error "Error establishing connection with New Relic Service at #{control.server}: #{error.message}"
  log.debug error.backtrace.join("\n")
end

#log_seed_tokenObject

If we are using a seed and token to validate the agent, we should debug log that fact so that debug logs include a clue that token authentication is what will be used



677
678
679
680
681
# File 'lib/new_relic/agent/agent.rb', line 677

def log_seed_token
  if control.validate_seed
    log.debug "Connecting with validation seed/token: #{control.validate_seed}/#{control.validate_token}"
  end
end

#log_sql_transmission_warning?Boolean

Warn the user when we are sending raw sql across the wire

  • they should probably be using ssl when this is true

Returns:

  • (Boolean)


829
830
831
# File 'lib/new_relic/agent/agent.rb', line 829

def log_sql_transmission_warning?
  log.warn("Agent is configured to send raw SQL to the service") if @record_sql == :raw
end

#query_server_for_configurationObject

Sets the collector host and connects to the server, then invokes the final configuration with the returned data



846
847
848
849
850
# File 'lib/new_relic/agent/agent.rb', line 846

def query_server_for_configuration
  set_collector_host!

  finish_setup(connect_to_server)
end

#set_collector_host!Object

Asks the collector to tell us which sub-collector we should be reporting to, and then does the name resolution on that host so we don’t block on DNS during the normal course of agent processing



837
838
839
840
841
842
# File 'lib/new_relic/agent/agent.rb', line 837

def set_collector_host!
  host = invoke_remote(:get_redirect_host)
  if host
    @collector = control.server_from_host(host)
  end
end

#set_sql_recording!Object

Sets the sql recording configuration by trying to detect any attempt to disable the sql collection - ‘off’, ‘false’, ‘none’, and friends. Otherwise, we accept ‘raw’, and unrecognized values default to ‘obfuscated’



809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
# File 'lib/new_relic/agent/agent.rb', line 809

def set_sql_recording!
  record_sql_config = @transaction_sampler.config.fetch('record_sql', :obfuscated)
  case record_sql_config.to_s
  when 'off'
    @record_sql = :off
  when 'none'
    @record_sql = :off
  when 'false'
    @record_sql = :off
  when 'raw'
    @record_sql = :raw
  else
    @record_sql = :obfuscated
  end

  log_sql_transmission_warning?
end

#should_keep_retrying?(options) ⇒ Boolean

We keep trying by default, but you can disable it with the :keep_retrying option set to false

Returns:

  • (Boolean)


619
620
621
# File 'lib/new_relic/agent/agent.rb', line 619

def should_keep_retrying?(options)
  @keep_retrying = (options[:keep_retrying].nil? || options[:keep_retrying])
end

#should_retry?Boolean

We should only retry when there has not been a more serious condition that would prevent it. We increment the connect attempts and the retry period, to prevent constant connection attempts, and tell the user what we’re doing by logging.

Returns:

  • (Boolean)


641
642
643
644
645
646
647
648
649
650
651
# File 'lib/new_relic/agent/agent.rb', line 641

def should_retry?
  if @keep_retrying
    self.connect_attempts=(connect_attempts + 1)
    increment_retry_period!
    log.info "Will re-attempt in #{connect_retry_period} seconds"
    true
  else
    disconnect
    false
  end
end

#tried_to_connect?(options) ⇒ Boolean

We’ve tried to connect if @connected is not nil, or if we are forcing reconnection (i.e. in the case of an after_fork with long running processes)

Returns:

  • (Boolean)


613
614
615
# File 'lib/new_relic/agent/agent.rb', line 613

def tried_to_connect?(options)
  !(@connected.nil? || options[:force_reconnect])
end

#validate_settingsObject

These validation settings are used for cases where a dynamic server is spun up for clients - partners can include a seed and token to indicate that the host is allowed to connect, rather than setting a unique hostname



693
694
695
696
697
698
# File 'lib/new_relic/agent/agent.rb', line 693

def validate_settings
  {
    :seed => control.validate_seed,
    :token => control.validate_token
  }
end