lib/instana/agent.rb in instana-0.13.1 vs lib/instana/agent.rb in instana-0.14.0
- old
+ new
@@ -25,11 +25,11 @@
# Store the pid from process boot so we can detect forks
@pid = Process.pid
# Snapshot data is collected once per process but resent
# every 10 minutes along side process metrics.
- @snapshot = take_snapshot
+ @snapshot = ::Instana::Util.take_snapshot
# Set last snapshot to just under 10 minutes ago
# so we send a snapshot sooner than later
@last_snapshot = Time.now - 570
@@ -80,18 +80,10 @@
# This is usually Process.pid but in the case of docker, the host agent
# will return to us the true host pid in which we use to report data.
@process[:report_pid] = nil
end
- # Determine whether the pid has changed since Agent start.
- #
- # @ return [Boolean] true or false to indicate if forked
- #
- def forked?
- @pid != Process.pid
- end
-
# Used post fork to re-initialize state and restart communications with
# the host agent.
#
def after_fork
::Instana.logger.agent "after_fork hook called. Falling back to unannounced state and spawning a new background agent thread."
@@ -135,25 +127,25 @@
# The announce timer
# We attempt to announce this ruby sensor to the host agent.
# In case of failure, we try again in 30 seconds.
@announce_timer = @timers.now_and_every(30) do
if host_agent_ready? && announce_sensor
- ::Instana.logger.debug "Announce successful. Switching to metrics collection."
+ ::Instana.logger.warn "Host agent available. We're in business."
transition_to(:announced)
end
end
# The collect timer
# If we are in announced state, send metric data (only delta reporting)
# every ::Instana::Collector.interval seconds.
@collect_timer = @timers.every(::Instana::Collector.interval) do
if @state == :announced
- unless ::Instana::Collector.collect_and_report
+ if !::Instana::Collector.collect_and_report
# If report has been failing for more than 1 minute,
# fall back to unannounced state
if (Time.now - @entity_last_seen) > 60
- ::Instana.logger.debug "Metrics reporting failed for >1 min. Falling back to unannounced state."
+ ::Instana.logger.warn "Host agent offline for >1 min. Going to sit in a corner..."
transition_to(:unannounced)
end
end
::Instana.processor.send
end
@@ -186,35 +178,10 @@
::Instana.logger.debug "Agent exiting. Reporting final #{::Instana.processor.queue_count} trace(s)."
::Instana.processor.send
end
end
- # Indicates if the agent is ready to send metrics
- # and/or data.
- #
- def ready?
- # In test, we're always ready :-)
- return true if ENV['INSTANA_GEM_TEST']
-
- if forked?
- ::Instana.logger.agent "Instana: detected fork. Calling after_fork"
- after_fork
- end
-
- @state == :announced
- rescue => e
- Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
- Instana.logger.debug e.backtrace.join("\r\n")
- return false
- end
-
- # Returns the PID that we are reporting to
- #
- def report_pid
- @process[:report_pid]
- end
-
# Collect process ID, name and arguments to notify
# the host agent.
#
def announce_sensor
announce_payload = {}
@@ -268,25 +235,55 @@
req.body = payload.to_json
response = make_host_agent_request(req)
if response
- last_entity_response = response.code.to_i
+ if response.body.length > 2
+ # The host agent returned something indicating that is has a request for us that we
+ # need to process.
+ handle_response(response.body)
+ end
- if last_entity_response == 200
+ if response.code.to_i == 200
@entity_last_seen = Time.now
@last_snapshot = Time.now if with_snapshot
-
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")
end
+ # When a request is received by the host agent, it is sent here
+ # from processing and response.
+ #
+ # @param json_string [String] the request from the host agent
+ #
+ def handle_response(json_string)
+ their_request = JSON.parse(json_string).first
+
+ if their_request.key?("action")
+ if their_request["action"] == "ruby.source"
+ payload = ::Instana::Util.get_rb_source(their_request["args"]["file"])
+ else
+ payload = { :error => "Unrecognized action: #{their_request["action"]}. An newer Instana gem may be required for this. Current version: #{::Instana::VERSION}" }
+ end
+ 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}")
+ 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
+
# Accept and report spans to the host agent.
#
# @param traces [Array] An array of [Span]
# @return [Boolean]
#
@@ -348,10 +345,35 @@
Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
Instana.logger.debug e.backtrace.join("\r\n")
return false
end
+ # Returns the PID that we are reporting to
+ #
+ def report_pid
+ @process[:report_pid]
+ end
+
+ # Indicates if the agent is ready to send metrics
+ # and/or data.
+ #
+ def ready?
+ # In test, we're always ready :-)
+ return true if ENV['INSTANA_GEM_TEST']
+
+ if forked?
+ ::Instana.logger.agent "Instana: detected fork. Calling after_fork"
+ after_fork
+ end
+
+ @state == :announced
+ rescue => e
+ Instana.logger.debug "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
+ Instana.logger.debug e.backtrace.join("\r\n")
+ return false
+ end
+
private
# Handles any/all steps required in the transtion
# between states.
#
@@ -422,43 +444,14 @@
raise RuntimeError.new("Unsupported platform: get_real_pid") unless @is_linux
v = File.open("/proc/#{Process.pid}/sched", &:readline)
v.match(/\d+/).to_s.to_i
end
- # Method to collect up process info for snapshots. This
- # is generally used once per process.
+ # Determine whether the pid has changed since Agent start.
#
- def take_snapshot
- data = {}
-
- data[:sensorVersion] = ::Instana::VERSION
- data[:ruby_version] = RUBY_VERSION
-
- # Since a snapshot is only taken on process boot,
- # this is ok here.
- data[:start_time] = Time.now.to_s
-
- # Framework Detection
- if defined?(::RailsLts::VERSION)
- data[:framework] = "Rails on Rails LTS-#{::RailsLts::VERSION}"
-
- elsif defined?(::Rails.version)
- data[:framework] = "Ruby on Rails #{::Rails.version}"
-
- elsif defined?(::Grape::VERSION)
- data[:framework] = "Grape #{::Grape::VERSION}"
-
- elsif defined?(::Padrino::VERSION)
- data[:framework] = "Padrino #{::Padrino::VERSION}"
-
- elsif defined?(::Sinatra::VERSION)
- data[:framework] = "Sinatra #{::Sinatra::VERSION}"
- end
-
- data
- rescue => e
- ::Instana.logger.error "#{__method__}:#{File.basename(__FILE__)}:#{__LINE__}: #{e.message}"
- ::Instana.logger.debug e.backtrace.join("\r\n")
- return data
+ # @ return [Boolean] true or false to indicate if forked
+ #
+ def forked?
+ @pid != Process.pid
end
end
end