class StackifyRubyAPM::Agent

@api private

Constants

LOCK

Attributes

config[R]
context_builder[R]
error_builder[R]
error_serializer[R]
instrumenter[R]
messages[R]
pending_transactions[R]
stacktrace_builder[R]
trace_logger[R]

Public Class Methods

instance() click to toggle source
# File lib/stackify_apm/agent.rb, line 24
def self.instance # rubocop:disable Style/TrivialAccessors
  @instance
end
new(config) click to toggle source
# File lib/stackify_apm/agent.rb, line 78
def initialize(config)
  @config = config
  @trace_logger = TraceLogger.new(config)
  @messages = Queue.new
  @pending_transactions = Queue.new
  @instrumenter = Instrumenter.new(self)
  @context_builder = ContextBuilder.new(self)
  @error_builder = ErrorBuilder.new(self)
  @stacktrace_builder = StacktraceBuilder.new(self)
  @error_serializer = Serializers::Errors.new(config)
end
running?() click to toggle source
# File lib/stackify_apm/agent.rb, line 74
def self.running?
  !@instance.nil?
end
squish(str) click to toggle source

This method will strip and remove garbage character and multiple spaces.

# File lib/stackify_apm/agent.rb, line 189
def self.squish(str)
  str = str.sub(/\A[[:space:]]+/, '')
  str = str.sub(/[[:space:]]+\z/, '')
  str = str.sub(/[[:space:]]+/, ' ')
  str = str.strip.sub(/\s+/, '')
  str
end
start(config) click to toggle source

rubocop:disable Metrics/PerceivedComplexity rubocop:disable Metrics/CyclomaticComplexity

# File lib/stackify_apm/agent.rb, line 30
def self.start(config)
  return @instance if @instance

  config = Config.new(config) unless config.is_a?(Config)
  case config.transport.downcase
  # For unix socket we don't create a trace log file
  when StackifyRubyAPM::TRACE_LOG
    # For Default transport let's create initial trace log file
    pid = $PID || Process.pid
    host_name = (config.hostname || `hostname`).strip
    date_now = Time.now
    current_trace_file = config.log_trace_path + squish(host_name) + '#' + squish(pid.to_s)
    if ENV['STACKIFY_RUBY_ENV'] != 'rspec'
      config.tracer_logger = StackifyLogger.new(current_trace_file, config.filenum_rotate, config.logger_byte_size)
      config.debug_logger
      config.logtime_created = date_now.strftime('%H:%M')
      Util::TraceLogWatcher.delete_trace_logs(config)
    end
  end

  LOCK.synchronize do
    return @instance if @instance

    @instance = new(config).start
  end
end
stop() click to toggle source

rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/PerceivedComplexity

# File lib/stackify_apm/agent.rb, line 59
def self.stop
  LOCK.synchronize do
    return unless @instance

    @instance.stop
    @instance = nil
  end
end

Public Instance Methods

build_context(rack_env) click to toggle source

Responsible for building the transaction's context

# File lib/stackify_apm/agent.rb, line 161
def build_context(rack_env)
  @context_builder.build(rack_env)
end
current_transaction() click to toggle source

Instrumentation

# File lib/stackify_apm/agent.rb, line 145
def current_transaction
  instrumenter.current_transaction
end
enqueue_error(error) click to toggle source
# File lib/stackify_apm/agent.rb, line 137
def enqueue_error(error)
  boot_worker unless worker_running?

  messages.push(Worker::ErrorMsg.new(error))
end
enqueue_transaction(transaction) click to toggle source

queues Stores transaction in queue

# File lib/stackify_apm/agent.rb, line 118
def enqueue_transaction(transaction)
  if !@config.queue
    return @trace_logger.post([transaction])
  end

  boot_worker unless worker_running?
  pending_transactions.push(transaction)
  return unless should_flush_transactions?

  messages.push(Worker::FlushMsg.new)
end
report(exception, handled: true) click to toggle source

errors

# File lib/stackify_apm/agent.rb, line 167
def report(exception, handled: true)
  return if config.filter_exception_types.include?(exception.class.to_s)

  error = @error_builder.build_exception(
    exception,
    handled: handled
  )
  current_error = @error_serializer.build(error)
  current_transaction.add_exception(current_error) if current_transaction
end
report_message(message, backtrace: nil, **attrs) click to toggle source
# File lib/stackify_apm/agent.rb, line 178
def report_message(message, backtrace: nil, **attrs)
  error = @error_builder.build_log(
    message,
    backtrace: backtrace,
    **attrs
  )
  enqueue_error error
end
should_flush_transactions?() click to toggle source
# File lib/stackify_apm/agent.rb, line 130
def should_flush_transactions?
  return true unless config.flush_interval_seconds
  return true if pending_transactions.length >= config.max_queue_size

  false
end
span(*args, &block) click to toggle source
# File lib/stackify_apm/agent.rb, line 155
def span(*args, &block)
  instrumenter.span(*args, &block)
end
start() click to toggle source
# File lib/stackify_apm/agent.rb, line 100
def start
  info '[Agent] start()'
  info '[Agent] transport type: ' + @config.transport
  spies_name = ''
  return false unless @config.instrument
  config.enabled_spies.each do |lib|
    spies_name = spies_name + ', ' + lib.inspect.to_s

    require "stackify_apm/spies/#{lib}"
  end

  debug '[Agent] Loaded spies: ' + spies_name if ENV['STACKIFY_TRANSPORT_LOG_LEVEL'] == '0'
  self
end
stop() click to toggle source
# File lib/stackify_apm/agent.rb, line 68
def stop
  @instrumenter.stop
  kill_worker
  self
end
transaction(*args, &block) click to toggle source

Loads transaction

# File lib/stackify_apm/agent.rb, line 151
def transaction(*args, &block)
  instrumenter.transaction(*args, &block)
end

Private Instance Methods

boot_worker() click to toggle source
# File lib/stackify_apm/agent.rb, line 199
def boot_worker
  debug '[Agent] Booting worker' if ENV['STACKIFY_TRANSPORT_LOG_LEVEL'] == '0'

  @worker_thread = Thread.new do
    Worker.new(
      config,
      messages,
      pending_transactions,
      trace_logger
    ).run_forever
  end
end
kill_worker() click to toggle source
# File lib/stackify_apm/agent.rb, line 212
def kill_worker
  messages << Worker::StopMsg.new
  raise 'Failed to wait for worker, not all messages sent' if @worker_thread && !@worker_thread.join(5) # 5 secs

  @worker_thread = nil
end
worker_running?() click to toggle source
# File lib/stackify_apm/agent.rb, line 219
def worker_running?
  @worker_thread && @worker_thread.alive?
end