class HeimdallApm::Agent

Main entry point for HeimdallApm. Only one instance is created per ruby process, and it manages the lifecycle of the monitoring

Constants

DEFAULT_PUSH_INTERVAL

Attributes

context[R]
options[R]

Public Class Methods

instance(opts = {}) click to toggle source
# File lib/heimdall_apm/agent.rb, line 13
def self.instance(opts = {})
  @@instance ||= self.new(opts)
end
new(opts) click to toggle source
# File lib/heimdall_apm/agent.rb, line 21
def initialize(opts)
  @options            = opts
  @context            = ::HeimdallApm::AgentContext.new
  @background_thread  = nil
  @stopped            = false
end

Public Instance Methods

install(options = {}) click to toggle source
# File lib/heimdall_apm/agent.rb, line 28
def install(options = {})
  context.config = ::HeimdallApm::Config.new

  if context.interactive?
    context.logger.info 'Preventing agent to start in interactive mode'
    return
  end

  # if defined?(Sidekiq) && Sidekiq.server?
  #   # TODO: handle custom instrumentation disabling
  #   HeimdallApm.logger.info 'Preventing agent to start in sidekiq server'
  #   return
  # end

  start(options)
end
start(options = {}) click to toggle source
# File lib/heimdall_apm/agent.rb, line 45
def start(options = {})
  return unless context.config.value('enabled')

  # TODO: use instruments manager
  if !defined?(Sidekiq) || !Sidekiq.server?
    require 'heimdall_apm/instruments/active_record'      if defined?(ActiveRecord)
    require 'heimdall_apm/instruments/action_controller'  if defined?(ActionController)
    require 'heimdall_apm/instruments/elasticsearch'      if defined?(Elasticsearch)
  end

  require 'heimdall_apm/instruments/sidekiq' if defined?(Sidekiq) && Sidekiq.server?

  if (options[:app])
    require 'heimdall_apm/instruments/middleware'
    # TODO: make the position configurable
    options[:app].config.middleware.insert_after Rack::Cors, HeimdallApm::Instruments::Middleware
  end

  # TODO: handle platform/webserver that don't handle this correctly
  at_exit { stop }

  context.started!
  @background_thread = Thread.new { background_run }
end
stop() click to toggle source
# File lib/heimdall_apm/agent.rb, line 70
def stop
  context.logger.info 'Stopping agent...'
  @stopped = true
  context.stopped!
  if @background_thread.alive?
    @background_thread.wakeup
    @background_thread.join
  end
end

Private Instance Methods

background_run() click to toggle source
# File lib/heimdall_apm/agent.rb, line 82
def background_run
  context.logger.info "Start background thread"
  reporting = ::HeimdallApm::Reporting.new(@context)
  next_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) + DEFAULT_PUSH_INTERVAL

  loop do
    now = Process.clock_gettime(Process::CLOCK_MONOTONIC)

    if @stopped
      # Commit data before stopping
      reporting.call
      break
    end

    if now < next_time
      remaining = next_time - now
      context.logger.debug { "Sleeping for #{remaining}" }
      sleep(remaining)
      next
    end

    reporting.call
    next_time = now + DEFAULT_PUSH_INTERVAL
  end
rescue => e
  context.logger.error e.message
end