lib/honeybadger/config/defaults.rb



require 'socket'
require 'honeybadger/breadcrumbs/active_support'

module Honeybadger
  class Config
    class Boolean; end

    IGNORE_DEFAULT = ['ActionController::RoutingError',
                      'AbstractController::ActionNotFound',
                      'ActionController::MethodNotAllowed',
                      'ActionController::UnknownHttpMethod',
                      'ActionController::NotImplemented',
                      'ActionController::UnknownFormat',
                      'ActionController::InvalidAuthenticityToken',
                      'ActionController::InvalidCrossOriginRequest',
                      # ActionDispatch::ParamsParser::ParseError was removed in Rails 6.0
                      # and may be removed here once support for Rails 5.2 is dropped.
                      # https://github.com/rails/rails/commit/e16c765ac6dcff068ff2e5554d69ff345c003de1
                      # https://github.com/honeybadger-io/honeybadger-ruby/pull/358
                      'ActionDispatch::ParamsParser::ParseError',
                      'ActionDispatch::Http::Parameters::ParseError',
                      'ActionController::BadRequest',
                      'ActionController::ParameterMissing',
                      'ActiveRecord::RecordNotFound',
                      'ActionController::UnknownAction',
                      'ActionDispatch::Http::MimeNegotiation::InvalidType',
                      'Rack::QueryParser::ParameterTypeError',
                      'Rack::QueryParser::InvalidParameterError',
                      'CGI::Session::CookieStore::TamperedWithCookie',
                      'Mongoid::Errors::DocumentNotFound',
                      'Sinatra::NotFound',
                      'Sidekiq::JobRetry::Skip'].map(&:freeze).freeze

    DEVELOPMENT_ENVIRONMENTS = ['development', 'test', 'cucumber'].map(&:freeze).freeze

    DEFAULT_PATHS = ['honeybadger.yml', 'config/honeybadger.yml', "#{ENV['HOME']}/honeybadger.yml"].map(&:freeze).freeze

    OPTIONS = {
      api_key: {
        description: 'The API key for your Honeybadger project.',
        default: nil,
        type: String
      },
      env: {
        description: 'The current application\'s environment name.',
        default: nil,
        type: String
      },
      report_data: {
        description: 'Enable/disable reporting of data. Defaults to true for non-development environments.',
        default: nil,
        type: Boolean
      },
      root: {
        description: 'The project\'s absolute root path.',
        default: Dir.pwd,
        type: String
      },
      revision: {
        description: 'The git revision of the project.',
        default: nil,
        type: String
      },
      hostname: {
        description: 'The hostname of the current box.',
        default: Socket.gethostname,
        type: String
      },
      backend: {
        description: 'An alternate backend to use for reporting data.',
        default: nil,
        type: String
      },
      debug: {
        description: 'Enables debug logging.',
        default: false,
        type: Boolean
      },
      development_environments: {
        description: 'Environments which will not report data by default (use report_data to enable/disable explicitly).',
        default: DEVELOPMENT_ENVIRONMENTS,
        type: Array
      },
      :'send_data_at_exit' => {
        description: 'Send remaining data when Ruby exits.',
        default: true,
        type: Boolean
      },
      max_queue_size: {
        description: 'Maximum number of items for each worker queue.',
        default: 100,
        type: Integer
      },
      plugins: {
        description: 'An optional list of plugins to load. Default is to load all plugins.',
        default: nil,
        type: Array
      },
      sync: {
        description: 'Enable all notices to be sent synchronously. Default is false.',
        default: false,
        type: Boolean
      },
      :'skipped_plugins' => {
        description: 'An optional list of plugins to skip.',
        default: nil,
        type: Array
      },
      :'config.path' => {
        description: 'The path (absolute, or relative from config.root) to the project\'s YAML configuration file.',
        default: DEFAULT_PATHS,
        type: String
      },
      :'logging.path' => {
        description: 'The path (absolute, or relative from config.root) to the log file.',
        default: nil,
        type: String
      },
      :'logging.level' => {
        description: 'The log level.',
        default: 'INFO',
        type: String
      },
      :'logging.debug' => {
        description: 'Override debug logging.',
        default: nil,
        type: Boolean
      },
      :'logging.tty_level' => {
        description: 'Level to log when attached to a terminal (anything < logging.level will always be ignored).',
        default: 'DEBUG',
        type: String
      },
      :'connection.secure' => {
        description: 'Use SSL when sending data.',
        default: true,
        type: Boolean
      },
      :'connection.host' => {
        description: 'The host to use when sending data.',
        default: 'api.honeybadger.io'.freeze,
        type: String
      },
      :'connection.port' => {
        description: 'The port to use when sending data.',
        default: nil,
        type: Integer
      },
      :'connection.system_ssl_cert_chain' => {
        description: 'Use the system\'s SSL certificate chain (if available).',
        default: false,
        type: Boolean
      },
      :'connection.ssl_ca_bundle_path' => {
        description: 'Use this ca bundle when establishing secure connections.',
        default: nil,
        type: String
      },
      :'connection.http_open_timeout' => {
        description: 'The HTTP open timeout when connecting to the server.',
        default: 2,
        type: Integer
      },
      :'connection.http_read_timeout' => {
        description: 'The HTTP read timeout when connecting to the server.',
        default: 5,
        type: Integer
      },
      :'connection.proxy_host' => {
        description: 'The proxy host to use when sending data.',
        default: nil,
        type: String
      },
      :'connection.proxy_port' => {
        description: 'The proxy port to use when sending data.',
        default: nil,
        type: Integer
      },
      :'connection.proxy_user' => {
        description: 'The proxy user to use when sending data.',
        default: nil,
        type: String
      },
      :'connection.proxy_pass' => {
        description: 'The proxy password to use when sending data.',
        default: nil,
        type: String
      },
      :'request.filter_keys' => {
        description: 'A list of keys to filter when sending request data.',
        default: ['password'.freeze, 'password_confirmation'.freeze, 'HTTP_AUTHORIZATION'.freeze].freeze,
        type: Array
      },
      :'request.disable_session' => {
        description: 'Prevent session from being sent with request data.',
        default: false,
        type: Boolean
      },
      :'request.disable_params' => {
        description: 'Prevent params from being sent with request data.',
        default: false,
        type: Boolean
      },
      :'request.disable_environment' => {
        description: 'Prevent Rack environment from being sent with request data.',
        default: false,
        type: Boolean
      },
      :'request.disable_url' => {
        description: 'Prevent url from being sent with request data (Rack environment may still contain it in some cases).',
        default: false,
        type: Boolean
      },
      :'user_informer.enabled' => {
        description: 'Enable the UserInformer middleware.',
        default: true,
        type: Boolean
      },
      :'user_informer.info' => {
        description: 'Replacement string for HTML comment in templates.',
        default: 'Honeybadger Error {{error_id}}'.freeze,
        type: String
      },
      :'feedback.enabled' => {
        description: 'Enable the UserFeedback middleware.',
        default: true,
        type: Boolean
      },
      :'exceptions.enabled' => {
        description: 'Enable automatic reporting of exceptions.',
        default: true,
        type: Boolean
      },
      :'exceptions.ignore' => {
        description: 'A list of additional exceptions to ignore (includes default ignored exceptions).',
        default: IGNORE_DEFAULT,
        type: Array
      },
      :'exceptions.ignore_only' => {
        description: 'A list of exceptions to ignore (overrides the default ignored exceptions).',
        default: nil,
        type: Array
      },
      :'exceptions.ignored_user_agents' => {
        description: 'A list of user agents to ignore.',
        default: [].freeze,
        type: Array
      },
      :'exceptions.rescue_rake' => {
        description: 'Enable reporting exceptions in rake tasks.',
        default: !STDOUT.tty?,
        type: Boolean
      },
      :'exceptions.notify_at_exit' => {
        description: 'Report unhandled exception when Ruby crashes (at_exit).',
        default: true,
        type: Boolean
      },
      :'exceptions.source_radius' => {
        description: 'The number of lines before and after the source when reporting snippets.',
        default: 2,
        type: Integer
      },
      :'exceptions.local_variables' => {
        description: 'Enable sending local variables. Requires binding_of_caller to be loaded.',
        default: false,
        type: Boolean
      },
      :'exceptions.unwrap' => {
        description: 'Reports #original_exception or #cause one level up from rescued exception when available.',
        default: false,
        type: Boolean
      },
      :'delayed_job.attempt_threshold' => {
        description: 'The number of attempts before notifications will be sent.',
        default: 0,
        type: Integer
      },
      :'sidekiq.attempt_threshold' => {
        description: 'The number of attempts before notifications will be sent.',
        default: 0,
        type: Integer
      },
      :'shoryuken.attempt_threshold' => {
        description: 'The number of attempts before notifications will be sent.',
        default: 0,
        type: Integer
      },
      :'faktory.attempt_threshold' => {
        description: 'The number of attempts before notifications will be sent.',
        default: 0,
        type: Integer
      },
      :'sidekiq.use_component' => {
        description: 'Automatically set the component to the class of the job. Helps with grouping.',
        default: true,
        type: Boolean
      },
      :'sinatra.enabled' => {
        description: 'Enable Sinatra auto-initialization.',
        default: true,
        type: Boolean
      },
      :'rails.subscriber_ignore_sources' => {
        description: "Sources (strings or regexes) that should be ignored when using the Rails' (7+) native error reporter (handled exceptions only).",
        # External libraries (eg Sidekiq, Resque) may wrap their execution in Rails' executor.
        # But this means errors will first be reported by Rails.error, before the library's native error handler
        # We ignore these reports, since the native error handler provides more context (such as job details)
        default: ['application.active_support'],
        type: Array
      },
      :'resque.resque_retry.send_exceptions_when_retrying' => {
        description: 'Send exceptions when retrying job.',
        default: true,
        type: Boolean
      },
      :'breadcrumbs.enabled' => {
        description: 'Disable breadcrumb functionality.',
        default: true,
        type: Boolean
      },
      :'breadcrumbs.active_support_notifications' => {
        description: 'Configuration for automatic Active Support Instrumentation events.',
        default: Breadcrumbs::ActiveSupport.default_notifications,
        type: Hash
      },
      :'breadcrumbs.logging.enabled' => {
        description: 'Enable/Disable automatic breadcrumbs from log messages.',
        default: true,
        type: Boolean
      }
    }.freeze

    DEFAULTS = Hash[OPTIONS.map{|k,v| [k, v[:default]] }].freeze
  end
end