class ElasticAPM::Config

@api private
rubocop:disable Metrics/ClassLength

def alert_logger

def alert_logger
  @alert_logger ||= PrefixedLogger.new($stdout, prefix: Logging::PREFIX)
end

def app=(app)

def app=(app)
  case app_type?(app)
  when :sinatra
    set_sinatra(app)
  when :rails
    set_rails(app)
  else
    self.service_name = 'ruby'
  end
end

def app_type?(app)

def app_type?(app)
  if defined?(Rails::Application) && app.is_a?(Rails::Application)
    return :rails
  end
  if app.is_a?(Class) && app.superclass.to_s == 'Sinatra::Base'
    return :sinatra
  end
  nil
end

def assign(options)

def assign(options)
  options.each do |key, value|
    send("#{key}=", value)
  end
end

def available_spies

rubocop:disable Metrics/MethodLength
def available_spies
  %w[
    delayed_job
    elasticsearch
    faraday
    http
    json
    mongo
    net_http
    redis
    sequel
    sidekiq
    sinatra
    tilt
    rake
  ]
end

def build_logger

def build_logger
  logger = Logger.new(log_path == '-' ? STDOUT : log_path)
  logger.level = log_level
  self.logger = logger
end

def capture_body=(value)

rubocop:disable Metrics/MethodLength
def capture_body=(value)
  if value =~ /(all|transactions|errors|off)/
    @capture_body = value
    return
  end
  case value
  when true
    alert_logger.warn "Boolean value for option `capture_body' has " \
      "been deprecated. Setting to 'all'"
    @capture_body = 'all'
  when false
    alert_logger.warn "Boolean value for option `capture_body' has " \
      "been deprecated. Setting to 'off'"
    @capture_body = 'off'
  else
    default = DEFAULTS[:capture_body]
    alert_logger.warn "Unknown value `#{value}' for option "\
      "`capture_body'. Defaulting to `#{default}'"
    @capture_body = default
  end
end

def collect_metrics?

def collect_metrics?
  metrics_interval > 0
end

def custom_key_filters=(filters)

def custom_key_filters=(filters)
  @custom_key_filters = Array(filters).map(&Regexp.method(:new))
end

def enabled_spies

def enabled_spies
  available_spies - disabled_spies
end

def format_name(str)

def format_name(str)
  str && str.gsub('::', '_')
end

def ignore_url_patterns=(strings)

def ignore_url_patterns=(strings)
  @ignore_url_patterns = Array(strings).map(&Regexp.method(:new))
end

def initialize(options = {})

def initialize(options = {})
  set_defaults
  set_from_args(options)
  set_from_config_file
  set_from_env
  normalize_durations
  normalize_sizes
  yield self if block_given?
  build_logger if logger.nil?
end

def method_missing(name, *args)

def method_missing(name, *args)
  if DEPRECATED_OPTIONS.include?(name)
    alert_logger.warn "The option `#{name}' has been removed."
    return
  end
  if name.to_s.end_with?('=')
    raise ConfigError, "No such option `#{name.to_s.delete('=')}'"
  end
  super
end

def normalize_durations

def normalize_durations
  DURATION_KEYS.each do |key|
    value = send(key).to_s
    default_unit = DURATION_DEFAULT_UNITS.fetch(key, 's')
    duration = Duration.parse(value, default_unit: default_unit)
    send("#{key}=", duration.seconds)
  end
end

def normalize_sizes

def normalize_sizes
  SIZE_KEYS.each do |key|
    value = send(key).to_s
    default_unit = SIZE_DEFAULT_UNITS.fetch(key, 'b')
    size = Size.parse(value, default_unit: default_unit)
    send("#{key}=", size.bytes)
  end
end

def respond_to_missing?(name)

def respond_to_missing?(name)
  return true if DEPRECATED_OPTIONS.include? name
  return true if name.to_s.end_with?('=')
  false
end

def set_defaults

def set_defaults
  assign(DEFAULTS)
end

def set_from_args(options)

def set_from_args(options)
  assign(options)
rescue ConfigError => e
  alert_logger.warn format(
    'Failed to configure from arguments: %s',
    e.message
  )
end

def set_from_config_file

def set_from_config_file
  return unless File.exist?(config_file)
  assign(YAML.safe_load(ERB.new(File.read(config_file)).result) || {})
rescue ConfigError => e
  alert_logger.warn format(
    'Failed to configure from config file: %s',
    e.message
  )
end

def set_from_env

rubocop:disable Metrics/AbcSize
rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
def set_from_env
  ENV_TO_KEY.each do |env_key, key|
    next unless (value = ENV[env_key])
    type, key = key if key.is_a? Array
    value =
      case type
      when :int then value.to_i
      when :float then value.to_f
      when :bool then !%w[0 false].include?(value.strip.downcase)
      when :list then value.split(/[ ,]/)
      when :dict then Hash[value.split(/[&,]/).map { |kv| kv.split('=') }]
      else value
      end
    send("#{key}=", value)
  end
end

def set_rails(app) # rubocop:disable Metrics/AbcSize

rubocop:disable Metrics/AbcSize
def set_rails(app) # rubocop:disable Metrics/AbcSize
  self.service_name ||= format_name(service_name || app.class.parent_name)
  self.framework_name ||= 'Ruby on Rails'
  self.framework_version ||= Rails::VERSION::STRING
  self.logger ||= Rails.logger
  self.root_path = Rails.root.to_s
  self.view_paths = app.config.paths['app/views'].existent
end

def set_sinatra(app)

def set_sinatra(app)
  self.service_name = format_name(service_name || app.to_s)
  self.framework_name = framework_name || 'Sinatra'
  self.framework_version = framework_version || Sinatra::VERSION
  self.root_path = Dir.pwd
end

def span_frames_min_duration=(duration)

def span_frames_min_duration=(duration)
  @span_frames_min_duration = duration
  @span_frames_min_duration_us = duration * 1_000_000
end

def span_frames_min_duration?

def span_frames_min_duration?
  span_frames_min_duration != 0
end

def use_ssl?

def use_ssl?
  server_url.start_with?('https')
end