Draft: Airbrake v11 config example for Errbit - 2called-chaos/errbit GitHub Wiki
Errbit currently instructs you to use an airbrake 5.x release which hasn't seen a release since 2017. It's on you to decide if you want to update to a more recent version. Airbrake (v11 by now) has added a lot of functionality since then but Errbit does not support most of it (like performance metrics and job stats). Airbrake also removed their rather sensible default settings which may result in rather spammy notifications when left unconfigured. So why even update? Well as I said, your decision.
The following is an annotated version of an airbrake config currently being used in a production Rails application which includes important settings and sensible defaults. It should serve as a starting point to make your Errbit experience as enjoyable as possible.
Note that if you attempt to use the described method concerning "filter_parameter_logging" the airbrake config file should be named in a way that it is being executed after filter_parameter_logging.rb
. Feel free to rename either or both, Rails guarantees that initializers will be executed in sorted order.
Note: only project_key
, project_id
and host
are strictly necessary but it's strongly advised to also disable unsupported features as they impact performance, spam your log and phone home to airbrake.io! Everything else is optional and can be omitted.
Airbrake.configure do |config|
# disable features errbit cannot handle (log spam and performance impact)
config.job_stats = false
config.query_stats = false
config.performance_stats = false
config.remote_config = false
# project specific, must be set
config.project_key = 'YOUR_KEY_HERE_OR_USE_ENV'
# set app_version to something telling, we use the following:
config.app_version = "Ruby: #{RUBY_VERSION} » Rails: #{Rails::VERSION::STRING} » " << `cd #{Rails.root.shellescape} && git log -1 --pretty="%h - %B" HEAD`
# can always be 1, must be set
config.project_id = 1
# your errbit host, must be set (or you send to airbrake.io)
config.host = 'https://errbit.example.com'
# ignore exceptions in test/dev
config.ignore_environments = %w[development test]
# set app root directory
config.root_directory = Rails.root
# set current environment
config.environment = Rails.env
# log to own file
config.logger = Logger.new(Rails.root.join("log/airbrake.log"))
config.logger.level = Logger::INFO
# filter_parameter_logging.rb must run first or it's empty!
# (use naming, e.g. z_airbrake.rb or 01-airbrake/02-filter)
config.blocklist_keys = Rails.application.config.filter_parameters
end
# =========================
# = Ignore exceptions/env =
# =========================
AIRBRAKE_IGNORE_ENV = [
'ACTION_CONTROLLER_INSTANCE',
'ACTION_DISPATCH_BACKTRACE_CLEANER',
'ACTION_DISPATCH_COOKIES',
'ACTION_DISPATCH_COOKIES_DIGEST',
'ACTION_DISPATCH_COOKIES_SERIALIZER',
'ACTION_DISPATCH_ENCRYPTED_COOKIE_SALT',
'ACTION_DISPATCH_ENCRYPTED_SIGNED_COOKIE_SALT',
'ACTION_DISPATCH_HTTP_AUTH_SALT',
'ACTION_DISPATCH_KEY_GENERATOR',
'ACTION_DISPATCH_LOGGER',
'ACTION_DISPATCH_ROUTES',
'ACTION_DISPATCH_SECRET_KEY_BASE',
'ACTION_DISPATCH_SECRET_TOKEN',
'ACTION_DISPATCH_SIGNED_COOKIE_SALT',
]
AIRBRAKE_IGNORE_EXCEPTIONS = [
'ActiveRecord::RecordNotFound',
'ActionController::RoutingError',
'ActionController::UnknownFormat',
'ActionController::UnknownAction',
'ActionController::InvalidCrossOriginRequest',
'ActionController::InvalidAuthenticityToken',
'Mime::Type::InvalidMimeType',
]
# Ignore exceptions by class
Airbrake.add_filter do |notice|
if notice[:errors].any? { |error| AIRBRAKE_IGNORE_EXCEPTIONS.include?(error[:type]) }
notice.ignore!
end
end
# Example to ignore errors based on type or message
Airbrake.add_filter do |notice|
notice.ignore! if notice[:errors].any?{|error|
error[:type] == "ActionController::BadRequest" &&
(
error[:message].to_s.downcase.start_with?("invalid query parameters: non utf-8 value:") ||
error[:message].to_s.downcase.start_with?("invalid query parameters: invalid encoding for parameter")
)
}
end
# ==========================
# = Annotate notifications =
# ==========================
# A filter that collects request body information. Enable it if you are sure you
# don't send sensitive information to Airbrake in your body (such as passwords).
# https://github.com/airbrake/airbrake#requestbodyfilter
# Note: This patched version checks if body responds_to?(:read)
class PatchedAirbrakeBodyFilter < Airbrake::Rack::RequestBodyFilter
# @see Airbrake::FilterChain#refine
def call(notice)
return unless (request = notice.stash[:rack_request])
return unless request.body
if request.body.respond_to?(:read)
notice[:environment][:body] = request.body.read(@length)
request.body.rewind
else
notice[:environment][:body] = request.body.to_s
end
end
end
Airbrake.add_filter(PatchedAirbrakeBodyFilter.new)
# Annotate via filter
Airbrake.add_filter do |notice|
ctx = notice[:context]
# add link to user, will autolink within errbit
# (user context was discovered by airbrake via current_user method)
if uid = ctx.dig(:user, :id)
ctx[:user][:backend_link] = "https://example.com/admin/users/#{uid}"
end
# add headers to environment
if headers = ctx[:headers]
headers.each do |k, v|
nk = k.to_s.gsub(".", "_").upcase
next if AIRBRAKE_IGNORE_ENV.include?(nk)
notice[:environment][nk] = v.to_s
end
end
# add request env to environment
if env = notice.stash[:rack_request]&.env
env.each do |k, v|
nk = k.to_s.gsub(".", "_").upcase
next if AIRBRAKE_IGNORE_ENV.include?(nk)
notice[:environment][nk] = v.to_s
end
end
# cleanup env hash (remove blank values, sort by key)
notice[:environment] = notice[:environment].reject{|k, v| v.blank? }.sort_by{|k, v| k.to_s }.to_h
end
Reference: https://www.rubydoc.info/gems/airbrake-ruby/Airbrake/Config