lib/instana/agent.rb in instana-1.0.1 vs lib/instana/agent.rb in instana-1.0.2
- old
+ new
@@ -13,14 +13,10 @@
LOCALHOST = '127.0.0.1'.freeze
MIME_JSON = 'application/json'.freeze
DISCOVERY_PATH = 'com.instana.plugin.ruby.discovery'.freeze
def initialize
- # Host agent defaults. Can be configured via Instana.config
- @host = LOCALHOST
- @port = 42699
-
# Supported two states (unannounced & announced)
@state = :unannounced
# Snapshot data is collected once per process but resent
# every 10 minutes along side process metrics.
@@ -52,11 +48,15 @@
end
# The agent UUID returned from the host agent
@agent_uuid = nil
+ # Collect process information
@process = ::Instana::Util.collect_process_info
+
+ # This will hold info on the discovered agent host
+ @discovered = nil
end
# Used post fork to re-initialize state and restart communications with
# the host agent.
#
@@ -160,19 +160,24 @@
# Collect process ID, name and arguments to notify
# the host agent.
#
def announce_sensor
+ unless @discovered
+ ::Instana.logger.agent("#{__method__} called but discovery hasn't run yet!")
+ return false
+ end
+
announce_payload = {}
announce_payload[:pid] = pid_namespace? ? get_real_pid : Process.pid
announce_payload[:args] = @process[:arguments]
- uri = URI.parse("http://#{@host}:#{@port}/#{DISCOVERY_PATH}")
+ uri = URI.parse("http://#{@discovered[:agent_host]}:#{@discovered[:agent_port]}/#{DISCOVERY_PATH}")
req = Net::HTTP::Put.new(uri)
req.body = announce_payload.to_json
- ::Instana.logger.agent "Announce: http://#{@host}:#{@port}/#{DISCOVERY_PATH} - payload: #{req.body}"
+ ::Instana.logger.agent "Announce: http://#{@discovered[:agent_host]}:#{@discovered[:agent_port]}/#{DISCOVERY_PATH} - payload: #{req.body}"
response = make_host_agent_request(req)
if response && (response.code.to_i == 200)
data = JSON.parse(response.body)
@@ -191,13 +196,18 @@
# Method to report metrics data to the host agent.
#
# @param paylod [Hash] The collection of metrics to report.
#
def report_entity_data(payload)
+ unless @discovered
+ ::Instana.logger.agent("#{__method__} called but discovery hasn't run yet!")
+ return false
+ end
+
with_snapshot = false
path = "com.instana.plugin.ruby.#{@process[:report_pid]}"
- uri = URI.parse("http://#{@host}:#{@port}/#{path}")
+ uri = URI.parse("http://#{@discovered[:agent_host]}:#{@discovered[:agent_port]}/#{path}")
req = Net::HTTP::Post.new(uri)
# Every 5 minutes, send snapshot data as well
if (Time.now - @last_snapshot) > 600
with_snapshot = true
@@ -251,11 +261,11 @@
else
payload = { :error => "Instana Ruby: No action specified in request." }
end
path = "com.instana.plugin.ruby/response.#{@process[:report_pid]}?messageId=#{URI.encode(their_request['messageId'])}"
- uri = URI.parse("http://#{@host}:#{@port}/#{path}")
+ uri = URI.parse("http://#{@discovered[:agent_host]}:#{@discovered[:agent_port]}/#{path}")
req = Net::HTTP::Post.new(uri)
req.body = payload.to_json
::Instana.logger.agent_response "Responding to agent: #{req.inspect}"
make_host_agent_request(req)
end
@@ -266,12 +276,17 @@
# @return [Boolean]
#
def report_spans(spans)
return unless @state == :announced
+ unless @discovered
+ ::Instana.logger.agent("#{__method__} called but discovery hasn't run yet!")
+ return false
+ end
+
path = "com.instana.plugin.ruby/traces.#{@process[:report_pid]}"
- uri = URI.parse("http://#{@host}:#{@port}/#{path}")
+ uri = URI.parse("http://#{@discovered[:agent_host]}:#{@discovered[:agent_port]}/#{path}")
req = Net::HTTP::Post.new(uri)
req.body = spans.to_json
response = make_host_agent_request(req)
@@ -288,43 +303,77 @@
Instana.logger.debug e.backtrace.join("\r\n")
end
# Check that the host agent is available and can be contacted. This will
# first check localhost and if not, then attempt on the default gateway
- # for docker in bridged mode. It will save where it found the host agent
- # in @host that is used in subsequent HTTP calls.
+ # for docker in bridged mode.
#
def host_agent_ready?
- # Localhost
- uri = URI.parse("http://#{LOCALHOST}:#{@port}/")
+ @discovered ||= run_discovery
+
+ if @discovered
+ # Try default location or manually configured (if so)
+ uri = URI.parse("http://#{@discovered[:agent_host]}:#{@discovered[:agent_port]}/")
+ req = Net::HTTP::Get.new(uri)
+
+ response = make_host_agent_request(req)
+
+ if response && (response.code.to_i == 200)
+ return true
+ end
+ end
+ false
+ rescue => e
+ Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
+ Instana.logger.debug e.backtrace.join("\r\n") unless ::Instana.test?
+ return false
+ end
+
+ # Runs a discovery process to determine where we can contact the host agent. This is usually just
+ # localhost but in docker can be found on the default gateway. This also allows for manual
+ # configuration via ::Instana.config[:agent_host/port].
+ #
+ # @return [Hash] a hash with :agent_host, :agent_port values or empty hash
+ #
+ def run_discovery
+ discovered = {}
+
+ ::Instana.logger.debug "#{__method__}: Running agent discovery..."
+
+ # Try default location or manually configured (if so)
+ uri = URI.parse("http://#{::Instana.config[:agent_host]}:#{::Instana.config[:agent_port]}/")
req = Net::HTTP::Get.new(uri)
+ ::Instana.logger.debug "#{__method__}: Trying #{::Instana.config[:agent_host]}:#{::Instana.config[:agent_port]}"
+
response = make_host_agent_request(req)
if response && (response.code.to_i == 200)
- @host = LOCALHOST
- return true
+ discovered[:agent_host] = ::Instana.config[:agent_host]
+ discovered[:agent_port] = ::Instana.config[:agent_port]
+ ::Instana.logger.debug "#{__method__}: Found #{discovered[:agent_host]}:#{discovered[:agent_port]}"
+ return discovered
end
- return false unless @is_linux
+ return nil unless @is_linux
# We are potentially running on Docker in bridged networking mode.
# Attempt to contact default gateway
- uri = URI.parse("http://#{@default_gateway}:#{@port}/")
+ uri = URI.parse("http://#{@default_gateway}:#{::Instana.config[:agent_port]}/")
req = Net::HTTP::Get.new(uri)
+ ::Instana.logger.debug "#{__method__}: Trying default gateway #{@default_gateway}:#{::Instana.config[:agent_port]}"
+
response = make_host_agent_request(req)
if response && (response.code.to_i == 200)
- @host = @default_gateway
- return true
+ discovered[:agent_host] = @default_gateway
+ discovered[:agent_port] = ::Instana.config[:agent_port]
+ ::Instana.logger.debug "#{__method__}: Found #{discovered[:agent_host]}:#{discovered[:agent_port]}"
+ return discovered
end
- false
- rescue => e
- Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
- Instana.logger.debug e.backtrace.join("\r\n")
- return false
+ nil
end
# Returns the PID that we are reporting to
#
def report_pid
@@ -344,11 +393,11 @@
end
@state == :announced
rescue => e
Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
- Instana.logger.debug e.backtrace.join("\r\n")
+ Instana.logger.debug e.backtrace.join("\r\n") unless ::Instana.test?
return false
end
private
@@ -401,10 +450,10 @@
response
rescue Errno::ECONNREFUSED
return nil
rescue => e
Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
- Instana.logger.debug e.backtrace.join("\r\n")
+ Instana.logger.debug e.backtrace.join("\r\n") unless ::Instana.test?
return nil
end
# Indicates whether we are running in a pid namespace (such as
# Docker).