From 7f605caa7afcc498e5f6e327b1bce0f6db29bf2f Mon Sep 17 00:00:00 2001 From: Mike Perham Date: Mon, 20 Jan 2025 10:26:07 -0800 Subject: [PATCH 01/13] Integrate standard, including safe fixes --- .standard.yml | 3 + Gemfile | 37 +- Guardfile | 6 +- Rakefile | 59 +- honeybadger.gemspec | 56 +- lib/honeybadger.rb | 10 +- lib/honeybadger/agent.rb | 62 ++- lib/honeybadger/backend.rb | 12 +- lib/honeybadger/backend/base.rb | 16 +- lib/honeybadger/backend/debug.rb | 8 +- lib/honeybadger/backend/null.rb | 4 +- lib/honeybadger/backend/server.rb | 22 +- lib/honeybadger/backend/test.rb | 4 +- lib/honeybadger/backtrace.rb | 31 +- lib/honeybadger/breadcrumbs.rb | 6 +- lib/honeybadger/breadcrumbs/active_support.rb | 16 +- lib/honeybadger/breadcrumbs/breadcrumb.rb | 3 +- lib/honeybadger/breadcrumbs/collector.rb | 8 +- lib/honeybadger/breadcrumbs/logging.rb | 15 +- lib/honeybadger/cli.rb | 6 +- lib/honeybadger/cli/deploy.rb | 14 +- lib/honeybadger/cli/exec.rb | 82 +-- lib/honeybadger/cli/helpers.rb | 36 +- lib/honeybadger/cli/heroku.rb | 60 +- lib/honeybadger/cli/install.rb | 88 +-- lib/honeybadger/cli/main.rb | 208 +++---- lib/honeybadger/cli/notify.rb | 26 +- lib/honeybadger/cli/test.rb | 202 +++---- lib/honeybadger/config.rb | 149 +++-- lib/honeybadger/config/defaults.rb | 428 +++++++-------- lib/honeybadger/config/env.rb | 6 +- lib/honeybadger/config/ruby.rb | 36 +- lib/honeybadger/config/yaml.rb | 24 +- lib/honeybadger/const.rb | 8 +- lib/honeybadger/context_manager.rb | 3 +- lib/honeybadger/conversions.rb | 15 +- lib/honeybadger/counter.rb | 8 +- lib/honeybadger/event.rb | 6 +- lib/honeybadger/events_worker.rb | 56 +- lib/honeybadger/gauge.rb | 4 +- lib/honeybadger/histogram.rb | 6 +- lib/honeybadger/init/hanami.rb | 10 +- lib/honeybadger/init/rails.rb | 28 +- lib/honeybadger/init/rake.rb | 20 +- lib/honeybadger/init/ruby.rb | 8 +- lib/honeybadger/init/sinatra.rb | 23 +- lib/honeybadger/instrumentation.rb | 53 +- lib/honeybadger/instrumentation_helper.rb | 23 +- lib/honeybadger/karafka.rb | 111 ++-- lib/honeybadger/logging.rb | 37 +- lib/honeybadger/metric.rb | 4 +- lib/honeybadger/metrics_worker.rb | 14 +- lib/honeybadger/notice.rb | 92 ++-- lib/honeybadger/notification_subscriber.rb | 26 +- lib/honeybadger/plugin.rb | 34 +- lib/honeybadger/plugins/active_job.rb | 20 +- lib/honeybadger/plugins/autotuner.rb | 10 +- lib/honeybadger/plugins/breadcrumbs.rb | 12 +- lib/honeybadger/plugins/delayed_job.rb | 6 +- lib/honeybadger/plugins/delayed_job/plugin.rb | 53 +- lib/honeybadger/plugins/faktory.rb | 16 +- lib/honeybadger/plugins/karafka.rb | 6 +- lib/honeybadger/plugins/lambda.rb | 8 +- lib/honeybadger/plugins/local_variables.rb | 6 +- lib/honeybadger/plugins/net_http.rb | 20 +- lib/honeybadger/plugins/passenger.rb | 8 +- lib/honeybadger/plugins/rails.rb | 22 +- lib/honeybadger/plugins/resque.rb | 12 +- lib/honeybadger/plugins/shoryuken.rb | 12 +- lib/honeybadger/plugins/sidekiq.rb | 69 ++- lib/honeybadger/plugins/solid_queue.rb | 6 +- lib/honeybadger/plugins/sucker_punch.rb | 10 +- lib/honeybadger/plugins/system.rb | 6 +- lib/honeybadger/plugins/thor.rb | 6 +- lib/honeybadger/plugins/warden.rb | 8 +- lib/honeybadger/rack/error_notifier.rb | 26 +- lib/honeybadger/rack/user_feedback.rb | 23 +- lib/honeybadger/rack/user_informer.rb | 12 +- lib/honeybadger/registry.rb | 4 +- lib/honeybadger/registry_execution.rb | 2 +- lib/honeybadger/ruby.rb | 4 +- lib/honeybadger/singleton.rb | 95 ++-- lib/honeybadger/tasks.rb | 6 +- lib/honeybadger/timer.rb | 2 +- lib/honeybadger/util/http.rb | 54 +- lib/honeybadger/util/request_hash.rb | 22 +- lib/honeybadger/util/request_payload.rb | 4 +- lib/honeybadger/util/revision.rb | 18 +- lib/honeybadger/util/sanitizer.rb | 42 +- lib/honeybadger/util/stats.rb | 9 +- lib/honeybadger/version.rb | 2 +- lib/honeybadger/worker.rb | 50 +- lib/puma/plugin/honeybadger.rb | 20 +- spec/features/at_exit_spec.rb | 14 +- spec/features/capistrano_spec.rb | 6 +- spec/features/custom_agent_spec.rb | 4 +- spec/features/deploy_spec.rb | 15 +- spec/features/exec_spec.rb | 15 +- spec/features/install_spec.rb | 106 ++-- spec/features/notify_spec.rb | 18 +- spec/features/rake_spec.rb | 22 +- spec/features/test_spec.rb | 52 +- spec/fixtures/Capfile | 8 +- spec/fixtures/Rakefile | 10 +- spec/fixtures/hanami/app.rb | 2 +- spec/fixtures/rails/config/application.rb | 34 +- spec/fixtures/rails/config/breadcrumbs.rb | 3 +- spec/fixtures/rails/config/environment.rb | 4 +- spec/fixtures/ruby_crash.rb | 4 +- spec/fixtures/ruby_custom.rb | 10 +- spec/fixtures/ruby_custom_crash.rb | 10 +- spec/fixtures/sinatra/app.rb | 16 +- spec/integration/hanami_spec.rb | 21 +- .../rails/active_job_adapter_spec.rb | 22 +- spec/integration/rails/basic_spec.rb | 2 +- spec/integration/rails/breadcrumb_spec.rb | 6 +- .../rails/error_subscriber_spec.rb | 28 +- spec/integration/rails_helper.rb | 20 +- spec/integration/resque_spec.rb | 16 +- spec/integration/sidekiq_spec.rb | 24 +- spec/integration/sinatra_spec.rb | 22 +- spec/spec_helper.rb | 56 +- spec/support/allocation_stats.rb | 12 +- spec/support/backtraced_exception.rb | 1 + spec/support/feature_helpers.rb | 14 +- spec/support/helpers.rb | 20 +- spec/unit/honeybadger/agent_spec.rb | 188 +++---- spec/unit/honeybadger/backend/base_spec.rb | 6 +- spec/unit/honeybadger/backend/debug_spec.rb | 8 +- spec/unit/honeybadger/backend/null_spec.rb | 9 +- spec/unit/honeybadger/backend/server_spec.rb | 26 +- spec/unit/honeybadger/backend/test_spec.rb | 8 +- spec/unit/honeybadger/backtrace_spec.rb | 114 ++-- .../breadcrumbs/breadcrumb_spec.rb | 8 +- .../honeybadger/breadcrumbs/collector_spec.rb | 47 +- .../log_subscriber_injector_spec.rb | 4 +- .../honeybadger/breadcrumbs/logging_spec.rb | 22 +- .../breadcrumbs/ring_buffer_spec.rb | 12 +- spec/unit/honeybadger/config/env_spec.rb | 30 +- spec/unit/honeybadger/config/ruby_spec.rb | 36 +- spec/unit/honeybadger/config/yaml_spec.rb | 68 +-- spec/unit/honeybadger/config_spec.rb | 95 ++-- spec/unit/honeybadger/counter_spec.rb | 6 +- spec/unit/honeybadger/event_spec.rb | 12 +- spec/unit/honeybadger/events_worker_spec.rb | 34 +- spec/unit/honeybadger/gauge_spec.rb | 6 +- spec/unit/honeybadger/histogram_spec.rb | 4 +- .../instrumentation_helper_spec.rb | 140 ++--- spec/unit/honeybadger/instrumentation_spec.rb | 120 ++-- spec/unit/honeybadger/logging_spec.rb | 18 +- spec/unit/honeybadger/metric_spec.rb | 8 +- spec/unit/honeybadger/metrics_worker_spec.rb | 22 +- spec/unit/honeybadger/notice_spec.rb | 511 +++++++++--------- .../notification_subscriber_spec.rb | 34 +- spec/unit/honeybadger/plugin_spec.rb | 38 +- .../honeybadger/plugins/breadcrumbs_spec.rb | 17 +- .../honeybadger/plugins/delayed_job_spec.rb | 16 +- spec/unit/honeybadger/plugins/faktory_spec.rb | 36 +- spec/unit/honeybadger/plugins/karafka_spec.rb | 16 +- spec/unit/honeybadger/plugins/lambda_spec.rb | 26 +- .../plugins/local_variables_spec.rb | 24 +- .../unit/honeybadger/plugins/net_http_spec.rb | 32 +- .../honeybadger/plugins/passenger_spec.rb | 6 +- spec/unit/honeybadger/plugins/resque_spec.rb | 27 +- .../honeybadger/plugins/shoryuken_spec.rb | 33 +- spec/unit/honeybadger/plugins/sidekiq_spec.rb | 90 +-- .../honeybadger/plugins/sucker_punch_spec.rb | 4 +- spec/unit/honeybadger/plugins/thor_spec.rb | 4 +- .../honeybadger/rack/error_notifier_spec.rb | 31 +- .../honeybadger/rack/user_feedback_spec.rb | 14 +- .../honeybadger/rack/user_informer_spec.rb | 15 +- spec/unit/honeybadger/timer_spec.rb | 6 +- spec/unit/honeybadger/util/http_spec.rb | 72 +-- spec/unit/honeybadger/util/lambda_spec.rb | 2 +- .../honeybadger/util/request_hash_spec.rb | 22 +- .../honeybadger/util/request_payload_spec.rb | 26 +- spec/unit/honeybadger/util/revision_spec.rb | 10 +- spec/unit/honeybadger/util/sanitizer_spec.rb | 126 +++-- spec/unit/honeybadger/util/stats_spec.rb | 28 +- spec/unit/honeybadger/worker_spec.rb | 26 +- spec/unit/honeybadger_spec.rb | 69 ++- tools/allocation_stats.rb | 22 +- tools/benchmark.rb | 8 +- tools/isolation.rb | 4 +- tools/profile.rb | 8 +- tools/release.rb | 14 +- tools/sinatra.rb | 12 +- 187 files changed, 3087 insertions(+), 3053 deletions(-) create mode 100644 .standard.yml diff --git a/.standard.yml b/.standard.yml new file mode 100644 index 000000000..90f768ae7 --- /dev/null +++ b/.standard.yml @@ -0,0 +1,3 @@ +ruby_version: 2.3.0 +fix: true +parallel: true diff --git a/Gemfile b/Gemfile index f680d99a1..ad57ccb94 100644 --- a/Gemfile +++ b/Gemfile @@ -1,22 +1,22 @@ -source 'https://rubygems.org' +source "https://rubygems.org" gemspec -gem 'allocation_stats', platforms: :mri, require: false -gem 'appraisal', '~> 2.1' -gem 'aruba', '~> 2.0' -gem 'rspec', '~> 3.0' +gem "allocation_stats", platforms: :mri, require: false +gem "appraisal", "~> 2.1" +gem "aruba", "~> 2.0" +gem "rspec", "~> 3.0" gem "rspec-its", "~> 1.3.1" -gem 'ruby-prof', platforms: :mri, require: false -gem 'timecop' -gem 'webmock' -gem 'bigdecimal' -gem 'base64' -gem 'mutex_m' +gem "ruby-prof", platforms: :mri, require: false +gem "timecop" +gem "webmock" +gem "bigdecimal" +gem "base64" +gem "mutex_m" # Required by feature specs. -gem 'capistrano' -gem 'rake' +gem "capistrano" +gem "rake" # mathn has moved to a rubygem in Ruby 2.5.0: https://github.com/ruby/mathn platforms :ruby_25 do @@ -26,9 +26,10 @@ end gem "bump", "~> 0.10.0" group :development do - gem 'guard' - gem 'guard-rspec' - gem 'pry' - gem 'pry-byebug', platforms: :mri - gem 'rdoc' + gem "guard" + gem "guard-rspec" + gem "pry" + gem "pry-byebug", platforms: :mri + gem "rdoc" + gem "standard" end diff --git a/Guardfile b/Guardfile index 9ab4bf5b1..0dea4500b 100644 --- a/Guardfile +++ b/Guardfile @@ -1,5 +1,5 @@ -guard :rspec, cmd: 'bundle exec rspec --fail-fast', all_after_pass: false do +guard :rspec, cmd: "bundle exec rspec --fail-fast", all_after_pass: false do watch(%r{^spec/.+_spec\.rb$}) - watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { "spec" } + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" } + watch("spec/spec_helper.rb") { "spec" } end diff --git a/Rakefile b/Rakefile index 91c5b7312..2d7dd8db0 100644 --- a/Rakefile +++ b/Rakefile @@ -1,50 +1,51 @@ # frozen_string_literal: true -require 'rubygems' -require 'bundler/setup' -require 'bump' -require 'appraisal' -require 'honeybadger/version' -require_relative 'tools/release' - -NAME = Dir['*.gemspec'].first.split('.').first.freeze +require "rubygems" +require "bundler/setup" +require "bump" +require "appraisal" +require "honeybadger/version" +require_relative "tools/release" + +NAME = Dir["*.gemspec"].first.split(".").first.freeze VERSION = Honeybadger::VERSION -GEM_FILE = "#{NAME}-#{VERSION}.gem".freeze -GEMSPEC_FILE = "#{NAME}.gemspec".freeze +GEM_FILE = "#{NAME}-#{VERSION}.gem" +GEMSPEC_FILE = "#{NAME}.gemspec" -require 'rdoc/task' +require "rdoc/task" RDoc::Task.new do |rdoc| - rdoc.main = 'README.md' - rdoc.markup = 'tomdoc' - rdoc.rdoc_dir = 'doc' - rdoc.rdoc_files.include('README.md', 'lib/**/*.rb') + rdoc.main = "README.md" + rdoc.markup = "tomdoc" + rdoc.rdoc_dir = "doc" + rdoc.rdoc_files.include("README.md", "lib/**/*.rb") end -require 'rspec/core/rake_task' +require "rspec/core/rake_task" namespace :spec do - desc 'Run unit specs' + desc "Run unit specs" RSpec::Core::RakeTask.new(:units) do |t| - t.pattern = 'spec/unit/**/*_spec.rb' - t.rspec_opts = '--require spec_helper' + t.pattern = "spec/unit/**/*_spec.rb" + t.rspec_opts = "--require spec_helper" end - desc 'Run integration specs' + desc "Run integration specs" RSpec::Core::RakeTask.new(:integrations) do |t| - t.pattern = 'spec/integration/**/*_spec.rb' - t.rspec_opts = '--require spec_helper' + t.pattern = "spec/integration/**/*_spec.rb" + t.rspec_opts = "--require spec_helper" end - desc 'Run feature specs' + desc "Run feature specs" RSpec::Core::RakeTask.new(:features) do |t| - t.pattern = 'spec/features/**/*_spec.rb' - t.rspec_opts = '--require spec_helper' + t.pattern = "spec/features/**/*_spec.rb" + t.rspec_opts = "--require spec_helper" end - desc 'Runs unit and feature specs' + desc "Runs unit and feature specs" task all: [:units, :integrations, :features] end -desc 'Alias for spec:all (default task)' -task spec: :'spec:all' +require "standard/rake" +desc "Alias for spec:all (default task)" +task spec: :"spec:all" task test: :spec -task default: :spec +task default: [:standard, :spec] diff --git a/honeybadger.gemspec b/honeybadger.gemspec index ba2195803..c911f9aab 100644 --- a/honeybadger.gemspec +++ b/honeybadger.gemspec @@ -1,40 +1,40 @@ -require File.expand_path('../lib/honeybadger/version.rb', __FILE__) +require File.expand_path("../lib/honeybadger/version.rb", __FILE__) Gem::Specification.new do |s| - s.name = 'honeybadger' - s.version = Honeybadger::VERSION - s.platform = Gem::Platform::RUBY - s.summary = 'Error reports you can be happy about.' - s.description = 'Make managing application errors a more pleasant experience.' - s.authors = ['Honeybadger Industries LLC'] - s.email = ['support@honeybadger.io'] - s.homepage = 'https://www.honeybadger.io/for/ruby/' - s.license = 'MIT' + s.name = "honeybadger" + s.version = Honeybadger::VERSION + s.platform = Gem::Platform::RUBY + s.summary = "Error reports you can be happy about." + s.description = "Make managing application errors a more pleasant experience." + s.authors = ["Honeybadger Industries LLC"] + s.email = ["support@honeybadger.io"] + s.homepage = "https://www.honeybadger.io/for/ruby/" + s.license = "MIT" s.metadata = { - 'bug_tracker_uri' => 'https://github.com/honeybadger-io/honeybadger-ruby/issues', - 'changelog_uri' => 'https://github.com/honeybadger-io/honeybadger-ruby/blob/master/CHANGELOG.md', - 'documentation_uri' => 'https://docs.honeybadger.io/lib/ruby/', - 'homepage_uri' => 'https://www.honeybadger.io/for/ruby/', - 'source_code_uri' => 'https://github.com/honeybadger-io/honeybadger-ruby' + "bug_tracker_uri" => "https://github.com/honeybadger-io/honeybadger-ruby/issues", + "changelog_uri" => "https://github.com/honeybadger-io/honeybadger-ruby/blob/master/CHANGELOG.md", + "documentation_uri" => "https://docs.honeybadger.io/lib/ruby/", + "homepage_uri" => "https://www.honeybadger.io/for/ruby/", + "source_code_uri" => "https://github.com/honeybadger-io/honeybadger-ruby" } - s.required_ruby_version = '>= 2.3.0' + s.required_ruby_version = ">= 2.3.0" - s.rdoc_options << '--markup=tomdoc' - s.rdoc_options << '--main=README.md' + s.rdoc_options << "--markup=tomdoc" + s.rdoc_options << "--main=README.md" - s.files = Dir['lib/**/*.{rb,erb}'] - s.files += Dir['bin/*'] + s.files = Dir["lib/**/*.{rb,erb}"] + s.files += Dir["bin/*"] # CI installs caches installed gems in vendor/bundle, but we don't want to include them in the gem. - s.files += Dir['vendor/**/*.{rb,rake,cap}'].reject { |file| file.start_with?("vendor/bundle") } - s.files += Dir['resources/**/*.crt'] - s.files += Dir['*.md'] - s.files += ['LICENSE'] + s.files += Dir["vendor/**/*.{rb,rake,cap}"].reject { |file| file.start_with?("vendor/bundle") } + s.files += Dir["resources/**/*.crt"] + s.files += Dir["*.md"] + s.files += ["LICENSE"] - s.require_paths = ['lib', 'vendor/capistrano-honeybadger/lib'] + s.require_paths = ["lib", "vendor/capistrano-honeybadger/lib"] - s.executables << 'honeybadger' + s.executables << "honeybadger" - s.add_dependency 'logger' - s.add_dependency 'ostruct' + s.add_dependency "logger" + s.add_dependency "ostruct" end diff --git a/lib/honeybadger.rb b/lib/honeybadger.rb index ad00a4c43..f215c708b 100644 --- a/lib/honeybadger.rb +++ b/lib/honeybadger.rb @@ -1,13 +1,13 @@ if defined?(::Rails::Railtie) - require 'honeybadger/init/rails' + require "honeybadger/init/rails" elsif defined?(Sinatra::Base) - require 'honeybadger/init/sinatra' + require "honeybadger/init/sinatra" elsif defined?(::Hanami) - require 'honeybadger/init/hanami' + require "honeybadger/init/hanami" else - require 'honeybadger/init/ruby' + require "honeybadger/init/ruby" end if defined?(Rake.application) - require 'honeybadger/init/rake' + require "honeybadger/init/rake" end diff --git a/lib/honeybadger/agent.rb b/lib/honeybadger/agent.rb index 39f74e34c..e2c001f6e 100644 --- a/lib/honeybadger/agent.rb +++ b/lib/honeybadger/agent.rb @@ -1,18 +1,18 @@ -require 'forwardable' - -require 'honeybadger/version' -require 'honeybadger/config' -require 'honeybadger/context_manager' -require 'honeybadger/notice' -require 'honeybadger/event' -require 'honeybadger/plugin' -require 'honeybadger/logging' -require 'honeybadger/worker' -require 'honeybadger/events_worker' -require 'honeybadger/metrics_worker' -require 'honeybadger/breadcrumbs' -require 'honeybadger/registry' -require 'honeybadger/registry_execution' +require "forwardable" + +require "honeybadger/version" +require "honeybadger/config" +require "honeybadger/context_manager" +require "honeybadger/notice" +require "honeybadger/event" +require "honeybadger/plugin" +require "honeybadger/logging" +require "honeybadger/worker" +require "honeybadger/events_worker" +require "honeybadger/metrics_worker" +require "honeybadger/breadcrumbs" +require "honeybadger/registry" +require "honeybadger/registry_execution" module Honeybadger # The Honeybadger agent contains all the methods for interacting with the @@ -62,7 +62,7 @@ def self.instance=(instance) end def initialize(opts = {}) - if opts.kind_of?(Config) + if opts.is_a?(Config) @config = opts opts = {} end @@ -125,8 +125,8 @@ def initialize(opts = {}) # @return [String] UUID reference to the notice within Honeybadger. # @return [false] when ignored. def notify(exception_or_opts = nil, opts = {}, **kwargs) - if !config[:'exceptions.enabled'] - debug { 'disabled feature=notices' } + if !config[:"exceptions.enabled"] + debug { "disabled feature=notices" } return false end @@ -145,11 +145,13 @@ def notify(exception_or_opts = nil, opts = {}, **kwargs) validate_notify_opts!(opts) - add_breadcrumb( - "Honeybadger Notice", - metadata: opts, - category: "notice" - ) if config[:'breadcrumbs.enabled'] + if config[:"breadcrumbs.enabled"] + add_breadcrumb( + "Honeybadger Notice", + metadata: opts, + category: "notice" + ) + end opts[:rack_env] ||= context_manager.get_rack_env opts[:global_context] ||= context_manager.get_context @@ -164,21 +166,21 @@ def notify(exception_or_opts = nil, opts = {}, **kwargs) end unless notice.api_key =~ NOT_BLANK - error { sprintf('Unable to send error report: API key is missing. id=%s', notice.id) } + error { sprintf("Unable to send error report: API key is missing. id=%s", notice.id) } return false end if !opts[:force] && notice.ignore? - debug { sprintf('ignore notice feature=notices id=%s', notice.id) } + debug { sprintf("ignore notice feature=notices id=%s", notice.id) } return false end if notice.halted? - debug { 'halted notice feature=notices' } + debug { "halted notice feature=notices" } return false end - info { sprintf('Reporting error id=%s', notice.id) } + info { sprintf("Reporting error id=%s", notice.id) } if opts[:sync] || config[:sync] send_now(notice) @@ -204,7 +206,7 @@ def notify(exception_or_opts = nil, opts = {}, **kwargs) # otherwise. def check_in(id) # this is to allow check ins even if a url is passed - check_in_id = id.to_s.strip.gsub(/\/$/, '').split('/').last + check_in_id = id.to_s.strip.gsub(/\/$/, "").split("/").last response = backend.check_in(check_in_id) response.success? end @@ -411,7 +413,7 @@ def event(event_type, payload = {}) extra_payload = {}.tap do |p| p[:request_id] = context_manager.get_request_id if context_manager.get_request_id - p[:hostname] = config[:hostname].to_s if config[:'events.attach_hostname'] + p[:hostname] = config[:hostname].to_s if config[:"events.attach_hostname"] end event = Event.new(event_type, extra_payload.merge(payload)) @@ -573,7 +575,7 @@ def instrumentation def validate_notify_opts!(opts) return if opts.has_key?(:exception) return if opts.has_key?(:error_message) - msg = sprintf('`Honeybadger.notify` was called with invalid arguments. You must pass either an Exception or options Hash containing the `:error_message` key. location=%s', caller[caller.size-1]) + msg = sprintf("`Honeybadger.notify` was called with invalid arguments. You must pass either an Exception or options Hash containing the `:error_message` key. location=%s", caller[caller.size - 1]) raise ArgumentError.new(msg) if config.dev? warn(msg) end diff --git a/lib/honeybadger/backend.rb b/lib/honeybadger/backend.rb index 27ef61290..49a57bf3b 100644 --- a/lib/honeybadger/backend.rb +++ b/lib/honeybadger/backend.rb @@ -1,10 +1,10 @@ -require 'forwardable' +require "forwardable" -require 'honeybadger/backend/base' -require 'honeybadger/backend/server' -require 'honeybadger/backend/test' -require 'honeybadger/backend/null' -require 'honeybadger/backend/debug' +require "honeybadger/backend/base" +require "honeybadger/backend/server" +require "honeybadger/backend/test" +require "honeybadger/backend/null" +require "honeybadger/backend/debug" module Honeybadger # @api private diff --git a/lib/honeybadger/backend/base.rb b/lib/honeybadger/backend/base.rb index a2ce5022d..62e49db40 100644 --- a/lib/honeybadger/backend/base.rb +++ b/lib/honeybadger/backend/base.rb @@ -1,8 +1,8 @@ -require 'forwardable' -require 'net/http' -require 'json' +require "forwardable" +require "net/http" +require "json" -require 'honeybadger/logging' +require "honeybadger/logging" module Honeybadger module Backend @@ -34,7 +34,7 @@ class Response # @param [String] message The String message returned by the server (or # set by the backend in the case of an :error code). def initialize(*args) - if (response = args.first).kind_of?(Net::HTTPResponse) + if (response = args.first).is_a?(Net::HTTPResponse) @code, @body, @message = response.code.to_i, response.body.to_s, response.message else @code, @body, @message = args @@ -62,7 +62,7 @@ def error_message def parse_error(body) return unless body =~ NOT_BLANK obj = JSON.parse(body) - return obj['error'] if obj.kind_of?(Hash) + obj["error"] if obj.is_a?(Hash) rescue JSON::ParserError nil end @@ -88,7 +88,7 @@ def initialize(config) # # @raise NotImplementedError def notify(feature, payload) - raise NotImplementedError, 'must define #notify on subclass.' + raise NotImplementedError, "must define #notify on subclass." end # Does a check in using the input id. @@ -97,7 +97,7 @@ def notify(feature, payload) # # @raise NotImplementedError def check_in(id) - raise NotImplementedError, 'must define #check_in on subclass.' + raise NotImplementedError, "must define #check_in on subclass." end # Track a deployment diff --git a/lib/honeybadger/backend/debug.rb b/lib/honeybadger/backend/debug.rb index 4d557b40a..c1c35a86b 100644 --- a/lib/honeybadger/backend/debug.rb +++ b/lib/honeybadger/backend/debug.rb @@ -1,4 +1,4 @@ -require 'honeybadger/backend/null' +require "honeybadger/backend/null" module Honeybadger module Backend @@ -8,19 +8,19 @@ module Backend class Debug < Null def notify(feature, payload) logger.unknown("notifying debug backend of feature=#{feature}\n\t#{payload.to_json}") - return Response.new(ENV['DEBUG_BACKEND_STATUS'].to_i, nil) if ENV['DEBUG_BACKEND_STATUS'] + return Response.new(ENV["DEBUG_BACKEND_STATUS"].to_i, nil) if ENV["DEBUG_BACKEND_STATUS"] super end def check_in(id) logger.unknown("checking in debug backend with id=#{id}") - return Response.new(ENV['DEBUG_BACKEND_STATUS'].to_i, nil) if ENV['DEBUG_BACKEND_STATUS'] + return Response.new(ENV["DEBUG_BACKEND_STATUS"].to_i, nil) if ENV["DEBUG_BACKEND_STATUS"] super end def event(payload) logger.unknown("sending event to debug backend with event=#{payload.to_json}") - return Response.new(ENV['DEBUG_BACKEND_STATUS'].to_i, nil) if ENV['DEBUG_BACKEND_STATUS'] + return Response.new(ENV["DEBUG_BACKEND_STATUS"].to_i, nil) if ENV["DEBUG_BACKEND_STATUS"] super end end diff --git a/lib/honeybadger/backend/null.rb b/lib/honeybadger/backend/null.rb index 3f2af2d8c..4d5c13d5a 100644 --- a/lib/honeybadger/backend/null.rb +++ b/lib/honeybadger/backend/null.rb @@ -1,11 +1,11 @@ -require 'honeybadger/backend/base' +require "honeybadger/backend/base" module Honeybadger module Backend class Null < Base class StubbedResponse < Response def initialize - super(:stubbed, '{}'.freeze) + super(:stubbed, "{}".freeze) end def success? diff --git a/lib/honeybadger/backend/server.rb b/lib/honeybadger/backend/server.rb index 5100a2355..a31161271 100644 --- a/lib/honeybadger/backend/server.rb +++ b/lib/honeybadger/backend/server.rb @@ -1,20 +1,20 @@ -require 'net/http' -require 'json' -require 'zlib' -require 'openssl' +require "net/http" +require "json" +require "zlib" +require "openssl" -require 'honeybadger/backend/base' -require 'honeybadger/util/http' +require "honeybadger/backend/base" +require "honeybadger/util/http" module Honeybadger module Backend class Server < Base ENDPOINTS = { - notices: '/v1/notices'.freeze, - deploys: '/v1/deploys'.freeze, + notices: "/v1/notices".freeze, + deploys: "/v1/deploys".freeze }.freeze - CHECK_IN_ENDPOINT = '/v1/check_in'.freeze - EVENTS_ENDPOINT = '/v1/events'.freeze + CHECK_IN_ENDPOINT = "/v1/check_in".freeze + EVENTS_ENDPOINT = "/v1/events".freeze HTTP_ERRORS = Util::HTTP::ERRORS @@ -64,7 +64,7 @@ def event(payload) def payload_headers(payload) if payload.respond_to?(:api_key) && payload.api_key { - 'X-API-Key' => payload.api_key + "X-API-Key" => payload.api_key } end end diff --git a/lib/honeybadger/backend/test.rb b/lib/honeybadger/backend/test.rb index e8ecf9524..c57d0a695 100644 --- a/lib/honeybadger/backend/test.rb +++ b/lib/honeybadger/backend/test.rb @@ -1,4 +1,4 @@ -require 'honeybadger/backend/null' +require "honeybadger/backend/null" module Honeybadger module Backend @@ -10,7 +10,7 @@ class Test < Null # # @return [Hash] Notifications hash. def self.notifications - @notifications ||= Hash.new {|h,k| h[k] = [] } + @notifications ||= Hash.new { |h, k| h[k] = [] } end # The event list. diff --git a/lib/honeybadger/backtrace.rb b/lib/honeybadger/backtrace.rb index 6e5baaf34..4318d043b 100644 --- a/lib/honeybadger/backtrace.rb +++ b/lib/honeybadger/backtrace.rb @@ -1,4 +1,4 @@ -require 'json' +require "json" module Honeybadger # @api private @@ -45,21 +45,19 @@ def self.parse(unparsed_line, opts = {}) file, number, method = match[1], match[2], match[3] filtered_args = [fmatch[1], fmatch[2], fmatch[3]] new(file, number, method, *filtered_args, opts.fetch(:source_radius, 2)) - else - nil end end def initialize(file, number, method, filtered_file = file, - filtered_number = number, filtered_method = method, - source_radius = 2) - self.filtered_file = filtered_file + filtered_number = number, filtered_method = method, + source_radius = 2) + self.filtered_file = filtered_file self.filtered_number = filtered_number self.filtered_method = filtered_method - self.file = file - self.number = number - self.method = method - self.source_radius = source_radius + self.file = file + self.number = number + self.method = method + self.source_radius = source_radius end # Reconstructs the line in a readable fashion. @@ -72,7 +70,7 @@ def ==(other) end def inspect - "" + "" end # Determines if this line is part of the application trace or not. @@ -102,7 +100,10 @@ def get_source(file, number, radius = 2) l = 0 File.open(file) do |f| - start.times { f.gets ; l += 1 } + start.times { + f.gets + l += 1 + } return Hash[duration.times.map { (line = f.gets) ? [(l += 1), line] : nil }.compact] end else @@ -121,7 +122,7 @@ def self.parse(ruby_backtrace, opts = {}) Line.parse(unparsed_line.to_s, opts) end.compact - instance = new(lines) + new(lines) end def initialize(lines) @@ -133,9 +134,9 @@ def initialize(lines) # # Returns array containing backtrace lines. def to_ary - lines.take(1000).map { |l| { :number => l.filtered_number, :file => l.filtered_file, :method => l.filtered_method, :source => l.source } } + lines.take(1000).map { |l| {number: l.filtered_number, file: l.filtered_file, method: l.filtered_method, source: l.source} } end - alias :to_a :to_ary + alias_method :to_a, :to_ary # JSON support. # diff --git a/lib/honeybadger/breadcrumbs.rb b/lib/honeybadger/breadcrumbs.rb index eccd8dce3..b868c9694 100644 --- a/lib/honeybadger/breadcrumbs.rb +++ b/lib/honeybadger/breadcrumbs.rb @@ -1,6 +1,6 @@ -require 'honeybadger/breadcrumbs/ring_buffer' -require 'honeybadger/breadcrumbs/breadcrumb' -require 'honeybadger/breadcrumbs/collector' +require "honeybadger/breadcrumbs/ring_buffer" +require "honeybadger/breadcrumbs/breadcrumb" +require "honeybadger/breadcrumbs/collector" module Honeybadger module Breadcrumbs diff --git a/lib/honeybadger/breadcrumbs/active_support.rb b/lib/honeybadger/breadcrumbs/active_support.rb index 12a50f8de..09ce90767 100644 --- a/lib/honeybadger/breadcrumbs/active_support.rb +++ b/lib/honeybadger/breadcrumbs/active_support.rb @@ -1,4 +1,4 @@ -require 'honeybadger/util/sql' +require "honeybadger/util/sql" module Honeybadger module Breadcrumbs @@ -49,7 +49,7 @@ def self.default_notifications "perform_start.active_job" => { message: "Active Job Perform Start", select_keys: [], - category: "job", + category: "job" }, # ActiveSupport Actions @@ -67,32 +67,32 @@ def self.default_notifications # "halted_callback.action_controller" => { message: "Action Controller Callback Halted", - category: "request", + category: "request" }, "process_action.action_controller" => { message: "Action Controller Action Process", select_keys: [:controller, :action, :format, :method, :path, :status, :view_runtime, :db_runtime], - category: "request", + category: "request" }, "start_processing.action_controller" => { message: "Action Controller Start Process", select_keys: [:controller, :action, :format, :method, :path], - category: "request", + category: "request" }, "redirect_to.action_controller" => { message: "Action Controller Redirect", - category: "request", + category: "request" }, # View Actions # "render_template.action_view" => { message: "Action View Template Render", - category: "render", + category: "render" }, "render_partial.action_view" => { message: "Action View Partial Render", - category: "render", + category: "render" }, # Mailer actions diff --git a/lib/honeybadger/breadcrumbs/breadcrumb.rb b/lib/honeybadger/breadcrumbs/breadcrumb.rb index 56de4f182..2e7025a86 100644 --- a/lib/honeybadger/breadcrumbs/breadcrumb.rb +++ b/lib/honeybadger/breadcrumbs/breadcrumb.rb @@ -1,4 +1,4 @@ -require 'time' +require "time" module Honeybadger module Breadcrumbs @@ -32,7 +32,6 @@ def <=>(other) to_h <=> other.to_h end - # Is the Breadcrumb active or not. Inactive Breadcrumbs not be included # with any outgoing payloads. # diff --git a/lib/honeybadger/breadcrumbs/collector.rb b/lib/honeybadger/breadcrumbs/collector.rb index 804a0985f..e518fd7ef 100644 --- a/lib/honeybadger/breadcrumbs/collector.rb +++ b/lib/honeybadger/breadcrumbs/collector.rb @@ -1,4 +1,4 @@ -require 'forwardable' +require "forwardable" module Honeybadger module Breadcrumbs @@ -35,7 +35,7 @@ def initialize(config, buffer = RingBuffer.new) # # @return [self] Filtered breadcrumbs def add!(breadcrumb) - return unless @config[:'breadcrumbs.enabled'] + return unless @config[:"breadcrumbs.enabled"] @buffer.add!(breadcrumb) self @@ -48,7 +48,7 @@ def add!(breadcrumb) # block returns a falsy value # def drop_previous_breadcrumb_if - @buffer.drop if (previous && block_given? && yield(previous)) + @buffer.drop if previous && block_given? && yield(previous) end # All active breadcrumbs you want to remove a breadcrumb from the trail, @@ -61,7 +61,7 @@ def trail def to_h { - enabled: @config[:'breadcrumbs.enabled'], + enabled: @config[:"breadcrumbs.enabled"], trail: trail.map(&:to_h) } end diff --git a/lib/honeybadger/breadcrumbs/logging.rb b/lib/honeybadger/breadcrumbs/logging.rb index d656fcdce..dc229247e 100644 --- a/lib/honeybadger/breadcrumbs/logging.rb +++ b/lib/honeybadger/breadcrumbs/logging.rb @@ -7,10 +7,10 @@ def add(severity, message = nil, progname = nil) org_severity, org_message, org_progname = severity, message, progname if defined?(Dry::Logger::Entry) && progname.is_a?(Dry::Logger::Entry) # Hanami uses dry-logger message, progname = progname.message || progname.exception, progname.progname - else - message, progname = [progname, nil] if message.nil? + elsif message.nil? + message, progname = [progname, nil] end - message = message && message.to_s.strip + message &&= message.to_s.strip unless should_ignore_log?(message, progname) Honeybadger.add_breadcrumb(message, category: :log, metadata: { severity: format_severity(severity), @@ -25,9 +25,9 @@ def add(severity, message = nil, progname = nil) def should_ignore_log?(message, progname) message.nil? || - message == "" || - Thread.current[:__hb_within_log_subscriber] || - progname == "honeybadger" + message == "" || + Thread.current[:__hb_within_log_subscriber] || + progname == "honeybadger" end end @@ -39,7 +39,7 @@ def should_ignore_log?(message, progname) # class that provides LogSubscriber events, we want to filter out those # logs as they just become noise. module LogSubscriberInjector - %w(info debug warn error fatal unknown).each do |level| + %w[info debug warn error fatal unknown].each do |level| define_method(level) do |*args, &block| begin Thread.current[:__hb_within_log_subscriber] = true @@ -52,4 +52,3 @@ module LogSubscriberInjector end end end - diff --git a/lib/honeybadger/cli.rb b/lib/honeybadger/cli.rb index 641bc9bd1..b40c67171 100644 --- a/lib/honeybadger/cli.rb +++ b/lib/honeybadger/cli.rb @@ -1,8 +1,8 @@ -$:.unshift(File.expand_path('../../../vendor/cli', __FILE__)) +$:.unshift(File.expand_path("../../../vendor/cli", __FILE__)) -require 'thor' +require "thor" -require 'honeybadger/cli/main' +require "honeybadger/cli/main" module Honeybadger # @api private diff --git a/lib/honeybadger/cli/deploy.rb b/lib/honeybadger/cli/deploy.rb index 6a4489e3a..9ad5e5c49 100644 --- a/lib/honeybadger/cli/deploy.rb +++ b/lib/honeybadger/cli/deploy.rb @@ -1,7 +1,7 @@ -require 'forwardable' -require 'honeybadger/cli/main' -require 'honeybadger/cli/helpers' -require 'honeybadger/util/http' +require "forwardable" +require "honeybadger/cli/main" +require "honeybadger/cli/helpers" +require "honeybadger/util/http" module Honeybadger module CLI @@ -19,9 +19,9 @@ def initialize(options, args, config) def run payload = { environment: config.get(:env), - revision: options['revision'], - repository: options['repository'], - local_username: options['user'] + revision: options["revision"], + repository: options["repository"], + local_username: options["user"] } response = config.backend.notify(:deploys, payload) diff --git a/lib/honeybadger/cli/exec.rb b/lib/honeybadger/cli/exec.rb index 68c355529..86ed73cb7 100644 --- a/lib/honeybadger/cli/exec.rb +++ b/lib/honeybadger/cli/exec.rb @@ -1,12 +1,12 @@ -require 'erb' -require 'forwardable' -require 'honeybadger/cli/main' -require 'honeybadger/cli/helpers' -require 'honeybadger/util/http' -require 'honeybadger/util/stats' -require 'open3' -require 'ostruct' -require 'thor/shell' +require "erb" +require "forwardable" +require "honeybadger/cli/main" +require "honeybadger/cli/helpers" +require "honeybadger/util/http" +require "honeybadger/util/stats" +require "open3" +require "ostruct" +require "thor/shell" module Honeybadger module CLI @@ -14,34 +14,34 @@ class Exec extend Forwardable include Helpers::BackendCmd - FAILED_TEMPLATE = <<-MSG -Honeybadger detected failure or error output for the command: -`<%= args.join(' ') %>` - -PROCESS ID: <%= pid %> - -RESULT CODE: <%= code %> - -ERROR OUTPUT: -<%= stderr %> - -STANDARD OUTPUT: -<%= stdout %> -MSG - - NO_EXEC_TEMPLATE = <<-MSG -Honeybadger failed to execute the following command: -`<%= args.join(' ') %>` - -The command was not executable. Try adjusting permissions on the file. -MSG - - NOT_FOUND_TEMPLATE = <<-MSG -Honeybadger failed to execute the following command: -`<%= args.join(' ') %>` - -The command was not found. Make sure it exists in your PATH. -MSG + FAILED_TEMPLATE = <<~MSG + Honeybadger detected failure or error output for the command: + `<%= args.join(' ') %>` + + PROCESS ID: <%= pid %> + + RESULT CODE: <%= code %> + + ERROR OUTPUT: + <%= stderr %> + + STANDARD OUTPUT: + <%= stdout %> + MSG + + NO_EXEC_TEMPLATE = <<~MSG + Honeybadger failed to execute the following command: + `<%= args.join(' ') %>` + + The command was not executable. Try adjusting permissions on the file. + MSG + + NOT_FOUND_TEMPLATE = <<~MSG + Honeybadger failed to execute the following command: + `<%= args.join(' ') %>` + + The command was not found. Make sure it exists in your PATH. + MSG def initialize(options, args, config) @options = options @@ -59,17 +59,17 @@ def run api_key: config.get(:api_key), notifier: NOTIFIER, error: { - class: 'honeybadger exec error', + class: "honeybadger exec error", message: result.msg }, request: { component: executable, context: { - command: args.join(' '), + command: args.join(" "), code: result.code, pid: result.pid, pwd: Dir.pwd, - path: ENV['PATH'] + path: ENV["PATH"] } }, server: { @@ -112,7 +112,7 @@ def quiet? end def exec_cmd - stdout, stderr, status = Open3.capture3(args.join(' ')) + stdout, stderr, status = Open3.capture3(args.join(" ")) success = status.success? && stderr =~ BLANK pid = status.pid diff --git a/lib/honeybadger/cli/helpers.rb b/lib/honeybadger/cli/helpers.rb index 05589d36d..e96eb2a25 100644 --- a/lib/honeybadger/cli/helpers.rb +++ b/lib/honeybadger/cli/helpers.rb @@ -3,24 +3,24 @@ module CLI module Helpers module BackendCmd def error_message(response) - host = config.get(:'connection.host') - <<-MSG -!! --- Honeybadger request failed --------------------------------------------- !! - -We encountered an error when contacting the server: - - #{response.error_message} - -To fix this issue, please try the following: - - - Make sure the gem is configured properly. - - Retry executing this command a few times. - - Make sure you can connect to #{host} (`curl https://#{host}/v1/notices`). - - Email support@honeybadger.io for help. Include as much debug info as you - can for a faster resolution! - -!! --- End -------------------------------------------------------------------- !! -MSG + host = config.get(:"connection.host") + <<~MSG + !! --- Honeybadger request failed --------------------------------------------- !! + + We encountered an error when contacting the server: + + #{response.error_message} + + To fix this issue, please try the following: + + - Make sure the gem is configured properly. + - Retry executing this command a few times. + - Make sure you can connect to #{host} (`curl https://#{host}/v1/notices`). + - Email support@honeybadger.io for help. Include as much debug info as you + can for a faster resolution! + + !! --- End -------------------------------------------------------------------- !! + MSG end end end diff --git a/lib/honeybadger/cli/heroku.rb b/lib/honeybadger/cli/heroku.rb index 6c3cdfe7b..ed350fa9b 100644 --- a/lib/honeybadger/cli/heroku.rb +++ b/lib/honeybadger/cli/heroku.rb @@ -1,50 +1,50 @@ module Honeybadger module CLI class Heroku < Thor - class_option :app, aliases: :'-a', type: :string, default: nil, desc: 'Specify optional Heroku APP' + class_option :app, aliases: :"-a", type: :string, default: nil, desc: "Specify optional Heroku APP" - desc 'install_deploy_notification', 'Install Heroku deploy notifications addon' - option :api_key, aliases: :'-k', type: :string, desc: 'Api key of your Honeybadger application' - option :environment, aliases: :'-e', type: :string, desc: 'Environment of your Heroku application (i.e. "production", "staging")' + desc "install_deploy_notification", "Install Heroku deploy notifications addon" + option :api_key, aliases: :"-k", type: :string, desc: "Api key of your Honeybadger application" + option :environment, aliases: :"-e", type: :string, desc: 'Environment of your Heroku application (i.e. "production", "staging")' def install_deploy_notification - app = options.has_key?('app') ? options['app'] : detect_heroku_app(false) - rails_env = options['environment'] || heroku_var('RAILS_ENV', app) - api_key = options['api_key'] || heroku_var('HONEYBADGER_API_KEY', app) + app = options.has_key?("app") ? options["app"] : detect_heroku_app(false) + rails_env = options["environment"] || heroku_var("RAILS_ENV", app) + api_key = options["api_key"] || heroku_var("HONEYBADGER_API_KEY", app) unless api_key =~ /\S/ say("Unable to detect your API key from Heroku.", :red) - say('Have you configured multiple Heroku apps? Try using --app APP', :red) unless app + say("Have you configured multiple Heroku apps? Try using --app APP", :red) unless app exit(1) end unless rails_env =~ /\S/ say("Unable to detect your environment from Heroku. Use --environment ENVIRONMENT.", :red) - say('Have you configured multiple Heroku apps? Try using --app APP', :red) unless app + say("Have you configured multiple Heroku apps? Try using --app APP", :red) unless app exit(1) end - cmd = %Q(heroku webhooks:add -i api:release -l notify -u "https://api.honeybadger.io/v1/deploys/heroku?environment=#{rails_env}&api_key=#{api_key}"#{app ? " --app #{app}" : ''}) + cmd = %(heroku webhooks:add -i api:release -l notify -u "https://api.honeybadger.io/v1/deploys/heroku?environment=#{rails_env}&api_key=#{api_key}"#{app ? " --app #{app}" : ""}) say("Running: `#{cmd}`") say(run(cmd)) end - desc 'install API_KEY', 'Install Honeybadger on Heroku using API_KEY' + desc "install API_KEY", "Install Honeybadger on Heroku using API_KEY" def install(api_key) say("Installing Honeybadger #{VERSION} for Heroku") app = options[:app] || detect_heroku_app(false) say("Adding config HONEYBADGER_API_KEY=#{api_key} to Heroku.", :magenta) - unless write_heroku_env({'HONEYBADGER_API_KEY' => api_key}, app) - say('Unable to update heroku config. You may need to specify an app name with --app APP', :red) + unless write_heroku_env({"HONEYBADGER_API_KEY" => api_key}, app) + say("Unable to update heroku config. You may need to specify an app name with --app APP", :red) exit(1) end - if env = heroku_var('RAILS_ENV', app, heroku_var('RACK_ENV', app)) - say('Installing deploy notification addon', :magenta) - invoke :install_deploy_notification, [], { app: app, api_key: api_key, environment: env } + if env = heroku_var("RAILS_ENV", app, heroku_var("RACK_ENV", app)) + say("Installing deploy notification addon", :magenta) + invoke :install_deploy_notification, [], {app: app, api_key: api_key, environment: env} else - say('Skipping deploy notification installation: we were unable to determine the environment name from your Heroku app.', :yellow) + say("Skipping deploy notification installation: we were unable to determine the environment name from your Heroku app.", :yellow) say("To install manually, try `honeybadger heroku install_deploy_notification#{app ? " -a #{app}" : ""} -k #{api_key} --environment ENVIRONMENT`", :yellow) end @@ -60,13 +60,13 @@ def install(api_key) # # Returns the String app name if detected, otherwise nil. def detect_heroku_app(prompt_on_default = true) - apps, git_config = {}, File.join(Dir.pwd, '.git', 'config') + apps, git_config = {}, File.join(Dir.pwd, ".git", "config") if File.exist?(git_config) - require 'inifile' + require "inifile" ini = IniFile.load(git_config) ini.each_section do |section| - if match = section.match(/remote \"(?.+)\"/) - url = ini[section]['url'] + if match = section.match(/remote "(?.+)"/) + url = ini[section]["url"] if url_match = url.match(/heroku\.com:(?.+)\.git$/) apps[match[:remote]] = url_match[:app] end @@ -84,10 +84,10 @@ def detect_heroku_app(prompt_on_default = true) end elsif apps.size > 1 say "We detected the following Heroku apps:" - apps.each_with_index {|a,i| say "\s\s#{i+1}. #{a[1]}" } - say "\s\s#{apps.size+1}. Use default" - say "Please select an option (1-#{apps.size+1}):" - apps.values[STDIN.gets.chomp.to_i-1] + apps.each_with_index { |a, i| say "\s\s#{i + 1}. #{a[1]}" } + say "\s\s#{apps.size + 1}. Use default" + say "Please select an option (1-#{apps.size + 1}):" + apps.values[STDIN.gets.chomp.to_i - 1] end end end @@ -97,13 +97,13 @@ def run(cmd) end def heroku_var(var, app_name, default = nil) - app = app_name ? "--app #{app_name}" : '' + app = app_name ? "--app #{app_name}" : "" result = run("heroku config:get #{var} #{app} 2> /dev/null").strip - result.split.find(lambda { default }) {|x| x =~ /\S/ } + result.split.find(lambda { default }) { |x| x =~ /\S/ } end def read_heroku_env(app = nil) - cmd = ['heroku config'] + cmd = ["heroku config"] cmd << "--app #{app}" if app output = run(cmd.join("\s")) return false unless $?.to_i == 0 @@ -112,14 +112,14 @@ def read_heroku_env(app = nil) def set_env_from_heroku(app = nil) return false unless env = read_heroku_env(app) - env.each_pair do |k,v| + env.each_pair do |k, v| ENV[k] ||= v end end def write_heroku_env(env, app = nil) cmd = ["heroku config:set"] - Hash(env).each_pair {|k,v| cmd << "#{k}=#{v}" } + Hash(env).each_pair { |k, v| cmd << "#{k}=#{v}" } cmd << "--app #{app}" if app run(cmd.join("\s")) $?.to_i == 0 diff --git a/lib/honeybadger/cli/install.rb b/lib/honeybadger/cli/install.rb index 33de0a9d3..f3a6b9b63 100644 --- a/lib/honeybadger/cli/install.rb +++ b/lib/honeybadger/cli/install.rb @@ -1,7 +1,7 @@ -require 'forwardable' -require 'honeybadger/cli/main' -require 'honeybadger/cli/test' -require 'pathname' +require "forwardable" +require "honeybadger/cli/main" +require "honeybadger/cli/test" +require "pathname" module Honeybadger module CLI @@ -18,15 +18,15 @@ def run say("Installing Honeybadger #{VERSION}") begin - require File.join(Dir.pwd, 'config', 'application.rb') + require File.join(Dir.pwd, "config", "application.rb") raise LoadError unless defined?(::Rails.application) root = Rails.root - config_root = root.join('config') + config_root = root.join("config") rescue LoadError root = config_root = Pathname.new(Dir.pwd) end - config_path = config_root.join('honeybadger.yml') + config_path = config_root.join("honeybadger.yml") if config_path.exist? say("You're already on Honeybadger, so you're all set.", :yellow) @@ -45,52 +45,52 @@ def run default_env = defined?(::Rails.application) ? "Rails.env" : "ENV['RUBY_ENV'] || ENV['RACK_ENV']" default_root = defined?(::Rails.application) ? "Rails.root.to_s" : "Dir.pwd" - File.open(path, 'w+') do |file| - file.write(<<-CONFIG) ---- -# For more options, see https://docs.honeybadger.io/lib/ruby/gem-reference/configuration - -api_key: '#{api_key}' - -# The environment your app is running in. -env: "<%= #{default_env} %>" - -# The absolute path to your project folder. -root: "<%= #{default_root} %>" - -# Honeybadger won't report errors in these environments. -development_environments: -- test -- development -- cucumber - -# By default, Honeybadger won't report errors in the development_environments. -# You can override this by explicitly setting report_data to true or false. -# report_data: true - -# The current Git revision of your project. Defaults to the last commit hash. -# revision: null - -# Enable verbose debug logging (useful for troubleshooting). -debug: false - -# Enable Honeybadger Insights -insights: - enabled: #{options["insights"]} -CONFIG + File.open(path, "w+") do |file| + file.write(<<~CONFIG) + --- + # For more options, see https://docs.honeybadger.io/lib/ruby/gem-reference/configuration + + api_key: '#{api_key}' + + # The environment your app is running in. + env: "<%= #{default_env} %>" + + # The absolute path to your project folder. + root: "<%= #{default_root} %>" + + # Honeybadger won't report errors in these environments. + development_environments: + - test + - development + - cucumber + + # By default, Honeybadger won't report errors in the development_environments. + # You can override this by explicitly setting report_data to true or false. + # report_data: true + + # The current Git revision of your project. Defaults to the last commit hash. + # revision: null + + # Enable verbose debug logging (useful for troubleshooting). + debug: false + + # Enable Honeybadger Insights + insights: + enabled: #{options["insights"]} + CONFIG if (connection = options.slice("host", "ui_host")).any? file.puts("\n# Override hosts\nconnection:") - connection.each {|k,v| file.puts(" #{k}: '#{v}'") } + connection.each { |k, v| file.puts(" #{k}: '#{v}'") } end end end - if (capfile = root.join('Capfile')).exist? - if capfile.read.match(/honeybadger/) + if (capfile = root.join("Capfile")).exist? + if capfile.read =~ /honeybadger/ say("Detected Honeybadger in Capfile; skipping Capistrano installation.", :yellow) else say("Appending Capistrano tasks to: #{capfile}", :yellow) - File.open(capfile, 'a') do |f| + File.open(capfile, "a") do |f| f.puts("\nrequire 'capistrano/honeybadger'") end end diff --git a/lib/honeybadger/cli/main.rb b/lib/honeybadger/cli/main.rb index d62b805cc..39fa4c73d 100644 --- a/lib/honeybadger/cli/main.rb +++ b/lib/honeybadger/cli/main.rb @@ -1,54 +1,54 @@ -require 'honeybadger/cli/deploy' -require 'honeybadger/cli/exec' -require 'honeybadger/cli/heroku' -require 'honeybadger/cli/install' -require 'honeybadger/cli/notify' -require 'honeybadger/cli/test' -require 'honeybadger/config' -require 'honeybadger/config/defaults' -require 'honeybadger/ruby' -require 'honeybadger/util/http' -require 'honeybadger/version' -require 'logger' +require "honeybadger/cli/deploy" +require "honeybadger/cli/exec" +require "honeybadger/cli/heroku" +require "honeybadger/cli/install" +require "honeybadger/cli/notify" +require "honeybadger/cli/test" +require "honeybadger/config" +require "honeybadger/config/defaults" +require "honeybadger/ruby" +require "honeybadger/util/http" +require "honeybadger/version" +require "logger" module Honeybadger module CLI BLANK = /\A\s*\z/ NOTIFIER = { - name: 'honeybadger-ruby (cli)'.freeze, - url: 'https://github.com/honeybadger-io/honeybadger-ruby'.freeze, + name: "honeybadger-ruby (cli)".freeze, + url: "https://github.com/honeybadger-io/honeybadger-ruby".freeze, version: VERSION, language: nil }.freeze class Main < Thor def self.project_options - option :api_key, required: false, aliases: :'-k', type: :string, desc: 'Api key of your Honeybadger application' - option :environment, required: false, aliases: [:'-e', :'-env'], type: :string, desc: 'Environment this command is being executed in (i.e. "production", "staging")' - option :skip_rails_load, required: false, type: :boolean, desc: 'Flag to skip rails initialization' + option :api_key, required: false, aliases: :"-k", type: :string, desc: "Api key of your Honeybadger application" + option :environment, required: false, aliases: [:"-e", :"-env"], type: :string, desc: 'Environment this command is being executed in (i.e. "production", "staging")' + option :skip_rails_load, required: false, type: :boolean, desc: "Flag to skip rails initialization" end def help(*args, &block) if args.size == 0 - say(<<-WELCOME) -⚡ Honeybadger v#{VERSION} - -Honeybadger is your favorite error tracker for Ruby. When your app raises an -exception we notify you with all the context you need to fix it. - -The Honeybadger CLI provides tools for interacting with Honeybadger via the -command line. - -If you need support, please drop us a line: support@honeybadger.io - -WELCOME + say(<<~WELCOME) + ⚡ Honeybadger v#{VERSION} + + Honeybadger is your favorite error tracker for Ruby. When your app raises an + exception we notify you with all the context you need to fix it. + + The Honeybadger CLI provides tools for interacting with Honeybadger via the + command line. + + If you need support, please drop us a line: support@honeybadger.io + + WELCOME end super end - desc 'install API_KEY', 'Install Honeybadger into a new project' - option :insights, type: :boolean, aliases: :'-i', default: false, desc: 'Enable Honeybadger Insights' + desc "install API_KEY", "Install Honeybadger into a new project" + option :insights, type: :boolean, aliases: :"-i", default: false, desc: "Enable Honeybadger Insights" option :host, type: :string option :ui_host, type: :string def install(api_key) @@ -58,9 +58,9 @@ def install(api_key) exit(1) end - desc 'test', 'Send a test notification from Honeybadger' - option :dry_run, type: :boolean, aliases: :'-d', default: false, desc: 'Skip sending data to Honeybadger' - option :file, type: :string, aliases: :'-f', default: nil, desc: 'Write the output to FILE' + desc "test", "Send a test notification from Honeybadger" + option :dry_run, type: :boolean, aliases: :"-d", default: false, desc: "Skip sending data to Honeybadger" + option :file, type: :string, aliases: :"-f", default: nil, desc: "Write the output to FILE" def test Test.new(options).run rescue => e @@ -68,11 +68,11 @@ def test exit(1) end - desc 'deploy', 'Notify Honeybadger of deployment' + desc "deploy", "Notify Honeybadger of deployment" project_options - option :repository, required: true, type: :string, aliases: :'-r', desc: 'The address of your repository' - option :revision, required: true, type: :string, aliases: :'-s', desc: 'The revision/sha that is being deployed' - option :user, required: true, type: :string, aliases: :'-u', default: ENV['USER'] || ENV['USERNAME'], desc: 'The local user who is deploying' + option :repository, required: true, type: :string, aliases: :"-r", desc: "The address of your repository" + option :revision, required: true, type: :string, aliases: :"-s", desc: "The revision/sha that is being deployed" + option :user, required: true, type: :string, aliases: :"-u", default: ENV["USER"] || ENV["USERNAME"], desc: "The local user who is deploying" def deploy config = build_config(options) @@ -87,15 +87,15 @@ def deploy exit(1) end - desc 'notify', 'Notify Honeybadger of an error' + desc "notify", "Notify Honeybadger of an error" project_options - option :class, required: true, type: :string, aliases: :'-c', default: 'CLI Notification', desc: 'The class name of the error. (Default: CLI Notification)' - option :message, required: true, type: :string, aliases: :'-m', desc: 'The error message.' - option :action, required: false, type: :string, aliases: :'-a', desc: 'The action.' - option :component, required: false, type: :string, aliases: :'-C', desc: 'The component.' - option :fingerprint, required: false, type: :string, aliases: :'-f', desc: 'The fingerprint.' - option :tags, required: false, type: :string, aliases: :'-t', desc: 'The tags.' - option :url, required: false, type: :string, aliases: :'-u', desc: 'The URL.' + option :class, required: true, type: :string, aliases: :"-c", default: "CLI Notification", desc: "The class name of the error. (Default: CLI Notification)" + option :message, required: true, type: :string, aliases: :"-m", desc: "The error message." + option :action, required: false, type: :string, aliases: :"-a", desc: "The action." + option :component, required: false, type: :string, aliases: :"-C", desc: "The component." + option :fingerprint, required: false, type: :string, aliases: :"-f", desc: "The fingerprint." + option :tags, required: false, type: :string, aliases: :"-t", desc: "The tags." + option :url, required: false, type: :string, aliases: :"-u", desc: "The URL." def notify config = build_config(options) @@ -110,9 +110,9 @@ def notify exit(1) end - desc 'exec', 'Execute a command. If the exit status is not 0, report the result to Honeybadger' + desc "exec", "Execute a command. If the exit status is not 0, report the result to Honeybadger" project_options - option :quiet, required: false, type: :boolean, aliases: :'-q', default: false, desc: 'Suppress all output unless notification fails.' + option :quiet, required: false, type: :boolean, aliases: :"-q", default: false, desc: "Suppress all output unless notification fails." def exec(*args) if args.size == 0 say("honeybadger: exec needs a command to run", :red) @@ -132,13 +132,13 @@ def exec(*args) exit(1) end - desc 'heroku SUBCOMMAND ...ARGS', 'Manage Honeybadger on Heroku' - subcommand 'heroku', Heroku + desc "heroku SUBCOMMAND ...ARGS", "Manage Honeybadger on Heroku" + subcommand "heroku", Heroku private def fetch_value(options, key) - options[key] == key ? nil : options[key] + (options[key] == key) ? nil : options[key] end def build_config(options) @@ -146,15 +146,15 @@ def build_config(options) config = Honeybadger.config config.set(:report_data, true) - config.set(:api_key, fetch_value(options, 'api_key')) if options.has_key?('api_key') - config.set(:env, fetch_value(options, 'environment')) if options.has_key?('environment') + config.set(:api_key, fetch_value(options, "api_key")) if options.has_key?("api_key") + config.set(:env, fetch_value(options, "environment")) if options.has_key?("environment") config end def load_env(options) # Initialize Rails when running from Rails root. - environment_rb = File.join(Dir.pwd, 'config', 'environment.rb') + environment_rb = File.join(Dir.pwd, "config", "environment.rb") if File.exist?(environment_rb) load_rails_env_if_allowed(environment_rb, options) end @@ -164,7 +164,7 @@ def load_env(options) def load_rails_env_if_allowed(environment_rb, options) # Skip Rails initialization according to option flag - if options.has_key?('skip_rails_load') && fetch_value(options, 'skip_rails_load') + if options.has_key?("skip_rails_load") && fetch_value(options, "skip_rails_load") say("Skipping Rails initialization.") else load_rails_env(environment_rb) @@ -173,7 +173,7 @@ def load_rails_env_if_allowed(environment_rb, options) def load_rails_env(environment_rb) begin - require 'rails' + require "rails" rescue LoadError # No Rails, so skip loading Rails environment. return @@ -184,55 +184,55 @@ def load_rails_env(environment_rb) def log_error(e) case e when *Util::HTTP::ERRORS - say(<<-MSG, :red) -!! --- Failed to notify Honeybadger ------------------------------------------- !! - -# What happened? - - We encountered an HTTP error while contacting our service. Issues like this are - usually temporary. - -# Error details - - #{e.class}: #{e.message}\n at #{e.backtrace && e.backtrace.first} - -# What can I do? - - - Retry the command. - - Make sure you can connect to api.honeybadger.io (`curl https://api.honeybadger.io/v1/notices`). - - If you continue to see this message, email us at support@honeybadger.io - (don't forget to attach this output!) - -!! --- End -------------------------------------------------------------------- !! -MSG + say(<<~MSG, :red) + !! --- Failed to notify Honeybadger ------------------------------------------- !! + + # What happened? + + We encountered an HTTP error while contacting our service. Issues like this are + usually temporary. + + # Error details + + #{e.class}: #{e.message}\n at #{e.backtrace && e.backtrace.first} + + # What can I do? + + - Retry the command. + - Make sure you can connect to api.honeybadger.io (`curl https://api.honeybadger.io/v1/notices`). + - If you continue to see this message, email us at support@honeybadger.io + (don't forget to attach this output!) + + !! --- End -------------------------------------------------------------------- !! + MSG else - say(<<-MSG, :red) -!! --- Honeybadger command failed --------------------------------------------- !! - -# What did you try to do? - - You tried to execute the following command: - `honeybadger #{ARGV.join(' ')}` - -# What actually happend? - - We encountered a Ruby exception and were forced to cancel your request. - -# Error details - - #{e.class}: #{e.message} - #{e.backtrace && e.backtrace.join("\n ")} - -# What can I do? - - - If you're calling the `install` or `test` command in a Rails app, make sure - you can boot the Rails console: `bundle exec rails console`. - - Retry the command. - - If you continue to see this message, email us at support@honeybadger.io - (don't forget to attach this output!) - -!! --- End -------------------------------------------------------------------- !! -MSG + say(<<~MSG, :red) + !! --- Honeybadger command failed --------------------------------------------- !! + + # What did you try to do? + + You tried to execute the following command: + `honeybadger #{ARGV.join(" ")}` + + # What actually happend? + + We encountered a Ruby exception and were forced to cancel your request. + + # Error details + + #{e.class}: #{e.message} + #{e.backtrace && e.backtrace.join("\n ")} + + # What can I do? + + - If you're calling the `install` or `test` command in a Rails app, make sure + you can boot the Rails console: `bundle exec rails console`. + - Retry the command. + - If you continue to see this message, email us at support@honeybadger.io + (don't forget to attach this output!) + + !! --- End -------------------------------------------------------------------- !! + MSG end end end diff --git a/lib/honeybadger/cli/notify.rb b/lib/honeybadger/cli/notify.rb index b856d872a..7bf612676 100644 --- a/lib/honeybadger/cli/notify.rb +++ b/lib/honeybadger/cli/notify.rb @@ -1,9 +1,9 @@ -require 'digest' -require 'forwardable' -require 'honeybadger/cli/main' -require 'honeybadger/cli/helpers' -require 'honeybadger/util/http' -require 'honeybadger/util/stats' +require "digest" +require "forwardable" +require "honeybadger/cli/main" +require "honeybadger/cli/helpers" +require "honeybadger/util/http" +require "honeybadger/util/stats" module Honeybadger module CLI @@ -23,8 +23,8 @@ def run api_key: config.get(:api_key), notifier: NOTIFIER, error: { - class: options['class'], - message: options['message'] + class: options["class"], + message: options["message"] }, request: {}, server: { @@ -35,12 +35,12 @@ def run } } - payload[:error][:fingerprint] = Digest::SHA1.hexdigest(options['fingerprint']) if option?('fingerprint') - payload[:error][:tags] = options['tags'].to_s.strip.split(',').map(&:strip) if option?('tags') + payload[:error][:fingerprint] = Digest::SHA1.hexdigest(options["fingerprint"]) if option?("fingerprint") + payload[:error][:tags] = options["tags"].to_s.strip.split(",").map(&:strip) if option?("tags") - payload[:request][:component] = options['component'] if option?('component') - payload[:request][:action] = options['action'] if option?('action') - payload[:request][:url] = options['url'] if option?('url') + payload[:request][:component] = options["component"] if option?("component") + payload[:request][:action] = options["action"] if option?("action") + payload[:request][:url] = options["url"] if option?("url") payload.delete(:request) if payload[:request].empty? diff --git a/lib/honeybadger/cli/test.rb b/lib/honeybadger/cli/test.rb index 3bfad67c3..1b673acca 100644 --- a/lib/honeybadger/cli/test.rb +++ b/lib/honeybadger/cli/test.rb @@ -1,7 +1,7 @@ -require 'erb' -require 'forwardable' -require 'honeybadger/cli/main' -require 'pathname' +require "erb" +require "forwardable" +require "honeybadger/cli/main" +require "pathname" module Honeybadger module CLI @@ -9,11 +9,11 @@ class Test extend Forwardable TEST_EXCEPTION = begin - exception_name = ENV['EXCEPTION'] || 'HoneybadgerTestingException' - Object.const_get(exception_name) - rescue - Object.const_set(exception_name, Class.new(Exception)) - end.new('Testing honeybadger via "honeybadger test". If you can see this, it works.') + exception_name = ENV["EXCEPTION"] || "HoneybadgerTestingException" + Object.const_get(exception_name) + rescue + Object.const_set(exception_name, Class.new(Exception)) + end.new('Testing honeybadger via "honeybadger test". If you can see this, it works.') class TestBackend def initialize(backend) @@ -21,7 +21,7 @@ def initialize(backend) end def self.callings - @callings ||= Hash.new {|h,k| h[k] = [] } + @callings ||= Hash.new { |h, k| h[k] = [] } end def self.events @@ -48,11 +48,11 @@ def initialize(options) def run begin - require File.join(Dir.pwd, 'config', 'environment.rb') + require File.join(Dir.pwd, "config", "environment.rb") raise LoadError unless defined?(::Rails.application) say("Detected Rails #{Rails::VERSION::STRING}") rescue LoadError - require 'honeybadger/init/ruby' + require "honeybadger/init/ruby" end if Honeybadger.config.get(:api_key).to_s =~ BLANK @@ -87,7 +87,7 @@ def run_test end def test_exception_class - exception_name = ENV['EXCEPTION'] || 'HoneybadgerTestingException' + exception_name = ENV["EXCEPTION"] || "HoneybadgerTestingException" Object.const_get(exception_name) rescue Object.const_set(exception_name, Class.new(Exception)) @@ -104,24 +104,36 @@ def run_rails_test # logging the framework trace (moved to ActionDispatch::DebugExceptions), # which caused cluttered output while running the test task. defined?(::ActionDispatch::DebugExceptions) and - ::ActionDispatch::DebugExceptions.class_eval { def logger(*args) ; @logger ||= Logger.new(nil) ; end } + ::ActionDispatch::DebugExceptions.class_eval { + def logger(*args) + @logger ||= Logger.new(nil) + end + } defined?(::ActionDispatch::ShowExceptions) and - ::ActionDispatch::ShowExceptions.class_eval { def logger(*args) ; @logger ||= Logger.new(nil) ; end } + ::ActionDispatch::ShowExceptions.class_eval { + def logger(*args) + @logger ||= Logger.new(nil) + end + } # Detect and disable the better_errors gem if defined?(::BetterErrors::Middleware) - say('Better Errors detected: temporarily disabling middleware.', :yellow) - ::BetterErrors::Middleware.class_eval { def call(env) @app.call(env); end } + say("Better Errors detected: temporarily disabling middleware.", :yellow) + ::BetterErrors::Middleware.class_eval { + def call(env) + @app.call(env) + end + } end begin - require './app/controllers/application_controller' + require "./app/controllers/application_controller" rescue LoadError nil end unless defined?(::ApplicationController) - say('Error: No ApplicationController found.', :red) + say("Error: No ApplicationController found.", :red) return false end @@ -152,9 +164,9 @@ def verify; end r.disable_clear_and_finalize = true r.clear! r.draw do - match 'verify' => 'honeybadger/test#verify', :as => "verify_#{SecureRandom.hex}", :via => :get + match "verify" => "honeybadger/test#verify", :as => "verify_#{SecureRandom.hex}", :via => :get end - ::Rails.application.routes_reloader.paths.each{ |path| load(path) } + ::Rails.application.routes_reloader.paths.each { |path| load(path) } ::ActiveSupport.on_load(:action_controller) { r.finalize! } ensure r.disable_clear_and_finalize = d @@ -162,7 +174,7 @@ def verify; end end ssl = defined?(::Rails.configuration.force_ssl) && ::Rails.configuration.force_ssl - env = ::Rack::MockRequest.env_for("http#{ ssl ? 's' : nil }://www.example.com/verify", 'REMOTE_ADDR' => '127.0.0.1', 'HTTP_HOST' => 'localhost') + env = ::Rack::MockRequest.env_for("http#{ssl ? "s" : nil}://www.example.com/verify", "REMOTE_ADDR" => "127.0.0.1", "HTTP_HOST" => "localhost") ::Rails.application.call(env) end @@ -170,28 +182,28 @@ def verify; end def verify_test Honeybadger.flush - if calling = TestBackend.callings[:notices].find {|c| c[0].exception.eql?(TEST_EXCEPTION) } - notice, response = *calling + if calling = TestBackend.callings[:notices].find { |c| c[0].exception.eql?(TEST_EXCEPTION) } + _, response = *calling if !response.success? - host = Honeybadger.config.get(:'connection.host') - say(<<-MSG, :red) -!! --- Honeybadger test failed ------------------------------------------------ !! - -The error notifier is installed, but we encountered an error: - - #{response.error_message} - -To fix this issue, please try the following: - - - Make sure the gem is configured properly. - - Retry executing this command a few times. - - Make sure you can connect to #{host} (`curl https://#{host}/v1/notices`). - - Email support@honeybadger.io for help. Include as much debug info as you - can for a faster resolution! - -!! --- End -------------------------------------------------------------------- !! -MSG + host = Honeybadger.config.get(:"connection.host") + say(<<~MSG, :red) + !! --- Honeybadger test failed ------------------------------------------------ !! + + The error notifier is installed, but we encountered an error: + + #{response.error_message} + + To fix this issue, please try the following: + + - Make sure the gem is configured properly. + - Retry executing this command a few times. + - Make sure you can connect to #{host} (`curl https://#{host}/v1/notices`). + - Email support@honeybadger.io for help. Include as much debug info as you + can for a faster resolution! + + !! --- End -------------------------------------------------------------------- !! + MSG exit(1) end @@ -200,27 +212,27 @@ def verify_test exit(0) end - say(<<-MSG, :red) -!! --- Honeybadger test failed ------------------------------------------------ !! - -Error: The test exception was not reported; the application may not be -configured properly. - -This is usually caused by one of the following issues: - - - There was a problem loading your application. Check your logs to see if a - different exception is being raised. - - The exception is being rescued before it reaches our Rack middleware. If - you're using `rescue` or `rescue_from` you may need to notify Honeybadger - manually: `Honeybadger.notify(exception)`. - - The honeybadger gem is misconfigured. Check the settings in your - honeybadger.yml file. -MSG + say(<<~MSG, :red) + !! --- Honeybadger test failed ------------------------------------------------ !! + + Error: The test exception was not reported; the application may not be + configured properly. + + This is usually caused by one of the following issues: + + - There was a problem loading your application. Check your logs to see if a + different exception is being raised. + - The exception is being rescued before it reaches our Rack middleware. If + you're using `rescue` or `rescue_from` you may need to notify Honeybadger + manually: `Honeybadger.notify(exception)`. + - The honeybadger gem is misconfigured. Check the settings in your + honeybadger.yml file. + MSG notices = TestBackend.callings[:notices].map(&:first) unless notices.empty? say("\nThe following errors were reported:", :red) - notices.each {|n| say("\n - #{n.error_class}: #{n.error_message}", :red) } + notices.each { |n| say("\n - #{n.error_class}: #{n.error_message}", :red) } end say("\nSee https://docs.honeybadger.io/gem-troubleshooting for more troubleshooting help.\n\n", :red) @@ -230,48 +242,48 @@ def verify_test end def generate_success_message(response) - notice_id = JSON.parse(response.body)['id'] + notice_id = JSON.parse(response.body)["id"] notice_url = "https://app.honeybadger.io/notice/#{notice_id}" unless options[:install] return "⚡ Success: #{notice_url}" end - <<-MSG -⚡ --- Honeybadger is installed! ----------------------------------------------- - -Good news: You're one deploy away from seeing all of your exceptions in -Honeybadger. For now, we've generated a test exception for you: - - #{notice_url} - -Optional steps: - - - Show a feedback form on your error page: - https://docs.honeybadger.io/gem-feedback - - Show a UUID or link to Honeybadger on your error page: - https://docs.honeybadger.io/gem-informer - - Track deployments (if you're using Capistrano, we already did this): - https://docs.honeybadger.io/gem-deploys - -If you ever need help: - - - Read the gem troubleshooting guide: https://docs.honeybadger.io/gem-troubleshooting - - Check out our documentation: https://docs.honeybadger.io/ - - Email the founders: support@honeybadger.io - -Most people don't realize that Honeybadger is a small, bootstrapped company. We -really couldn't do this without you. Thank you for allowing us to do what we -love: making developers awesome. - -Happy 'badgering! - -Sincerely, -The Honeybadger Crew -https://www.honeybadger.io/about/ - -⚡ --- End -------------------------------------------------------------------- -MSG + <<~MSG + ⚡ --- Honeybadger is installed! ----------------------------------------------- + + Good news: You're one deploy away from seeing all of your exceptions in + Honeybadger. For now, we've generated a test exception for you: + + #{notice_url} + + Optional steps: + + - Show a feedback form on your error page: + https://docs.honeybadger.io/gem-feedback + - Show a UUID or link to Honeybadger on your error page: + https://docs.honeybadger.io/gem-informer + - Track deployments (if you're using Capistrano, we already did this): + https://docs.honeybadger.io/gem-deploys + + If you ever need help: + + - Read the gem troubleshooting guide: https://docs.honeybadger.io/gem-troubleshooting + - Check out our documentation: https://docs.honeybadger.io/ + - Email the founders: support@honeybadger.io + + Most people don't realize that Honeybadger is a small, bootstrapped company. We + really couldn't do this without you. Thank you for allowing us to do what we + love: making developers awesome. + + Happy 'badgering! + + Sincerely, + The Honeybadger Crew + https://www.honeybadger.io/about/ + + ⚡ --- End -------------------------------------------------------------------- + MSG end end end diff --git a/lib/honeybadger/config.rb b/lib/honeybadger/config.rb index e6e4f6185..a05189b8d 100644 --- a/lib/honeybadger/config.rb +++ b/lib/honeybadger/config.rb @@ -1,16 +1,16 @@ -require 'pathname' -require 'delegate' -require 'logger' -require 'fileutils' -require 'openssl' - -require 'honeybadger/version' -require 'honeybadger/logging' -require 'honeybadger/backend' -require 'honeybadger/config/defaults' -require 'honeybadger/util/http' -require 'honeybadger/util/revision' -require 'honeybadger/logging' +require "pathname" +require "delegate" +require "logger" +require "fileutils" +require "openssl" + +require "honeybadger/version" +require "honeybadger/logging" +require "honeybadger/backend" +require "honeybadger/config/defaults" +require "honeybadger/util/http" +require "honeybadger/util/revision" +require "honeybadger/logging" module Honeybadger # @api private @@ -25,9 +25,9 @@ class ConfigError < StandardError; end # Config subclasses have circular dependencies, so they must be loaded # after constants are defined. - autoload :Env, 'honeybadger/config/env' - autoload :Yaml, 'honeybadger/config/yaml' - autoload :Ruby, 'honeybadger/config/ruby' + autoload :Env, "honeybadger/config/env" + autoload :Yaml, "honeybadger/config/yaml" + autoload :Ruby, "honeybadger/config/ruby" KEY_REPLACEMENT = Regexp.new('[^a-z\d_]', Regexp::IGNORECASE).freeze @@ -55,8 +55,8 @@ def init!(opts = {}, env = ENV) init_logging! init_backend! - logger.debug(sprintf('Initializing Honeybadger Error Tracker for Ruby. Ship it! version=%s framework=%s', Honeybadger::VERSION, detected_framework)) - logger.warn('Development mode is enabled. Data will not be reported until you deploy your app.') if warn_development? + logger.debug(sprintf("Initializing Honeybadger Error Tracker for Ruby. Ship it! version=%s framework=%s", Honeybadger::VERSION, detected_framework)) + logger.warn("Development mode is enabled. Data will not be reported until you deploy your app.") if warn_development? self end @@ -65,7 +65,7 @@ def load!(framework: {}, env: ENV) return self if @loaded self.framework = framework.freeze self.env = Env.new(env).freeze - load_config_from_disk {|yaml| self.yaml = yaml.freeze } + load_config_from_disk { |yaml| self.yaml = yaml.freeze } detect_revision! @loaded = true self @@ -81,7 +81,7 @@ def configure def backtrace_filter(&block) if block_given? - warn('DEPRECATED: backtrace_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#backtrace_filter') + warn("DEPRECATED: backtrace_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#backtrace_filter") self[:backtrace_filter] = block end @@ -98,7 +98,7 @@ def before_event_hooks def exception_filter(&block) if block_given? - warn('DEPRECATED: exception_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_filter') + warn("DEPRECATED: exception_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_filter") self[:exception_filter] = block end @@ -107,7 +107,7 @@ def exception_filter(&block) def exception_fingerprint(&block) if block_given? - warn('DEPRECATED: exception_fingerprint is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_fingerprint') + warn("DEPRECATED: exception_fingerprint is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_fingerprint") self[:exception_fingerprint] = block end @@ -124,28 +124,27 @@ def get(key) DEFAULTS[key] end - alias [] :get + alias_method :[], :get def set(key, value) self.ruby = ruby.merge(key => value).freeze @logger = @backend = nil end - alias []= :set + alias_method :[]=, :set def to_hash(defaults = false) - hash = [:@ruby, :@env, :@yaml, :@framework].reverse.reduce({}) do |a,e| + hash = [:@ruby, :@env, :@yaml, :@framework].reverse.reduce({}) do |a, e| a.merge!(instance_variable_get(e)) end hash = DEFAULTS.merge(hash) if defaults - undotify_keys(hash.select {|k,v| DEFAULTS.has_key?(k) }) + undotify_keys(hash.select { |k, v| DEFAULTS.has_key?(k) }) end - alias to_h to_hash + alias_method :to_h, :to_hash # Internal Helpers - def logger init_logging! unless @logger @logger @@ -166,7 +165,7 @@ def dev? end def warn_development? - dev? && backend.kind_of?(Backend::Null) + dev? && backend.is_a?(Backend::Null) end def public? @@ -180,30 +179,30 @@ def debug? end def log_debug? - return debug? if self[:'logging.debug'].nil? - !!self[:'logging.debug'] + return debug? if self[:"logging.debug"].nil? + !!self[:"logging.debug"] end def ignored_classes - ignore_only = get(:'exceptions.ignore_only') + ignore_only = get(:"exceptions.ignore_only") return ignore_only if ignore_only - return DEFAULTS[:'exceptions.ignore'] unless ignore = get(:'exceptions.ignore') + return DEFAULTS[:"exceptions.ignore"] unless ignore = get(:"exceptions.ignore") - DEFAULTS[:'exceptions.ignore'] | Array(ignore) + DEFAULTS[:"exceptions.ignore"] | Array(ignore) end def raw_ignored_events - ignore_only = get(:'events.ignore_only') + ignore_only = get(:"events.ignore_only") return ignore_only if ignore_only - return DEFAULTS[:'events.ignore'] unless ignore = get(:'events.ignore') + return DEFAULTS[:"events.ignore"] unless ignore = get(:"events.ignore") - DEFAULTS[:'events.ignore'] | Array(ignore) + DEFAULTS[:"events.ignore"] | Array(ignore) end def ignored_events @ignored_events ||= raw_ignored_events.map do |check| if check.is_a?(String) || check.is_a?(Regexp) - { [:event_type] => check } + {[:event_type] => check} elsif check.is_a?(Hash) flat_hash(check).transform_keys! { |key_array| key_array.map(&:to_sym) } end @@ -211,23 +210,23 @@ def ignored_events end def ca_bundle_path - if self[:'connection.system_ssl_cert_chain'] && File.exist?(OpenSSL::X509::DEFAULT_CERT_FILE) + if self[:"connection.system_ssl_cert_chain"] && File.exist?(OpenSSL::X509::DEFAULT_CERT_FILE) OpenSSL::X509::DEFAULT_CERT_FILE - elsif self[:'connection.ssl_ca_bundle_path'] - self[:'connection.ssl_ca_bundle_path'] + elsif self[:"connection.ssl_ca_bundle_path"] + self[:"connection.ssl_ca_bundle_path"] else local_cert_path end end def local_cert_path - File.expand_path(File.join('..', '..', '..', 'resources', 'ca-bundle.crt'), __FILE__) + File.expand_path(File.join("..", "..", "..", "resources", "ca-bundle.crt"), __FILE__) end def connection_port - if self[:'connection.port'] - self[:'connection.port'] - elsif self[:'connection.secure'] + if self[:"connection.port"] + self[:"connection.port"] + elsif self[:"connection.secure"] 443 else 80 @@ -235,10 +234,10 @@ def connection_port end def connection_protocol - if self[:'connection.secure'] - 'https' + if self[:"connection.secure"] + "https" else - 'http' + "http" end end @@ -247,35 +246,35 @@ def max_queue_size end def events_max_queue_size - self[:'events.max_queue_size'] + self[:"events.max_queue_size"] end def events_batch_size - self[:'events.batch_size'] + self[:"events.batch_size"] end def events_timeout - self[:'events.timeout'] + self[:"events.timeout"] end def params_filters - Array(self[:'request.filter_keys']) + Array(self[:"request.filter_keys"]) end def excluded_request_keys [].tap do |keys| - keys << :session if self[:'request.disable_session'] - keys << :params if self[:'request.disable_params'] - keys << :cgi_data if self[:'request.disable_environment'] - keys << :url if self[:'request.disable_url'] + keys << :session if self[:"request.disable_session"] + keys << :params if self[:"request.disable_params"] + keys << :cgi_data if self[:"request.disable_environment"] + keys << :url if self[:"request.disable_url"] end end - def log_level(key = :'logging.level') + def log_level(key = :"logging.level") case self[key].to_s when /\A(0|debug)\z/i then Logger::DEBUG - when /\A(1|info)\z/i then Logger::INFO - when /\A(2|warn)\z/i then Logger::WARN + when /\A(1|info)\z/i then Logger::INFO + when /\A(2|warn)\z/i then Logger::WARN when /\A(3|error)\z/i then Logger::ERROR else Logger::INFO @@ -283,13 +282,13 @@ def log_level(key = :'logging.level') end def load_plugin?(name) - return false if includes_token?(self[:'skipped_plugins'], name) - return true unless self[:plugins].kind_of?(Array) + return false if includes_token?(self[:skipped_plugins], name) + return true unless self[:plugins].is_a?(Array) includes_token?(self[:plugins], name) end def insights_enabled? - public? && !!self[:'insights.enabled'] + public? && !!self[:"insights.enabled"] end def cluster_collection?(name) @@ -330,17 +329,17 @@ def root_regexp root = get(:root).to_s @no_root = true and return nil unless root =~ NOT_BLANK - @root_regexp = Regexp.new("^#{ Regexp.escape(root) }") + @root_regexp = Regexp.new("^#{Regexp.escape(root)}") end def detected_framework if self[:framework] =~ NOT_BLANK self[:framework].to_sym - elsif defined?(::Rails::VERSION) && ::Rails::VERSION::STRING > '3.0' + elsif defined?(::Rails::VERSION) && ::Rails::VERSION::STRING > "3.0" :rails elsif defined?(::Sinatra::VERSION) :sinatra - elsif defined?(::Hanami::VERSION) && ::Hanami::VERSION >= '2.0' + elsif defined?(::Hanami::VERSION) && ::Hanami::VERSION >= "2.0" :hanami elsif defined?(::Rack.release) :rack @@ -369,8 +368,8 @@ def detect_revision! def log_path return if log_stdout? - return if !self[:'logging.path'] - locate_absolute_path(self[:'logging.path'], self[:root]) + return if !self[:"logging.path"] + locate_absolute_path(self[:"logging.path"], self[:root]) end def config_path @@ -378,7 +377,7 @@ def config_path end def config_paths - Array(ENV['HONEYBADGER_CONFIG_PATH'] || get(:'config.path')).map do |c| + Array(ENV["HONEYBADGER_CONFIG_PATH"] || get(:"config.path")).map do |c| locate_absolute_path(c, self[:root]) end end @@ -400,7 +399,7 @@ def init_backend! end if ruby[:backend] - logger.warn(sprintf('Unknown backend: %p; default will be used. Backend must respond to #notify', self[:backend])) + logger.warn(sprintf("Unknown backend: %p; default will be used. Backend must respond to #notify", self[:backend])) end @backend = default_backend @@ -423,7 +422,7 @@ def build_file_logger(path) end def log_stdout? - self[:'logging.path'] && self[:'logging.path'].to_s.downcase == 'stdout' + self[:"logging.path"] && self[:"logging.path"].to_s.downcase == "stdout" end def build_logger @@ -448,7 +447,7 @@ def init_logging! # Takes an Array and a value and returns true if the value exists in the # array in String or Symbol form, otherwise false. def includes_token?(obj, value) - return false unless obj.kind_of?(Array) + return false unless obj.is_a?(Array) obj.map(&:to_sym).include?(value.to_sym) end @@ -471,7 +470,7 @@ def load_config_from_disk def undotify_keys(hash) {}.tap do |new_hash| - hash.each_pair do |k,v| + hash.each_pair do |k, v| if k.to_s =~ DOTTED_KEY new_hash[$1] ||= {} new_hash[$1] = undotify_keys(new_hash[$1].merge({$2 => v})) @@ -485,9 +484,9 @@ def undotify_keys(hash) # Converts a nested hash into a single layer where keys become arrays: # ex: > flat_hash({ :nested => { :hash => "value" }}) # > { [:nested, :hash] => "value" } - def flat_hash(h,f=[],g={}) - return g.update({ f=>h }) unless h.is_a? Hash - h.each { |k,r| flat_hash(r,f+[k],g) } + def flat_hash(h, f = [], g = {}) + return g.update({f => h}) unless h.is_a? Hash + h.each { |k, r| flat_hash(r, f + [k], g) } g end end diff --git a/lib/honeybadger/config/defaults.rb b/lib/honeybadger/config/defaults.rb index 8ce832c4b..eac3d0656 100644 --- a/lib/honeybadger/config/defaults.rb +++ b/lib/honeybadger/config/defaults.rb @@ -1,524 +1,524 @@ -require 'socket' -require 'honeybadger/breadcrumbs/active_support' +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 + 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 IGNORE_EVENTS_DEFAULT = [ - { event_type: 'metric.hb', metric_name: 'duration.sql.active_record', query: /^(begin|commit)( transaction)?$/i }, - { event_type: 'sql.active_record', query: /^(begin|commit)( transaction)?$/i }, - { event_type: 'sql.active_record', query: /(solid_queue|good_job)/i }, - { event_type: 'sql.active_record', name: /^GoodJob/ }, - { event_type: 'process_action.action_controller', controller: 'Rails::HealthController' } + {event_type: "metric.hb", metric_name: "duration.sql.active_record", query: /^(begin|commit)( transaction)?$/i}, + {event_type: "sql.active_record", query: /^(begin|commit)( transaction)?$/i}, + {event_type: "sql.active_record", query: /(solid_queue|good_job)/i}, + {event_type: "sql.active_record", name: /^GoodJob/}, + {event_type: "process_action.action_controller", controller: "Rails::HealthController"} ].freeze - DEVELOPMENT_ENVIRONMENTS = ['development', 'test', 'cucumber'].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 + 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.', + description: "The API key for your Honeybadger project.", default: nil, type: String }, env: { - description: 'The current application\'s environment name.', + 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.', + 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.', + description: "The project's absolute root path.", default: Dir.pwd, type: String }, revision: { - description: 'The git revision of the project.', + description: "The git revision of the project.", default: nil, type: String }, hostname: { - description: 'The hostname of the current box.', + description: "The hostname of the current box.", default: Socket.gethostname, type: String }, backend: { - description: 'An alternate backend to use for reporting data.', + description: "An alternate backend to use for reporting data.", default: nil, type: String }, debug: { - description: 'Enables debug logging.', + 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).', + 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.', + 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.', + description: "Maximum number of items for each worker queue.", default: 100, type: Integer }, - :'events.max_queue_size' => { - description: 'Maximum number of event for the event worker queue.', + "events.max_queue_size": { + description: "Maximum number of event for the event worker queue.", default: 100000, type: Integer }, - :'events.batch_size' => { - description: 'Send events batch if n events have accumulated', + "events.batch_size": { + description: "Send events batch if n events have accumulated", default: 1000, type: Integer }, - :'events.timeout' => { - description: 'Timeout after which the events batch will be sent regardless (in milliseconds)', + "events.timeout": { + description: "Timeout after which the events batch will be sent regardless (in milliseconds)", default: 30_000, type: Integer }, - :'events.attach_hostname' => { - description: 'Add the hostname to all event paylaods.', + "events.attach_hostname": { + description: "Add the hostname to all event paylaods.", default: true, type: Boolean }, - :'events.ignore' => { - description: 'A list of additional events to ignore. Use a hash to query nested payloads, match using a string or regex. Non-hash will match on the event_type.', + "events.ignore": { + description: "A list of additional events to ignore. Use a hash to query nested payloads, match using a string or regex. Non-hash will match on the event_type.", default: IGNORE_EVENTS_DEFAULT, type: Array }, - :'events.ignore_only' => { - description: 'A list of events to ignore (overrides the default ignored events).', + "events.ignore_only": { + description: "A list of events to ignore (overrides the default ignored events).", default: nil, type: Array }, plugins: { - description: 'An optional list of plugins to load. Default is to load all 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.', + 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.', + 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.', + "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.', + "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', + "logging.level": { + description: "The log level.", + default: "INFO", type: String }, - :'logging.debug' => { - description: 'Override debug logging.', + "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', + "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.', + "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, + "connection.host": { + description: "The host to use when sending data.", + default: "api.honeybadger.io".freeze, type: String }, - :'connection.ui_host' => { - description: 'The host to use when viewing data.', - default: 'app.honeybadger.io'.freeze, + "connection.ui_host": { + description: "The host to use when viewing data.", + default: "app.honeybadger.io".freeze, type: String }, - :'connection.port' => { - description: 'The port to use when sending data.', + "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).', + "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.', + "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.', + "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.', + "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.', + "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.', + "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.', + "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.', + "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, + "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.', + "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.', + "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.', + "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).', + "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.', + "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, + "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.', + "feedback.enabled": { + description: "Enable the UserFeedback middleware.", default: true, type: Boolean }, - :'exceptions.enabled' => { - description: 'Enable automatic reporting of exceptions.', + "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).', + "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).', + "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.', + "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.', + "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).', + "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.', + "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.', + "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.', + "exceptions.unwrap": { + description: "Reports #original_exception or #cause one level up from rescued exception when available.", default: false, type: Boolean }, - :'active_job.attempt_threshold' => { - description: 'The number of attempts before notifications will be sent.', + "active_job.attempt_threshold": { + description: "The number of attempts before notifications will be sent.", default: 0, type: Integer }, - :'delayed_job.attempt_threshold' => { - description: 'The number of attempts before notifications will be sent.', + "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.', + "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.', + "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.', + "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.', + "sidekiq.use_component": { + description: "Automatically set the component to the class of the job. Helps with grouping.", default: true, type: Boolean }, - :'sidekiq.insights.enabled' => { - description: 'Enable automatic data collection for Sidekiq.', + "sidekiq.insights.enabled": { + description: "Enable automatic data collection for Sidekiq.", default: true, type: Boolean }, - :'sidekiq.insights.events' => { - description: 'Enable automatic event capturing for Sidekiq.', + "sidekiq.insights.events": { + description: "Enable automatic event capturing for Sidekiq.", default: true, type: Boolean }, - :'sidekiq.insights.metrics' => { - description: 'Enable automatic metric data collection for Sidekiq.', + "sidekiq.insights.metrics": { + description: "Enable automatic metric data collection for Sidekiq.", default: false, type: Boolean }, - :'sidekiq.insights.cluster_collection' => { - description: 'Collect cluster based metrics for Sidekiq.', + "sidekiq.insights.cluster_collection": { + description: "Collect cluster based metrics for Sidekiq.", default: true, type: Boolean }, - :'sidekiq.insights.collection_interval' => { - description: 'The frequency in which Sidekiq cluster metrics are sampled.', + "sidekiq.insights.collection_interval": { + description: "The frequency in which Sidekiq cluster metrics are sampled.", default: 5, type: Integer }, - :'solid_queue.insights.enabled' => { - description: 'Enable automatic data collection for SolidQueue.', + "solid_queue.insights.enabled": { + description: "Enable automatic data collection for SolidQueue.", default: true, type: Boolean }, - :'solid_queue.insights.events' => { - description: 'Enable automatic event capturing for SolidQueue.', + "solid_queue.insights.events": { + description: "Enable automatic event capturing for SolidQueue.", default: true, type: Boolean }, - :'solid_queue.insights.metrics' => { - description: 'Enable automatic metric data collection for SolidQueue.', + "solid_queue.insights.metrics": { + description: "Enable automatic metric data collection for SolidQueue.", default: false, type: Boolean }, - :'solid_queue.insights.cluster_collection' => { - description: 'Collect cluster based metrics for SolidQueue.', + "solid_queue.insights.cluster_collection": { + description: "Collect cluster based metrics for SolidQueue.", default: true, type: Boolean }, - :'solid_queue.insights.collection_interval' => { - description: 'The frequency in which SolidQueue cluster metrics are sampled.', + "solid_queue.insights.collection_interval": { + description: "The frequency in which SolidQueue cluster metrics are sampled.", default: 5, type: Integer }, - :'rails.insights.enabled' => { - description: 'Enable automatic data collection for Ruby on Rails.', + "rails.insights.enabled": { + description: "Enable automatic data collection for Ruby on Rails.", default: true, type: Boolean }, - :'rails.insights.events' => { - description: 'Enable automatic event capturing for Ruby on Rails.', + "rails.insights.events": { + description: "Enable automatic event capturing for Ruby on Rails.", default: true, type: Boolean }, - :'rails.insights.metrics' => { - description: 'Enable automatic metric data collection for Ruby on Rails.', + "rails.insights.metrics": { + description: "Enable automatic metric data collection for Ruby on Rails.", default: false, type: Boolean }, - :'karafka.insights.enabled' => { - description: 'Enable automatic data collection for Karafka.', + "karafka.insights.enabled": { + description: "Enable automatic data collection for Karafka.", default: true, type: Boolean }, - :'karafka.insights.events' => { - description: 'Enable automatic event capturing for Karafka.', + "karafka.insights.events": { + description: "Enable automatic event capturing for Karafka.", default: true, type: Boolean }, - :'karafka.insights.metrics' => { - description: 'Enable automatic metric data collection for Karafka.', + "karafka.insights.metrics": { + description: "Enable automatic metric data collection for Karafka.", default: false, type: Boolean }, - :'net_http.insights.enabled' => { - description: 'Allow automatic instrumentation of Net::HTTP requests.', + "net_http.insights.enabled": { + description: "Allow automatic instrumentation of Net::HTTP requests.", default: true, type: Boolean }, - :'net_http.insights.events' => { - description: 'Enable automatic event capturing for Net::HTTP requests.', + "net_http.insights.events": { + description: "Enable automatic event capturing for Net::HTTP requests.", default: true, type: Boolean }, - :'net_http.insights.metrics' => { - description: 'Enable automatic metric data collection for Net::HTTP requests.', + "net_http.insights.metrics": { + description: "Enable automatic metric data collection for Net::HTTP requests.", default: false, type: Boolean }, - :'net_http.insights.full_url' => { - description: 'Record the full request url during instrumentation.', + "net_http.insights.full_url": { + description: "Record the full request url during instrumentation.", default: false, type: Boolean }, - :'sinatra.enabled' => { - description: 'Enable Sinatra auto-initialization.', + "sinatra.enabled": { + description: "Enable Sinatra auto-initialization.", default: true, type: Boolean }, - :'rails.subscriber_ignore_sources' => { + "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'], + default: ["application.active_support"], type: Array }, - :'resque.resque_retry.send_exceptions_when_retrying' => { - description: 'Send exceptions when retrying job.', + "resque.resque_retry.send_exceptions_when_retrying": { + description: "Send exceptions when retrying job.", default: true, type: Boolean }, - :'breadcrumbs.enabled' => { - description: 'Disable breadcrumb functionality.', + "breadcrumbs.enabled": { + description: "Disable breadcrumb functionality.", default: true, type: Boolean }, - :'breadcrumbs.active_support_notifications' => { - description: 'Configuration for automatic Active Support Instrumentation events.', + "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.', + "breadcrumbs.logging.enabled": { + description: "Enable/Disable automatic breadcrumbs from log messages.", default: true, type: Boolean }, - :'insights.enabled' => { + "insights.enabled": { description: "Enable/Disable Honeybadger Insights built-in instrumentation.", default: false, type: Boolean }, - :'insights.console.enabled' => { + "insights.console.enabled": { description: "Enable/Disable Honeybadger Insights built-in instrumentation in a Rails console.", default: false, type: Boolean }, - :'insights.registry_flush_interval' => { + "insights.registry_flush_interval": { description: "Number of seconds between registry flushes.", default: 60, type: Integer }, - :'puma.insights.events' => { - description: 'Enable automatic event capturing for Puma stats.', + "puma.insights.events": { + description: "Enable automatic event capturing for Puma stats.", default: true, type: Boolean }, - :'puma.insights.metrics' => { - description: 'Enable automatic metric data aggregation for Puma stats.', + "puma.insights.metrics": { + description: "Enable automatic metric data aggregation for Puma stats.", default: false, type: Boolean }, - :'puma.insights.collection_interval' => { - description: 'The frequency in which the Honeybadger gem will collect Puma stats.', + "puma.insights.collection_interval": { + description: "The frequency in which the Honeybadger gem will collect Puma stats.", default: 1, type: Integer }, - :'autotuner.insights.events' => { - description: 'Enable automatic event capturing for Autotuner stats.', + "autotuner.insights.events": { + description: "Enable automatic event capturing for Autotuner stats.", default: true, type: Boolean }, - :'autotuner.insights.metrics' => { - description: 'Enable automatic metric data aggregation for Autotuner stats.', + "autotuner.insights.metrics": { + description: "Enable automatic metric data aggregation for Autotuner stats.", default: false, type: Boolean } }.freeze - DEFAULTS = Hash[OPTIONS.map{|k,v| [k, v[:default]] }].freeze + DEFAULTS = Hash[OPTIONS.map { |k, v| [k, v[:default]] }].freeze end end diff --git a/lib/honeybadger/config/env.rb b/lib/honeybadger/config/env.rb index 6348a38c2..d69258400 100644 --- a/lib/honeybadger/config/env.rb +++ b/lib/honeybadger/config/env.rb @@ -1,17 +1,17 @@ -require 'set' +require "set" module Honeybadger class Config module Env CONFIG_KEY = /\AHONEYBADGER_(.+)\Z/.freeze - CONFIG_MAPPING = Hash[DEFAULTS.keys.map {|k| [k.to_s.upcase.gsub(KEY_REPLACEMENT, '_'), k] }].freeze + CONFIG_MAPPING = Hash[DEFAULTS.keys.map { |k| [k.to_s.upcase.gsub(KEY_REPLACEMENT, "_"), k] }].freeze ARRAY_VALUES = Regexp.new('\s*,\s*').freeze IGNORED_TYPES = Set[Hash] def self.new(env = ENV) hash = {} - env.each_pair do |k,v| + env.each_pair do |k, v| next unless k.match(CONFIG_KEY) next unless config_key = CONFIG_MAPPING[$1] type = OPTIONS[config_key][:type] diff --git a/lib/honeybadger/config/ruby.rb b/lib/honeybadger/config/ruby.rb index 4126075d7..6e2dc3a74 100644 --- a/lib/honeybadger/config/ruby.rb +++ b/lib/honeybadger/config/ruby.rb @@ -12,7 +12,7 @@ def initialize(config, prefix: nil, hash: {}) def to_hash hash.to_hash end - alias to_h to_hash + alias_method :to_h, :to_hash private @@ -41,25 +41,25 @@ def respond_to_missing?(method_name, include_private = false) end def mash?(method) - key = [prefix, method.to_s + '.'].compact.join('.') - KEYS.any? {|k| k.start_with?(key) } + key = [prefix, method.to_s + "."].compact.join(".") + KEYS.any? { |k| k.start_with?(key) } end def setter?(method_name) return false unless method_name.to_s =~ /=\z/ key = key(method_name) - KEYS.any? {|k| k == key } + KEYS.any? { |k| k == key } end def getter?(method_name) key = key(method_name) - KEYS.any? {|k| k == key } + KEYS.any? { |k| k == key } end def key(method_name) - parts = [prefix, method_name.to_s.chomp('=')] + parts = [prefix, method_name.to_s.chomp("=")] parts.compact! - parts.join('.') + parts.join(".") end def get(key) @@ -89,9 +89,9 @@ def backend def before_notify(action = nil, &block) hooks = Array(get(:before_notify)).dup - if action && validate_before_action(action, 'notify') + if action && validate_before_action(action, "notify") hooks << action - elsif block_given? && validate_before_action(block, 'notify') + elsif block_given? && validate_before_action(block, "notify") hooks << block end @@ -101,9 +101,9 @@ def before_notify(action = nil, &block) def before_event(action = nil, &block) hooks = Array(get(:before_event)).dup - if action && validate_before_action(action, 'event') + if action && validate_before_action(action, "event") hooks << action - elsif block_given? && validate_before_action(block, 'event') + elsif block_given? && validate_before_action(block, "event") hooks << block end @@ -112,7 +112,7 @@ def before_event(action = nil, &block) def backtrace_filter(&block) if block_given? - logger.warn('DEPRECATED: backtrace_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#backtrace_filter') + logger.warn("DEPRECATED: backtrace_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#backtrace_filter") hash[:backtrace_filter] = block if block_given? end @@ -121,7 +121,7 @@ def backtrace_filter(&block) def exception_filter(&block) if block_given? - logger.warn('DEPRECATED: exception_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_filter') + logger.warn("DEPRECATED: exception_filter is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_filter") hash[:exception_filter] = block end @@ -130,7 +130,7 @@ def exception_filter(&block) def exception_fingerprint(&block) if block_given? - logger.warn('DEPRECATED: exception_fingerprint is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_fingerprint') + logger.warn("DEPRECATED: exception_fingerprint is deprecated. Please use before_notify instead. See https://docs.honeybadger.io/ruby/support/v4-upgrade#exception_fingerprint") hash[:exception_fingerprint] = block end @@ -143,15 +143,15 @@ def validate_before_action(action, type) if !action.respond_to?(:call) logger.warn( "You attempted to add a before #{type} hook that does not respond " \ - 'to #call. We are discarding this hook so your intended behavior ' \ - 'will not occur.' + "to #call. We are discarding this hook so your intended behavior " \ + "will not occur." ) false elsif action.arity != 1 logger.warn( "You attempted to add a before #{type} hook that has an arity " \ - 'other than one. We are discarding this hook so your intended ' \ - 'behavior will not occur.' + "other than one. We are discarding this hook so your intended " \ + "behavior will not occur." ) false else diff --git a/lib/honeybadger/config/yaml.rb b/lib/honeybadger/config/yaml.rb index 146843fc8..a7eae4510 100644 --- a/lib/honeybadger/config/yaml.rb +++ b/lib/honeybadger/config/yaml.rb @@ -1,14 +1,14 @@ -require 'pathname' -require 'yaml' -require 'erb' +require "pathname" +require "yaml" +require "erb" module Honeybadger class Config module Yaml - DISALLOWED_KEYS = [:'config.path'].freeze + DISALLOWED_KEYS = [:"config.path"].freeze - def self.new(path, env = 'production') - path = path.kind_of?(Pathname) ? path : Pathname.new(path) + def self.new(path, env = "production") + path = path.is_a?(Pathname) ? path : Pathname.new(path) if !path.exist? raise ConfigError, "The configuration file #{path} was not found." @@ -19,7 +19,7 @@ def self.new(path, env = 'production') end yaml = load_yaml(path) - yaml.merge!(yaml[env]) if yaml[env].kind_of?(Hash) + yaml.merge!(yaml[env]) if yaml[env].is_a?(Hash) dotify_keys(yaml) end @@ -36,8 +36,8 @@ def self.load_yaml(path) if e.backtrace backtrace = e.backtrace.map do |line| - if line.start_with?('(erb)'.freeze) - line.gsub('(erb)'.freeze, path.to_s) + if line.start_with?("(erb)".freeze) + line.gsub("(erb)".freeze, path.to_s) else line end @@ -60,9 +60,9 @@ def self.load_yaml(path) def self.dotify_keys(hash, key_prefix = nil) {}.tap do |new_hash| - hash.each_pair do |k,v| - k = [key_prefix, k].compact.join('.') - if v.kind_of?(Hash) + hash.each_pair do |k, v| + k = [key_prefix, k].compact.join(".") + if v.is_a?(Hash) new_hash.update(dotify_keys(v, k)) else next if DISALLOWED_KEYS.include?(k.to_sym) diff --git a/lib/honeybadger/const.rb b/lib/honeybadger/const.rb index 36295e8a9..eb9555491 100644 --- a/lib/honeybadger/const.rb +++ b/lib/honeybadger/const.rb @@ -1,13 +1,13 @@ -require 'honeybadger/version' +require "honeybadger/version" module Honeybadger module Rack # Autoloading allows middleware classes to be referenced in applications # which include the optional Rack dependency without explicitly requiring # these files. - autoload :ErrorNotifier, 'honeybadger/rack/error_notifier' - autoload :UserFeedback, 'honeybadger/rack/user_feedback' - autoload :UserInformer, 'honeybadger/rack/user_informer' + autoload :ErrorNotifier, "honeybadger/rack/error_notifier" + autoload :UserFeedback, "honeybadger/rack/user_feedback" + autoload :UserInformer, "honeybadger/rack/user_informer" end # @api private diff --git a/lib/honeybadger/context_manager.rb b/lib/honeybadger/context_manager.rb index dad811923..a290d68c8 100644 --- a/lib/honeybadger/context_manager.rb +++ b/lib/honeybadger/context_manager.rb @@ -1,4 +1,4 @@ -require 'honeybadger/conversions' +require "honeybadger/conversions" module Honeybadger # @api private @@ -20,7 +20,6 @@ def clear! # Internal helpers - def set_context(hash, &block) local = block_given? @mutex.synchronize do diff --git a/lib/honeybadger/conversions.rb b/lib/honeybadger/conversions.rb index 5e421573a..b056b03dc 100644 --- a/lib/honeybadger/conversions.rb +++ b/lib/honeybadger/conversions.rb @@ -2,6 +2,7 @@ module Honeybadger # @api private module Conversions module_function + MAX_CONTEXT_DEPTH = 5 # Convert context into a Hash. @@ -12,13 +13,15 @@ module Conversions def Context(object, depth = 1) object = object.to_honeybadger_context if object.respond_to?(:to_honeybadger_context) object = Hash(object) - object = object.transform_values do |value| - if value&.respond_to?(:to_honeybadger_context) - Context(value, depth + 1) - else - value + if depth < MAX_CONTEXT_DEPTH + object = object.transform_values do |value| + if value&.respond_to?(:to_honeybadger_context) + Context(value, depth + 1) + else + value + end end - end if depth < MAX_CONTEXT_DEPTH + end object end end diff --git a/lib/honeybadger/counter.rb b/lib/honeybadger/counter.rb index 35044cb3e..f413d082f 100644 --- a/lib/honeybadger/counter.rb +++ b/lib/honeybadger/counter.rb @@ -1,18 +1,18 @@ -require 'honeybadger/metric' +require "honeybadger/metric" module Honeybadger class Counter < Metric - def count(by=1) + def count(by = 1) return unless by @samples += 1 @counter ||= 0 - @counter = @counter + by + @counter += by end def payloads - [{ counter: @counter }] + [{counter: @counter}] end end end diff --git a/lib/honeybadger/event.rb b/lib/honeybadger/event.rb index 3c3987059..649c3a119 100644 --- a/lib/honeybadger/event.rb +++ b/lib/honeybadger/event.rb @@ -1,6 +1,6 @@ -require 'forwardable' +require "forwardable" -require 'honeybadger/util/sanitizer' +require "honeybadger/util/sanitizer" module Honeybadger class Event @@ -18,7 +18,7 @@ class Event def_delegators :payload, :dig, :[], :[]= # @api private - def initialize(event_type_or_payload, payload={}) + def initialize(event_type_or_payload, payload = {}) if event_type_or_payload.is_a?(String) @event_type = event_type_or_payload @payload = payload diff --git a/lib/honeybadger/events_worker.rb b/lib/honeybadger/events_worker.rb index 791667966..bf1068e5f 100644 --- a/lib/honeybadger/events_worker.rb +++ b/lib/honeybadger/events_worker.rb @@ -1,7 +1,7 @@ -require 'forwardable' -require 'net/http' +require "forwardable" +require "net/http" -require 'honeybadger/logging' +require "honeybadger/logging" module Honeybadger # A concurrent queue to notify the backend. @@ -58,7 +58,7 @@ def send_now(msg) end def shutdown(force = false) - d { 'shutting down events worker' } + d { "shutting down events worker" } mutex.synchronize do @shutdown = true @@ -68,11 +68,11 @@ def shutdown(force = false) return true unless thread&.alive? if throttled? - warn { sprintf('Unable to send %s event(s) to Honeybadger (currently throttled)', queue.size) } unless queue.empty? + warn { sprintf("Unable to send %s event(s) to Honeybadger (currently throttled)", queue.size) } unless queue.empty? return true end - info { sprintf('Waiting to send %s events(s) to Honeybadger', queue.size) } unless queue.empty? + info { sprintf("Waiting to send %s events(s) to Honeybadger", queue.size) } unless queue.empty? queue.push(FLUSH) queue.push(SHUTDOWN) !!thread.join @@ -135,7 +135,7 @@ def throttled? end def kill! - d { 'killing worker thread' } + d { "killing worker thread" } if thread Thread.kill(thread) @@ -165,7 +165,7 @@ def schedule_timeout_check def run begin - d { 'worker started' } + d { "worker started" } mutex.synchronize do @last_sent = Time.now end @@ -179,7 +179,7 @@ def run end end ensure - d { 'stopping worker' } + d { "stopping worker" } end rescue Exception => e error { @@ -208,10 +208,10 @@ def send_batch send_now(mutex.synchronize { send_queue }) mutex.synchronize do @last_sent = Time.now - debug { sprintf('Sending %s events', send_queue.length) } + debug { sprintf("Sending %s events", send_queue.length) } send_queue.clear if @dropped_events > 0 - warn { sprintf('Dropped %s messages due to exceeding max queue size of %s', @dropped_events, config.events_max_queue_size) } + warn { sprintf("Dropped %s messages due to exceeding max queue size of %s", @dropped_events, config.events_max_queue_size) } end @dropped_events = 0 end @@ -227,7 +227,7 @@ def check_and_send def flush_send_queue return if mutex.synchronize { send_queue.empty? } send_batch - rescue StandardError => e + rescue => e error { msg = "Error in worker thread class=%s message=%s\n\t%s" sprintf(msg, e.class, e.message.dump, Array(e.backtrace).join("\n\t")) @@ -239,28 +239,26 @@ def work(msg) check_and_send if shutdown? && throttled? - warn { sprintf('Unable to send %s events(s) to Honeybadger (currently throttled)', queue.size) } if queue.size > 1 + warn { sprintf("Unable to send %s events(s) to Honeybadger (currently throttled)", queue.size) } if queue.size > 1 kill! return end sleep(throttle_interval) - rescue StandardError => e + rescue => e error { msg = "Error in worker thread class=%s message=%s\n\t%s" sprintf(msg, e.class, e.message.dump, Array(e.backtrace).join("\n\t")) } end - def send_to_backend(msg) - d { 'events_worker sending to backend' } - response = backend.event(msg) - response + d { "events_worker sending to backend" } + backend.event(msg) end def calc_throttle_interval - ((BASE_THROTTLE ** throttle) - 1).round(3) + ((BASE_THROTTLE**throttle) - 1).round(3) end def inc_throttle @@ -281,32 +279,32 @@ def dec_throttle end def handle_response(response) - d { sprintf('events_worker response code=%s message=%s', response.code, response.message.to_s.dump) } + d { sprintf("events_worker response code=%s message=%s", response.code, response.message.to_s.dump) } case response.code when 429, 503 throttle = inc_throttle - warn { sprintf('Event send failed: project is sending too many events. code=%s throttle=%s interval=%s', response.code, throttle, throttle_interval) } + warn { sprintf("Event send failed: project is sending too many events. code=%s throttle=%s interval=%s", response.code, throttle, throttle_interval) } when 402 - warn { sprintf('Event send failed: payment is required. code=%s', response.code) } + warn { sprintf("Event send failed: payment is required. code=%s", response.code) } suspend(3600) when 403 - warn { sprintf('Event send failed: API key is invalid. code=%s', response.code) } + warn { sprintf("Event send failed: API key is invalid. code=%s", response.code) } suspend(3600) when 413 - warn { sprintf('Event send failed: Payload is too large. code=%s', response.code) } + warn { sprintf("Event send failed: Payload is too large. code=%s", response.code) } when 201 if throttle = dec_throttle - debug { sprintf('Success ⚡ Event sent code=%s throttle=%s interval=%s', response.code, throttle, throttle_interval) } + debug { sprintf("Success ⚡ Event sent code=%s throttle=%s interval=%s", response.code, throttle, throttle_interval) } else - debug { sprintf('Success ⚡ Event sent code=%s', response.code) } + debug { sprintf("Success ⚡ Event sent code=%s", response.code) } end when :stubbed - info { sprintf('Success ⚡ Development mode is enabled; This event will be sent after app is deployed.') } + info { sprintf("Success ⚡ Development mode is enabled; This event will be sent after app is deployed.") } when :error - warn { sprintf('Event send failed: an unknown error occurred. code=%s error=%s', response.code, response.message.to_s.dump) } + warn { sprintf("Event send failed: an unknown error occurred. code=%s error=%s", response.code, response.message.to_s.dump) } else - warn { sprintf('Event send failed: unknown response from server. code=%s', response.code) } + warn { sprintf("Event send failed: unknown response from server. code=%s", response.code) } end end diff --git a/lib/honeybadger/gauge.rb b/lib/honeybadger/gauge.rb index 80288706f..d6f588984 100644 --- a/lib/honeybadger/gauge.rb +++ b/lib/honeybadger/gauge.rb @@ -1,4 +1,4 @@ -require 'honeybadger/metric' +require "honeybadger/metric" module Honeybadger class Gauge < Metric @@ -8,7 +8,7 @@ def record(value) @samples += 1 @total ||= 0 - @total = @total + value + @total += value @min = value if @min.nil? || @min > value @max = value if @max.nil? || @max < value diff --git a/lib/honeybadger/histogram.rb b/lib/honeybadger/histogram.rb index be637dafe..8f1ac109a 100644 --- a/lib/honeybadger/histogram.rb +++ b/lib/honeybadger/histogram.rb @@ -1,4 +1,4 @@ -require 'honeybadger/metric' +require "honeybadger/metric" module Honeybadger class Histogram < Metric @@ -11,7 +11,7 @@ def record(value) @samples += 1 @total ||= 0 - @total = @total + value + @total += value @min = value if @min.nil? || @min > value @max = value if @max.nil? || @max < value @@ -23,7 +23,7 @@ def record(value) end def find_bin(value) - bin = bins.find {|b| b >= value } + bin = bins.find { |b| b >= value } bin = INFINITY if bin.nil? bin end diff --git a/lib/honeybadger/init/hanami.rb b/lib/honeybadger/init/hanami.rb index 3965e5d09..5c97fc0b0 100644 --- a/lib/honeybadger/init/hanami.rb +++ b/lib/honeybadger/init/hanami.rb @@ -1,14 +1,14 @@ -require 'honeybadger/ruby' +require "honeybadger/ruby" Honeybadger.init!({ - :framework => :hanami, - :env => ENV['HANAMI_ENV'] || ENV['RACK_ENV'], - :'logging.path' => 'STDOUT' + framework: :hanami, + env: ENV["HANAMI_ENV"] || ENV["RACK_ENV"], + "logging.path": "STDOUT" }) Honeybadger.load_plugins! -if Hanami::VERSION >= '2.0' && Honeybadger.config[:'exceptions.enabled'] +if Hanami::VERSION >= "2.0" && Honeybadger.config[:"exceptions.enabled"] Hanami.app.instance_eval do config.middleware.use Honeybadger::Rack::UserFeedback config.middleware.use Honeybadger::Rack::UserInformer diff --git a/lib/honeybadger/init/rails.rb b/lib/honeybadger/init/rails.rb index 5c806bcb3..c793dc0ab 100644 --- a/lib/honeybadger/init/rails.rb +++ b/lib/honeybadger/init/rails.rb @@ -1,33 +1,33 @@ -require 'rails' -require 'yaml' +require "rails" +require "yaml" -require 'honeybadger/ruby' +require "honeybadger/ruby" module Honeybadger module Init module Rails class Railtie < ::Rails::Railtie rake_tasks do - load 'honeybadger/tasks.rb' + load "honeybadger/tasks.rb" end - initializer 'honeybadger.install_middleware' do |app| + initializer "honeybadger.install_middleware" do |app| honeybadger_config = Honeybadger::Agent.instance.config - if honeybadger_config[:'exceptions.enabled'] + if honeybadger_config[:"exceptions.enabled"] app.config.middleware.insert(0, Honeybadger::Rack::ErrorNotifier) - app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserInformer) if honeybadger_config[:'user_informer.enabled'] - app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserFeedback) if honeybadger_config[:'feedback.enabled'] + app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserInformer) if honeybadger_config[:"user_informer.enabled"] + app.config.middleware.insert_before(Honeybadger::Rack::ErrorNotifier, Honeybadger::Rack::UserFeedback) if honeybadger_config[:"feedback.enabled"] end end config.before_initialize do Honeybadger.init!({ - :root => ::Rails.root.to_s, - :env => ::Rails.env, - :'config.path' => ::Rails.root.join('config', 'honeybadger.yml'), - :logger => Logging::FormattedLogger.new(::Rails.logger), - :framework => :rails + root: ::Rails.root.to_s, + env: ::Rails.env, + "config.path": ::Rails.root.join("config", "honeybadger.yml"), + logger: Logging::FormattedLogger.new(::Rails.logger), + framework: :rails }) end @@ -36,7 +36,7 @@ class Railtie < ::Rails::Railtie end console do - unless Honeybadger::Agent.instance.config[:'insights.enabled'] = Honeybadger::Agent.instance.config[:'insights.console.enabled'] + unless Honeybadger::Agent.instance.config[:"insights.enabled"] = Honeybadger::Agent.instance.config[:"insights.console.enabled"] Honeybadger::Agent.instance.config.logger.debug("Rails console detected, shutting down Honeybadger Insights workers.") Honeybadger::Agent.instance.stop_insights end diff --git a/lib/honeybadger/init/rake.rb b/lib/honeybadger/init/rake.rb index b4677bce6..08c9a3b28 100644 --- a/lib/honeybadger/init/rake.rb +++ b/lib/honeybadger/init/rake.rb @@ -1,4 +1,4 @@ -require 'honeybadger/ruby' +require "honeybadger/ruby" module Honeybadger # @api private @@ -6,7 +6,7 @@ module Honeybadger module RakeHandler def self.included(klass) klass.class_eval do - include Rake087Methods unless defined?(Rake::VERSION) && Rake::VERSION >= '0.9.0' + include Rake087Methods unless defined?(Rake::VERSION) && Rake::VERSION >= "0.9.0" alias_method :display_error_message_without_honeybadger, :display_error_message alias_method :display_error_message, :display_error_message_with_honeybadger end @@ -20,7 +20,7 @@ def display_error_message_with_honeybadger(ex) end def reconstruct_command_line - "rake #{ARGV.join( ' ' )}" + "rake #{ARGV.join(" ")}" end # This module brings Rake 0.8.7 error handling to 0.9.0 standards @@ -31,11 +31,11 @@ module Rake087Methods def standard_exception_handling begin yield - rescue SystemExit => ex + rescue SystemExit # Exit silently with current status raise rescue OptionParser::InvalidOption => ex - $stderr.puts ex.message + warn ex.message exit(false) rescue Exception => ex # Exit with error message @@ -46,13 +46,13 @@ def standard_exception_handling # Method extracted from Rake 0.8.7 source def display_error_message(ex) - $stderr.puts "#{name} aborted!" - $stderr.puts ex.message + warn "#{name} aborted!" + warn ex.message if options.trace - $stderr.puts ex.backtrace.join("\n") + warn ex.backtrace.join("\n") else - $stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || "" - $stderr.puts "(See full trace by running task with --trace)" + warn ex.backtrace.find { |str| str =~ /#{@rakefile}/ } || "" + warn "(See full trace by running task with --trace)" end end end diff --git a/lib/honeybadger/init/ruby.rb b/lib/honeybadger/init/ruby.rb index 810abfb12..e80a5770c 100644 --- a/lib/honeybadger/init/ruby.rb +++ b/lib/honeybadger/init/ruby.rb @@ -1,9 +1,9 @@ -require 'honeybadger/ruby' +require "honeybadger/ruby" Honeybadger.init!({ - :framework => :ruby, - :env => ENV['RUBY_ENV'] || ENV['RACK_ENV'], - :'logging.path' => 'STDOUT' + framework: :ruby, + env: ENV["RUBY_ENV"] || ENV["RACK_ENV"], + "logging.path": "STDOUT" }) Honeybadger.load_plugins! diff --git a/lib/honeybadger/init/sinatra.rb b/lib/honeybadger/init/sinatra.rb index 6cb8923eb..d24eb2a95 100644 --- a/lib/honeybadger/init/sinatra.rb +++ b/lib/honeybadger/init/sinatra.rb @@ -1,5 +1,5 @@ -require 'sinatra/base' -require 'honeybadger/ruby' +require "sinatra/base" +require "honeybadger/ruby" module Honeybadger module Init @@ -15,8 +15,8 @@ def build_with_honeybadger(*args, &block) Honeybadger.install_at_exit_callback build_without_honeybadger(*args, &block) end - alias :build_without_honeybadger :build - alias :build :build_with_honeybadger + alias_method :build_without_honeybadger, :build + alias_method :build, :build_with_honeybadger def configure_honeybadger return unless defined?(honeybadger_api_key) @@ -27,21 +27,20 @@ def configure_honeybadger def install_honeybadger config = Honeybadger.config - return unless config[:'sinatra.enabled'] - if config[:'exceptions.enabled'] + return unless config[:"sinatra.enabled"] + if config[:"exceptions.enabled"] # These two must come before the ErrorNotifier, since an error/response # passes through middleware from inner to outer (bottom to top) - install_honeybadger_middleware(Honeybadger::Rack::UserFeedback) if config[:'feedback.enabled'] - install_honeybadger_middleware(Honeybadger::Rack::UserInformer) if config[:'user_informer.enabled'] + install_honeybadger_middleware(Honeybadger::Rack::UserFeedback) if config[:"feedback.enabled"] + install_honeybadger_middleware(Honeybadger::Rack::UserInformer) if config[:"user_informer.enabled"] install_honeybadger_middleware(Honeybadger::Rack::ErrorNotifier) end end def install_honeybadger_middleware(klass) - return if middleware.any? {|m| m[0] == klass } + return if middleware.any? { |m| m[0] == klass } use(klass) end - end end end @@ -49,9 +48,9 @@ def install_honeybadger_middleware(klass) end Honeybadger.init!({ - env: ENV['APP_ENV'] || ENV['RACK_ENV'], + env: ENV["APP_ENV"] || ENV["RACK_ENV"], framework: :sinatra, - :'logging.path' => 'STDOUT' + "logging.path": "STDOUT" }) Honeybadger.load_plugins! diff --git a/lib/honeybadger/instrumentation.rb b/lib/honeybadger/instrumentation.rb index 62d009460..d843a602d 100644 --- a/lib/honeybadger/instrumentation.rb +++ b/lib/honeybadger/instrumentation.rb @@ -1,7 +1,7 @@ -require 'honeybadger/histogram' -require 'honeybadger/timer' -require 'honeybadger/counter' -require 'honeybadger/gauge' +require "honeybadger/histogram" +require "honeybadger/timer" +require "honeybadger/counter" +require "honeybadger/gauge" module Honeybadger # +Honeybadger::Instrumentation+ defines the API for collecting metric data from anywhere @@ -47,14 +47,13 @@ def monotonic_timer def time(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) - value = nil - if callable - value = monotonic_timer{ callable.call }[0] + value = if callable + monotonic_timer { callable.call }[0] elsif block_given? - value = monotonic_timer{ yield }[0] + monotonic_timer { yield }[0] else - value = attributes.delete(:duration) || attributes.delete(:value) + attributes.delete(:duration) || attributes.delete(:value) end Honeybadger::Timer.register(registry, name, attributes).tap do |timer| @@ -69,14 +68,13 @@ def time(name, *args) def histogram(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) - value = nil - if callable - value = monotonic_timer{ callable.call }[0] + value = if callable + monotonic_timer { callable.call }[0] elsif block_given? - value = monotonic_timer{ yield }[0] + monotonic_timer { yield }[0] else - value = attributes.delete(:duration) || attributes.delete(:value) + attributes.delete(:duration) || attributes.delete(:value) end Honeybadger::Histogram.register(registry, name, attributes).tap do |histogram| @@ -91,14 +89,13 @@ def histogram(name, *args) def increment_counter(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) - value = nil - if callable - value = callable.call + value = if callable + callable.call elsif block_given? - value = yield + yield else - value = attributes.delete(:by) || attributes.delete(:value) || 1 + attributes.delete(:by) || attributes.delete(:value) || 1 end Honeybadger::Counter.register(registry, name, attributes).tap do |counter| @@ -109,14 +106,13 @@ def increment_counter(name, *args) def decrement_counter(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) - value = nil - if callable - value = callable.call + value = if callable + callable.call elsif block_given? - value = yield + yield else - value = attributes.delete(:by) || attributes.delete(:value) || 1 + attributes.delete(:by) || attributes.delete(:value) || 1 end Honeybadger::Counter.register(registry, name, attributes).tap do |counter| @@ -127,14 +123,13 @@ def decrement_counter(name, *args) def gauge(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) - value = nil - if callable - value = callable.call + value = if callable + callable.call elsif block_given? - value = yield + yield else - value = attributes.delete(:duration) || attributes.delete(:value) + attributes.delete(:duration) || attributes.delete(:value) end Honeybadger::Gauge.register(registry, name, attributes).tap do |gauge| diff --git a/lib/honeybadger/instrumentation_helper.rb b/lib/honeybadger/instrumentation_helper.rb index 089a338a4..1295ed07d 100644 --- a/lib/honeybadger/instrumentation_helper.rb +++ b/lib/honeybadger/instrumentation_helper.rb @@ -1,4 +1,4 @@ -require 'honeybadger/instrumentation' +require "honeybadger/instrumentation" module Honeybadger # +Honeybadger::InstrumentationHelper+ is a module that can be included into any class. This module @@ -25,7 +25,6 @@ module Honeybadger # end # end module InstrumentationHelper - # returns two parameters, the first is the duration of the execution, and the second is # the return value of the passed block def monotonic_timer @@ -53,9 +52,9 @@ def time(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) if callable - metric_instrumentation.time(name, attributes, ->{ callable.call }) + metric_instrumentation.time(name, attributes, -> { callable.call }) elsif block_given? - metric_instrumentation.time(name, attributes, ->{ yield }) + metric_instrumentation.time(name, attributes, -> { yield }) else metric_instrumentation.time(name, attributes) end @@ -65,9 +64,9 @@ def histogram(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) if callable - metric_instrumentation.histogram(name, attributes, ->{ callable.call }) + metric_instrumentation.histogram(name, attributes, -> { callable.call }) elsif block_given? - metric_instrumentation.histogram(name, attributes, ->{ yield }) + metric_instrumentation.histogram(name, attributes, -> { yield }) else metric_instrumentation.histogram(name, attributes) end @@ -77,9 +76,9 @@ def increment_counter(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) if callable - metric_instrumentation.increment_counter(name, attributes, ->{ callable.call }) + metric_instrumentation.increment_counter(name, attributes, -> { callable.call }) elsif block_given? - metric_instrumentation.increment_counter(name, attributes, ->{ yield }) + metric_instrumentation.increment_counter(name, attributes, -> { yield }) else metric_instrumentation.increment_counter(name, attributes) end @@ -89,9 +88,9 @@ def decrement_counter(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) if callable - metric_instrumentation.decrement_counter(name, attributes, ->{ callable.call }) + metric_instrumentation.decrement_counter(name, attributes, -> { callable.call }) elsif block_given? - metric_instrumentation.decrement_counter(name, attributes, ->{ yield }) + metric_instrumentation.decrement_counter(name, attributes, -> { yield }) else metric_instrumentation.decrement_counter(name, attributes) end @@ -101,9 +100,9 @@ def gauge(name, *args) attributes = extract_attributes(args) callable = extract_callable(args) if callable - metric_instrumentation.gauge(name, attributes, ->{ callable.call }) + metric_instrumentation.gauge(name, attributes, -> { callable.call }) elsif block_given? - metric_instrumentation.gauge(name, attributes, ->{ yield }) + metric_instrumentation.gauge(name, attributes, -> { yield }) else metric_instrumentation.gauge(name, attributes) end diff --git a/lib/honeybadger/karafka.rb b/lib/honeybadger/karafka.rb index e00caac8d..0014624f6 100644 --- a/lib/honeybadger/karafka.rb +++ b/lib/honeybadger/karafka.rb @@ -1,4 +1,4 @@ -require 'honeybadger/instrumentation_helper' +require "honeybadger/instrumentation_helper" module Honeybadger module Karafka @@ -10,7 +10,6 @@ def on_error_occurred(event) context = { type: event[:type] } - tags = ["type:#{event[:type]}"] if (consumer = event.payload[:caller]).respond_to?(:messages) messages = consumer.messages @@ -38,28 +37,28 @@ class InsightsListener # Note, that the once with `_d` come from Karafka, not rdkafka or Kafka RD_KAFKA_METRICS = [ # Client metrics - RdKafkaMetric.new(:increment_counter, :root, 'messages_consumed', 'rxmsgs_d'), - RdKafkaMetric.new(:increment_counter, :root, 'messages_consumed_bytes', 'rxmsg_bytes'), + RdKafkaMetric.new(:increment_counter, :root, "messages_consumed", "rxmsgs_d"), + RdKafkaMetric.new(:increment_counter, :root, "messages_consumed_bytes", "rxmsg_bytes"), # Broker metrics - RdKafkaMetric.new(:increment_counter, :brokers, 'consume_attempts', 'txretries_d'), - RdKafkaMetric.new(:increment_counter, :brokers, 'consume_errors', 'txerrs_d'), - RdKafkaMetric.new(:increment_counter, :brokers, 'receive_errors', 'rxerrs_d'), - RdKafkaMetric.new(:increment_counter, :brokers, 'connection_connects', 'connects_d'), - RdKafkaMetric.new(:increment_counter, :brokers, 'connection_disconnects', 'disconnects_d'), - RdKafkaMetric.new(:gauge, :brokers, 'network_latency_avg', %w[rtt avg]), - RdKafkaMetric.new(:gauge, :brokers, 'network_latency_p95', %w[rtt p95]), - RdKafkaMetric.new(:gauge, :brokers, 'network_latency_p99', %w[rtt p99]), + RdKafkaMetric.new(:increment_counter, :brokers, "consume_attempts", "txretries_d"), + RdKafkaMetric.new(:increment_counter, :brokers, "consume_errors", "txerrs_d"), + RdKafkaMetric.new(:increment_counter, :brokers, "receive_errors", "rxerrs_d"), + RdKafkaMetric.new(:increment_counter, :brokers, "connection_connects", "connects_d"), + RdKafkaMetric.new(:increment_counter, :brokers, "connection_disconnects", "disconnects_d"), + RdKafkaMetric.new(:gauge, :brokers, "network_latency_avg", %w[rtt avg]), + RdKafkaMetric.new(:gauge, :brokers, "network_latency_p95", %w[rtt p95]), + RdKafkaMetric.new(:gauge, :brokers, "network_latency_p99", %w[rtt p99]), # Topics metrics - RdKafkaMetric.new(:gauge, :topics, 'consumer_lags', 'consumer_lag_stored'), - RdKafkaMetric.new(:gauge, :topics, 'consumer_lags_delta', 'consumer_lag_stored_d') + RdKafkaMetric.new(:gauge, :topics, "consumer_lags", "consumer_lag_stored"), + RdKafkaMetric.new(:gauge, :topics, "consumer_lags_delta", "consumer_lag_stored_d") ].freeze # Metrics that sum values on topics levels and not on partition levels AGGREGATED_RD_KAFKA_METRICS = [ # Topic aggregated metrics - RdKafkaMetric.new(:gauge, :topics, 'consumer_aggregated_lag', 'consumer_lag_stored') + RdKafkaMetric.new(:gauge, :topics, "consumer_aggregated_lag", "consumer_lag_stored") ].freeze def initialize @@ -79,7 +78,7 @@ def on_statistics_emitted(event) statistics = event[:statistics] consumer_group_id = event[:consumer_group_id] - base_tags = { consumer_group: consumer_group_id } + base_tags = {consumer_group: consumer_group_id} RD_KAFKA_METRICS.each do |metric| report_metric(metric, statistics, base_tags) @@ -94,14 +93,14 @@ def on_statistics_emitted(event) # @param consumer_group_id [String] cg in context which we operate def report_aggregated_topics_metrics(statistics, consumer_group_id) AGGREGATED_RD_KAFKA_METRICS.each do |metric| - statistics.fetch('topics').each do |topic_name, topic_values| + statistics.fetch("topics").each do |topic_name, topic_values| sum = 0 - topic_values['partitions'].each do |partition_name, partition_statistics| - next if partition_name == '-1' + topic_values["partitions"].each do |partition_name, partition_statistics| + next if partition_name == "-1" # Skip until lag info is available - next if partition_statistics['consumer_lag'] == -1 - next if partition_statistics['consumer_lag_stored'] == -1 + next if partition_statistics["consumer_lag"] == -1 + next if partition_statistics["consumer_lag_stored"] == -1 sum += partition_statistics.dig(*metric.key_location) end @@ -121,7 +120,7 @@ def report_aggregated_topics_metrics(statistics, consumer_group_id) # # @param event [Karafka::Core::Monitoring::Event] def on_error_occurred(event) - extra_tags = { type: event[:type] } + extra_tags = {type: event[:type]} if event.payload[:caller].respond_to?(:messages) extra_tags.merge!(consumer_tags(event.payload[:caller])) @@ -132,7 +131,7 @@ def on_error_occurred(event) end if Honeybadger.config.load_plugin_insights_metrics?(:karafka) - increment_counter('error_occurred', value: 1, **extra_tags) + increment_counter("error_occurred", value: 1, **extra_tags) end end @@ -143,11 +142,11 @@ def on_connection_listener_fetch_loop_received(event) time_taken = event[:time] messages_count = event[:messages_buffer].size consumer_group_id = event[:subscription_group].consumer_group.id - extra_tags = { consumer_group: consumer_group_id } + extra_tags = {consumer_group: consumer_group_id} if Honeybadger.config.load_plugin_insights_metrics?(:karafka) - histogram('listener_polling_time_taken', value: time_taken, **extra_tags) - histogram('listener_polling_messages', value: messages_count, **extra_tags) + histogram("listener_polling_time_taken", value: time_taken, **extra_tags) + histogram("listener_polling_messages", value: messages_count, **extra_tags) end end @@ -173,13 +172,13 @@ def on_consumer_consumed(event) end if Honeybadger.config.load_plugin_insights_metrics?(:karafka) - increment_counter('consumer_messages', value: messages.count, **tags) - increment_counter('consumer_batches', value: 1, **tags) - gauge('consumer_offset', value: metadata.last_offset, **tags) - histogram('consumer_consumed_time_taken', value: event[:time], **tags) - histogram('consumer_batch_size', value: messages.count, **tags) - histogram('consumer_processing_lag', value: metadata.processing_lag, **tags) - histogram('consumer_consumption_lag', value: metadata.consumption_lag, **tags) + increment_counter("consumer_messages", value: messages.count, **tags) + increment_counter("consumer_batches", value: 1, **tags) + gauge("consumer_offset", value: metadata.last_offset, **tags) + histogram("consumer_consumed_time_taken", value: event[:time], **tags) + histogram("consumer_batch_size", value: messages.count, **tags) + histogram("consumer_processing_lag", value: metadata.processing_lag, **tags) + histogram("consumer_consumption_lag", value: metadata.consumption_lag, **tags) end end @@ -189,15 +188,15 @@ def on_consumer_consumed(event) ticked: :tick }.each do |after, name| class_eval <<~RUBY, __FILE__, __LINE__ + 1 - # Keeps track of user code execution - # - # @param event [Karafka::Core::Monitoring::Event] - def on_consumer_#{after}(event) - if Honeybadger.config.load_plugin_insights_metrics?(:karafka) - tags = consumer_tags(event.payload[:caller]) - increment_counter('consumer_#{name}', value: 1, **tags) - end - end + # Keeps track of user code execution + # + # @param event [Karafka::Core::Monitoring::Event] + def on_consumer_#{after}(event) + if Honeybadger.config.load_plugin_insights_metrics?(:karafka) + tags = consumer_tags(event.payload[:caller]) + increment_counter('consumer_#{name}', value: 1, **tags) + end + end RUBY end @@ -207,9 +206,9 @@ def on_worker_process(event) jq_stats = event[:jobs_queue].statistics if Honeybadger.config.load_plugin_insights_metrics?(:karafka) - gauge('worker_total_threads', value: ::Karafka::App.config.concurrency) - histogram('worker_processing', value: jq_stats[:busy]) - histogram('worker_enqueued_jobs', value: jq_stats[:enqueued]) + gauge("worker_total_threads", value: ::Karafka::App.config.concurrency) + histogram("worker_processing", value: jq_stats[:busy]) + histogram("worker_enqueued_jobs", value: jq_stats[:enqueued]) end end @@ -220,7 +219,7 @@ def on_worker_processed(event) jq_stats = event[:jobs_queue].statistics if Honeybadger.config.load_plugin_insights_metrics?(:karafka) - histogram('worker_processing', value: jq_stats[:busy]) + histogram("worker_processing", value: jq_stats[:busy]) end end @@ -240,30 +239,30 @@ def report_metric(metric, statistics, base_tags) **base_tags ) when :brokers - statistics.fetch('brokers').each_value do |broker_statistics| + statistics.fetch("brokers").each_value do |broker_statistics| # Skip bootstrap nodes # Bootstrap nodes have nodeid -1, other nodes have positive # node ids - next if broker_statistics['nodeid'] == -1 + next if broker_statistics["nodeid"] == -1 public_send( metric.type, metric.name, value: broker_statistics.dig(*metric.key_location), - **base_tags.merge(broker: broker_statistics['nodename']) + **base_tags.merge(broker: broker_statistics["nodename"]) ) end when :topics - statistics.fetch('topics').each do |topic_name, topic_values| - topic_values['partitions'].each do |partition_name, partition_statistics| - next if partition_name == '-1' + statistics.fetch("topics").each do |topic_name, topic_values| + topic_values["partitions"].each do |partition_name, partition_statistics| + next if partition_name == "-1" # Skip until lag info is available - next if partition_statistics['consumer_lag'] == -1 - next if partition_statistics['consumer_lag_stored'] == -1 + next if partition_statistics["consumer_lag"] == -1 + next if partition_statistics["consumer_lag_stored"] == -1 # Skip if we do not own the fetch assignment - next if partition_statistics['fetch_state'] == 'stopped' - next if partition_statistics['fetch_state'] == 'none' + next if partition_statistics["fetch_state"] == "stopped" + next if partition_statistics["fetch_state"] == "none" public_send( metric.type, diff --git a/lib/honeybadger/logging.rb b/lib/honeybadger/logging.rb index 006dc3468..b60aae875 100644 --- a/lib/honeybadger/logging.rb +++ b/lib/honeybadger/logging.rb @@ -1,12 +1,12 @@ -require 'logger' -require 'singleton' -require 'delegate' -require 'forwardable' +require "logger" +require "singleton" +require "delegate" +require "forwardable" module Honeybadger # @api private module Logging - PREFIX = '** [Honeybadger] '.freeze + PREFIX = "** [Honeybadger] ".freeze LOGGER_PROG = "honeybadger".freeze # Logging helper methods. Requires a Honeybadger::Config @config instance @@ -15,12 +15,13 @@ module Logging # logger directly to avoid extra object allocation. module Helper private + def debug(msg = nil) return true unless logger.debug? msg = yield if block_given? logger.debug(msg) end - alias :d :debug + alias_method :d, :debug def info(msg = nil) return true unless logger.info? @@ -57,7 +58,7 @@ class Base end def add(severity, msg) - raise NotImplementedError, 'must define #add on subclass.' + raise NotImplementedError, "must define #add on subclass." end def level @@ -88,13 +89,13 @@ class StandardLogger < Base extend Forwardable def initialize(logger = Logger.new(nil)) - raise ArgumentError, 'logger not specified' unless logger - raise ArgumentError, 'logger must be a logger' unless logger.respond_to?(:add) + raise ArgumentError, "logger not specified" unless logger + raise ArgumentError, "logger must be a logger" unless logger.respond_to?(:add) @logger = logger end - def add(severity, msg, progname=LOGGER_PROG) + def add(severity, msg, progname = LOGGER_PROG) @logger.add(severity, msg, progname) end @@ -102,29 +103,29 @@ def add(severity, msg, progname=LOGGER_PROG) end class FormattedLogger < StandardLogger - def add(severity, msg, progname=LOGGER_PROG) + def add(severity, msg, progname = LOGGER_PROG) super(severity, format_message(msg), progname) end private def format_message(msg) - return msg unless msg.kind_of?(String) + return msg unless msg.is_a?(String) PREFIX + msg end end class ConfigLogger < StandardLogger LOCATE_CALLER_LOCATION = Regexp.new("#{Regexp.escape(__FILE__)}").freeze - CALLER_LOCATION = Regexp.new("#{Regexp.escape(File.expand_path('../../../', __FILE__))}/(.*)").freeze + CALLER_LOCATION = Regexp.new("#{Regexp.escape(File.expand_path("../../../", __FILE__))}/(.*)").freeze - INFO_SUPPLEMENT = ' level=%s pid=%s'.freeze - DEBUG_SUPPLEMENT = ' at=%s'.freeze + INFO_SUPPLEMENT = " level=%s pid=%s".freeze + DEBUG_SUPPLEMENT = " at=%s".freeze def initialize(config, logger = Logger.new(nil)) @config = config @tty = STDOUT.tty? - @tty_level = @config.log_level(:'logging.tty_level') + @tty_level = @config.log_level(:"logging.tty_level") super(logger) end @@ -156,7 +157,7 @@ def suppress_tty?(severity) end def supplement(msg, severity) - return msg unless msg.kind_of?(String) + return msg unless msg.is_a?(String) r = msg.dup r << sprintf(INFO_SUPPLEMENT, severity, Process.pid) @@ -168,7 +169,7 @@ def supplement(msg, severity) end def caller_location - if caller && caller.find {|l| l !~ LOCATE_CALLER_LOCATION && l =~ CALLER_LOCATION } + if caller && caller.find { |l| l !~ LOCATE_CALLER_LOCATION && l =~ CALLER_LOCATION } Regexp.last_match(1) end end diff --git a/lib/honeybadger/metric.rb b/lib/honeybadger/metric.rb index 11801e96c..a8a11412c 100644 --- a/lib/honeybadger/metric.rb +++ b/lib/honeybadger/metric.rb @@ -3,11 +3,11 @@ class Metric attr_reader :name, :attributes, :samples def self.metric_type - name.split('::').last.downcase + name.split("::").last.downcase end def self.signature(metric_type, name, attributes) - Digest::SHA1.hexdigest("#{metric_type}-#{name}-#{attributes.keys.join('-')}-#{attributes.values.join('-')}").to_sym + Digest::SHA1.hexdigest("#{metric_type}-#{name}-#{attributes.keys.join("-")}-#{attributes.values.join("-")}").to_sym end def self.register(registry, metric_name, attributes) diff --git a/lib/honeybadger/metrics_worker.rb b/lib/honeybadger/metrics_worker.rb index 1241ed37e..1948b3a23 100644 --- a/lib/honeybadger/metrics_worker.rb +++ b/lib/honeybadger/metrics_worker.rb @@ -1,4 +1,4 @@ -require 'honeybadger/logging' +require "honeybadger/logging" module Honeybadger # A concurrent queue to execute plugin collect blocks and registry. @@ -40,7 +40,7 @@ def send_now(msg) end def shutdown(force = false) - d { 'shutting down worker' } + d { "shutting down worker" } mutex.synchronize do @shutdown = true @@ -101,7 +101,7 @@ def can_start? end def kill! - d { 'killing worker thread' } + d { "killing worker thread" } if thread Thread.kill(thread) @@ -123,7 +123,7 @@ def suspend(interval) def run begin - d { 'worker started' } + d { "worker started" } loop do case msg = queue.pop when SHUTDOWN then break @@ -132,7 +132,7 @@ def run end end ensure - d { 'stopping worker' } + d { "stopping worker" } end rescue Exception => e error { @@ -148,9 +148,9 @@ def work(msg) if shutdown? kill! - return + nil end - rescue StandardError => e + rescue => e error { err = "Error in worker thread class=%s message=%s\n\t%s" sprintf(err, e.class, e.message.dump, Array(e.backtrace).join("\n\t")) diff --git a/lib/honeybadger/notice.rb b/lib/honeybadger/notice.rb index 0d8cdc92e..79250066d 100644 --- a/lib/honeybadger/notice.rb +++ b/lib/honeybadger/notice.rb @@ -1,35 +1,35 @@ -require 'json' -require 'securerandom' -require 'forwardable' - -require 'honeybadger/version' -require 'honeybadger/backtrace' -require 'honeybadger/conversions' -require 'honeybadger/util/stats' -require 'honeybadger/util/sanitizer' -require 'honeybadger/util/request_hash' -require 'honeybadger/util/request_payload' +require "json" +require "securerandom" +require "forwardable" + +require "honeybadger/version" +require "honeybadger/backtrace" +require "honeybadger/conversions" +require "honeybadger/util/stats" +require "honeybadger/util/sanitizer" +require "honeybadger/util/request_hash" +require "honeybadger/util/request_payload" module Honeybadger # @api private NOTIFIER = { - name: 'honeybadger-ruby'.freeze, - url: 'https://github.com/honeybadger-io/honeybadger-ruby'.freeze, + name: "honeybadger-ruby".freeze, + url: "https://github.com/honeybadger-io/honeybadger-ruby".freeze, version: VERSION, - language: 'ruby'.freeze + language: "ruby".freeze }.freeze # @api private # Substitution for gem root in backtrace lines. - GEM_ROOT = '[GEM_ROOT]'.freeze + GEM_ROOT = "[GEM_ROOT]".freeze # @api private # Substitution for project root in backtrace lines. - PROJECT_ROOT = '[PROJECT_ROOT]'.freeze + PROJECT_ROOT = "[PROJECT_ROOT]".freeze # @api private # Empty String (used for equality comparisons and assignment). - STRING_EMPTY = ''.freeze + STRING_EMPTY = "".freeze # @api private # A Regexp which matches non-blank characters. @@ -177,10 +177,10 @@ def parsed_backtrace c = (PROJECT_ROOT_CACHE[config[:root]] ||= {}) return c[line] if c.has_key?(line) c[line] ||= if config.root_regexp - line.sub(config.root_regexp, PROJECT_ROOT) - else - line - end + line.sub(config.root_regexp, PROJECT_ROOT) + else + line + end }, lambda { |line| line.sub(RELATIVE_ROOT, STRING_EMPTY) }, lambda { |line| line if line !~ %r{lib/honeybadger} } @@ -188,9 +188,9 @@ def parsed_backtrace # @api private def initialize(config, opts = {}) - @now = Time.now.utc - @pid = Process.pid - @id = SecureRandom.uuid + @now = Time.now.utc + @pid = Process.pid + @id = SecureRandom.uuid @stats = Util::Stats.all @opts = opts @@ -201,10 +201,10 @@ def initialize(config, opts = {}) @exception = unwrap_exception(opts[:exception]) - self.error_class = exception_attribute(:error_class, 'Notice') {|exception| exception.class.name } - self.error_message = exception_attribute(:error_message, 'No message provided') do |exception| + self.error_class = exception_attribute(:error_class, "Notice") { |exception| exception.class.name } + self.error_message = exception_attribute(:error_message, "No message provided") do |exception| message = exception.respond_to?(:detailed_message) ? - exception.detailed_message(highlight: false).sub(" (#{exception.class.name})", '') # Gems like error_highlight append the exception class name + exception.detailed_message(highlight: false).sub(" (#{exception.class.name})", "") # Gems like error_highlight append the exception class name : exception.message "#{exception.class.name}: #{message}" end @@ -216,13 +216,13 @@ def initialize(config, opts = {}) self.api_key = opts[:api_key] || config[:api_key] self.tags = construct_tags(opts[:tags]) | construct_tags(context[:tags]) - self.url = opts[:url] || request_hash[:url] || nil - self.action = opts[:action] || request_hash[:action] || nil - self.component = opts[:controller] || opts[:component] || request_hash[:component] || nil - self.params = opts[:parameters] || opts[:params] || request_hash[:params] || {} - self.session = opts[:session] || request_hash[:session] || {} - self.cgi_data = opts[:cgi_data] || request_hash[:cgi_data] || {} - self.details = opts[:details] || {} + self.url = opts[:url] || request_hash[:url] || nil + self.action = opts[:action] || request_hash[:action] || nil + self.component = opts[:controller] || opts[:component] || request_hash[:component] || nil + self.params = opts[:parameters] || opts[:params] || request_hash[:params] || {} + self.session = opts[:session] || request_hash[:session] || {} + self.cgi_data = opts[:cgi_data] || request_hash[:cgi_data] || {} + self.details = opts[:details] || {} self.request_id = opts[:request_id] || nil self.session = opts[:session][:data] if opts[:session] && opts[:session][:data] @@ -305,7 +305,7 @@ def halted? def ignore_by_origin? return false if opts[:origin] != :rake - return false if config[:'exceptions.rescue_rake'] + return false if config[:"exceptions.rescue_rake"] true end @@ -353,7 +353,7 @@ def from_exception(attribute) # # Returns true or false. def ignore_by_class?(ignored_class = nil) - @ignore_by_class ||= Proc.new do |ignored_class| + @ignore_by_class ||= proc do |ignored_class| case error_class when (ignored_class.respond_to?(:name) ? ignored_class.name : ignored_class) true @@ -388,7 +388,7 @@ def construct_request_hash cgi_data: cgi_data, sanitizer: request_sanitizer } - request.delete_if {|k,v| config.excluded_request_keys.include?(k) } + request.delete_if { |k, v| config.excluded_request_keys.include?(k) } Util::RequestPayload.build(request) end @@ -471,24 +471,22 @@ def local_variables_from_exception(exception, config) if BINDING_HAS_SOURCE_LOCATION b.source_location[0] else - b.eval('__FILE__') + b.eval("__FILE__") end =~ /^#{Regexp.escape(config[:root].to_s)}/ } end binding ||= exception.__honeybadger_bindings_stack[0] - vars = binding.eval('local_variables') + vars = binding.eval("local_variables") results = - vars.inject([]) { |acc, arg| + vars.each_with_object([]) { |arg, acc| begin result = binding.eval(arg.to_s) acc << [arg, result] rescue NameError # Do Nothing end - - acc } result_hash = Hash[results] @@ -499,7 +497,7 @@ def local_variables_from_exception(exception, config) # # Returns true to send local_variables. def send_local_variables?(config) - config[:'exceptions.local_variables'] + config[:"exceptions.local_variables"] end # Parse Backtrace from exception backtrace. @@ -512,7 +510,7 @@ def parse_backtrace(backtrace) backtrace, filters: construct_backtrace_filters(opts), config: config, - source_radius: config[:'exceptions.source_radius'] + source_radius: config[:"exceptions.source_radius"] ).to_a end @@ -523,7 +521,7 @@ def parse_backtrace(backtrace) # # Returns the Exception to report. def unwrap_exception(exception) - return exception unless config[:'exceptions.unwrap'] + return exception unless config[:"exceptions.unwrap"] exception_cause(exception) || exception end @@ -566,7 +564,7 @@ def unwrap_causes(cause) # # Returns the Array of causes in Hash payload format. def prepare_causes(causes) - causes.map {|c| + causes.map { |c| { class: c.error_class, message: c.error_message, @@ -580,7 +578,7 @@ def params_filters end def rails_params_filters - rack_env && Array(rack_env['action_dispatch.parameter_filter']) or [] + rack_env && Array(rack_env["action_dispatch.parameter_filter"]) or [] end end end diff --git a/lib/honeybadger/notification_subscriber.rb b/lib/honeybadger/notification_subscriber.rb index 3f2d59d23..d55161099 100644 --- a/lib/honeybadger/notification_subscriber.rb +++ b/lib/honeybadger/notification_subscriber.rb @@ -1,5 +1,5 @@ -require 'honeybadger/instrumentation_helper' -require 'honeybadger/util/sql' +require "honeybadger/instrumentation_helper" +require "honeybadger/util/sql" module Honeybadger class NotificationSubscriber @@ -27,21 +27,21 @@ def record(name, payload) end if Honeybadger.config.load_plugin_insights_metrics?(:rails) - metric_source 'rails' + metric_source "rails" record_metrics(name, payload) end end def record_metrics(name, payload) case name - when 'sql.active_record' - gauge('duration.sql.active_record', value: payload[:duration], **payload.slice(:query)) - when 'process_action.action_controller' - gauge('duration.process_action.action_controller', value: payload[:duration], **payload.slice(:method, :controller, :action, :format, :status)) - gauge('db_runtime.process_action.action_controller', value: payload[:db_runtime], **payload.slice(:method, :controller, :action, :format, :status)) - gauge('view_runtime.process_action.action_controller', value: payload[:view_runtime], **payload.slice(:method, :controller, :action, :format, :status)) - when 'perform.active_job' - gauge('duration.perform.active_job', value: payload[:duration], **payload.slice(:job_class, :queue_name)) + when "sql.active_record" + gauge("duration.sql.active_record", value: payload[:duration], **payload.slice(:query)) + when "process_action.action_controller" + gauge("duration.process_action.action_controller", value: payload[:duration], **payload.slice(:method, :controller, :action, :format, :status)) + gauge("db_runtime.process_action.action_controller", value: payload[:db_runtime], **payload.slice(:method, :controller, :action, :format, :status)) + gauge("view_runtime.process_action.action_controller", value: payload[:view_runtime], **payload.slice(:method, :controller, :action, :format, :status)) + when "perform.active_job" + gauge("duration.perform.active_job", value: payload[:duration], **payload.slice(:job_class, :queue_name)) when /^cache_.*.active_support$/ gauge("duration.#{name}", value: payload[:duration], **payload.slice(:store, :key)) end @@ -95,11 +95,11 @@ def expand_cache_keys_from_payload(data) end class ActionViewSubscriber < NotificationSubscriber - PROJECT_ROOT = defined?(::Rails) ? ::Rails.root.to_s : '' + PROJECT_ROOT = defined?(::Rails) ? ::Rails.root.to_s : "" def format_payload(payload) { - view: payload[:identifier].to_s.gsub(PROJECT_ROOT, '[PROJECT_ROOT]'), + view: payload[:identifier].to_s.gsub(PROJECT_ROOT, "[PROJECT_ROOT]"), layout: payload[:layout] } end diff --git a/lib/honeybadger/plugin.rb b/lib/honeybadger/plugin.rb index ae3e96b89..e87a8cf2a 100644 --- a/lib/honeybadger/plugin.rb +++ b/lib/honeybadger/plugin.rb @@ -1,5 +1,5 @@ -require 'forwardable' -require 'honeybadger/instrumentation_helper' +require "forwardable" +require "honeybadger/instrumentation_helper" module Honeybadger # +Honeybadger::Plugin+ defines the API for registering plugins with @@ -84,7 +84,7 @@ def instances # @return nil def register(name = nil, &block) name ||= name_from_caller(caller) or - raise(ArgumentError, 'Plugin name is required, but was nil.') + raise(ArgumentError, "Plugin name is required, but was nil.") instances[key = name.to_sym] and fail("Already registered: #{name}") instances[key] = new(name).tap { |d| d.instance_eval(&block) } end @@ -95,7 +95,7 @@ def load!(config) if config.load_plugin?(name) plugin.load!(config) else - config.logger.debug(sprintf('skip plugin name=%s reason=disabled', name)) + config.logger.debug(sprintf("skip plugin name=%s reason=disabled", name)) end end end @@ -157,11 +157,11 @@ def register! # @api private def initialize(name) - @name = name - @loaded = false + @name = name + @loaded = false @requirements = [] - @executions = [] - @collectors = [] + @executions = [] + @collectors = [] end # Define a requirement. All requirement blocks must return +true+ for the @@ -231,13 +231,13 @@ def execution(&block) # end # # @return nil - def collect(options={}, &block) + def collect(options = {}, &block) @collectors << [options, block] end # @api private def ok?(config) - @requirements.all? {|r| Execution.new(config, &r).call } + @requirements.all? { |r| Execution.new(config, &r).call } rescue => e config.logger.error(sprintf("plugin error name=%s class=%s message=%s\n\t%s", name, e.class, e.message.dump, Array(e.backtrace).join("\n\t"))) false @@ -246,15 +246,15 @@ def ok?(config) # @api private def load!(config) if @loaded - config.logger.debug(sprintf('skip plugin name=%s reason=loaded', name)) + config.logger.debug(sprintf("skip plugin name=%s reason=loaded", name)) return false elsif ok?(config) - config.logger.debug(sprintf('load plugin name=%s', name)) - @executions.each {|e| Execution.new(config, &e).call } - @collectors.each {|o,b| CollectorExecution.new(name, config, o, &b).register! } + config.logger.debug(sprintf("load plugin name=%s", name)) + @executions.each { |e| Execution.new(config, &e).call } + @collectors.each { |o, b| CollectorExecution.new(name, config, o, &b).register! } @loaded = true else - config.logger.debug(sprintf('skip plugin name=%s reason=requirement', name)) + config.logger.debug(sprintf("skip plugin name=%s reason=requirement", name)) end @loaded @@ -265,9 +265,7 @@ def load!(config) end # @api private - def collectors - @collectors - end + attr_reader :collectors # @api private def loaded? diff --git a/lib/honeybadger/plugins/active_job.rb b/lib/honeybadger/plugins/active_job.rb index 941881d37..57ed2dcbf 100644 --- a/lib/honeybadger/plugins/active_job.rb +++ b/lib/honeybadger/plugins/active_job.rb @@ -1,4 +1,4 @@ -require 'honeybadger/notification_subscriber' +require "honeybadger/notification_subscriber" module Honeybadger module Plugins @@ -11,19 +11,21 @@ def perform_around(job, block) Honeybadger.clear! context = context(job) block.call - rescue StandardError => e - Honeybadger.notify( - e, - context: context, - parameters: { arguments: job.arguments } - ) if job.executions >= Honeybadger.config[:'active_job.attempt_threshold'].to_i + rescue => e + if job.executions >= Honeybadger.config[:"active_job.attempt_threshold"].to_i + Honeybadger.notify( + e, + context: context, + parameters: {arguments: job.arguments} + ) + end raise e end def context(job) # rubocop:disable Metrics/MethodLength { component: job.class, - action: 'perform', + action: "perform", enqueued_at: job.try(:enqueued_at), executions: job.executions, job_class: job.class, @@ -51,7 +53,7 @@ def context(job) # rubocop:disable Metrics/MethodLength end execution do - ::ActiveJob::Base.set_callback(:perform, :around, &ActiveJob.method(:perform_around)) if Honeybadger.config[:'exceptions.enabled'] + ::ActiveJob::Base.set_callback(:perform, :around, &ActiveJob.method(:perform_around)) if Honeybadger.config[:"exceptions.enabled"] if config.load_plugin_insights?(:active_job) ::ActiveSupport::Notifications.subscribe(/(enqueue_at|enqueue|enqueue_retry|enqueue_all|perform|retry_stopped|discard)\.active_job/, Honeybadger::ActiveJobSubscriber.new) diff --git a/lib/honeybadger/plugins/autotuner.rb b/lib/honeybadger/plugins/autotuner.rb index b50f9f6df..b74202f23 100644 --- a/lib/honeybadger/plugins/autotuner.rb +++ b/lib/honeybadger/plugins/autotuner.rb @@ -1,5 +1,5 @@ -require 'honeybadger/instrumentation_helper' -require 'honeybadger/plugin' +require "honeybadger/instrumentation_helper" +require "honeybadger/plugin" module Honeybadger module Plugins @@ -16,13 +16,13 @@ module Autotuner ::Autotuner.metrics_reporter = proc do |metrics| if config.load_plugin_insights_events?(:autotuner) - Honeybadger.event('stats.autotuner', metrics) + Honeybadger.event("stats.autotuner", metrics) end if config.load_plugin_insights_metrics?(:autotuner) - metric_source 'autotuner' + metric_source "autotuner" metrics.each do |key, val| - gauge key, ->{ val } + gauge key, -> { val } end end end diff --git a/lib/honeybadger/plugins/breadcrumbs.rb b/lib/honeybadger/plugins/breadcrumbs.rb index 159320784..10d2d4604 100644 --- a/lib/honeybadger/plugins/breadcrumbs.rb +++ b/lib/honeybadger/plugins/breadcrumbs.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/breadcrumbs/logging' +require "honeybadger/plugin" +require "honeybadger/breadcrumbs/logging" module Honeybadger module Plugins @@ -41,19 +41,19 @@ module Plugins # See RailsBreadcrumbs.send_breadcrumb_notification for specifics on the # options for customization Plugin.register :breadcrumbs do - requirement { config[:'breadcrumbs.enabled'] } + requirement { config[:"breadcrumbs.enabled"] } execution do # Rails specific breadcrumb events # if defined?(::Rails.application) && ::Rails.application - config[:'breadcrumbs.active_support_notifications'].each do |name, config| + config[:"breadcrumbs.active_support_notifications"].each do |name, config| RailsBreadcrumbs.subscribe_to_notification(name, config) end - ActiveSupport::LogSubscriber.prepend(Honeybadger::Breadcrumbs::LogSubscriberInjector) if config[:'breadcrumbs.logging.enabled'] + ActiveSupport::LogSubscriber.prepend(Honeybadger::Breadcrumbs::LogSubscriberInjector) if config[:"breadcrumbs.logging.enabled"] end - ::Logger.prepend(Honeybadger::Breadcrumbs::LogWrapper) if config[:'breadcrumbs.logging.enabled'] + ::Logger.prepend(Honeybadger::Breadcrumbs::LogWrapper) if config[:"breadcrumbs.logging.enabled"] end end diff --git a/lib/honeybadger/plugins/delayed_job.rb b/lib/honeybadger/plugins/delayed_job.rb index da23c2fdd..e3f087c20 100644 --- a/lib/honeybadger/plugins/delayed_job.rb +++ b/lib/honeybadger/plugins/delayed_job.rb @@ -1,4 +1,4 @@ -require 'honeybadger/plugin' +require "honeybadger/plugin" module Honeybadger Plugin.register do @@ -15,8 +15,8 @@ module Honeybadger end execution do - return unless Honeybadger.config[:'exceptions.enabled'] - require 'honeybadger/plugins/delayed_job/plugin' + return unless Honeybadger.config[:"exceptions.enabled"] + require "honeybadger/plugins/delayed_job/plugin" ::Delayed::Worker.plugins << Plugins::DelayedJob::Plugin end end diff --git a/lib/honeybadger/plugins/delayed_job/plugin.rb b/lib/honeybadger/plugins/delayed_job/plugin.rb index b3bf4b58d..6869c7cc8 100644 --- a/lib/honeybadger/plugins/delayed_job/plugin.rb +++ b/lib/honeybadger/plugins/delayed_job/plugin.rb @@ -1,5 +1,5 @@ -require 'delayed_job' -require 'honeybadger/ruby' +require "delayed_job" +require "honeybadger/ruby" module Honeybadger module Plugins @@ -8,42 +8,43 @@ class Plugin < ::Delayed::Plugin callbacks do |lifecycle| lifecycle.around(:invoke_job) do |job, &block| begin - begin - if job.payload_object.class.name == 'ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper' - #buildin support for Rails 4.2 ActiveJob - component = job.payload_object.job_data['job_class'] - action = 'perform' + if job.payload_object.class.name == "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper" + # buildin support for Rails 4.2 ActiveJob + component = job.payload_object.job_data["job_class"] + action = "perform" else - #buildin support for Delayed::PerformableMethod + # buildin support for Delayed::PerformableMethod component = job.payload_object.object.is_a?(Class) ? job.payload_object.object.name : job.payload_object.object.class.name - action = job.payload_object.method_name.to_s + action = job.payload_object.method_name.to_s end - rescue #fallback to support all other classes + rescue # fallback to support all other classes component = job.payload_object.class.name - action = 'perform' + action = "perform" end ::Honeybadger.context( - :component => component, - :action => action, - :job_id => job.id, - :handler => job.handler, - :last_error => job.last_error, - :attempts => job.attempts, - :queue => job.queue + component: component, + action: action, + job_id: job.id, + handler: job.handler, + last_error: job.last_error, + attempts: job.attempts, + queue: job.queue ) block.call(job) rescue Exception => error - ::Honeybadger.notify( - :component => component, - :action => action, - :error_class => error.class.name, - :error_message => "#{ error.class.name }: #{ error.message }", - :backtrace => error.backtrace, - :exception => error - ) if job.attempts.to_i >= ::Honeybadger.config[:'delayed_job.attempt_threshold'].to_i + if job.attempts.to_i >= ::Honeybadger.config[:"delayed_job.attempt_threshold"].to_i + ::Honeybadger.notify( + component: component, + action: action, + error_class: error.class.name, + error_message: "#{error.class.name}: #{error.message}", + backtrace: error.backtrace, + exception: error + ) + end raise error ensure ::Honeybadger.clear! diff --git a/lib/honeybadger/plugins/faktory.rb b/lib/honeybadger/plugins/faktory.rb index a13401f3e..d62d4af11 100644 --- a/lib/honeybadger/plugins/faktory.rb +++ b/lib/honeybadger/plugins/faktory.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/ruby' +require "honeybadger/plugin" +require "honeybadger/ruby" module Honeybadger module Plugins @@ -15,7 +15,7 @@ def call(worker, job) requirement { defined?(::Faktory) } execution do - return unless Honeybadger.config[:'exceptions.enabled'] + return unless Honeybadger.config[:"exceptions.enabled"] ::Faktory.configure_worker do |faktory| faktory.worker_middleware do |chain| chain.prepend Middleware @@ -27,20 +27,20 @@ def call(worker, job) opts = {parameters: params} if job = params[:job] - if (threshold = config[:'faktory.attempt_threshold'].to_i) > 0 + if (threshold = config[:"faktory.attempt_threshold"].to_i) > 0 # If job.failure is nil, it is the first attempt. The first # retry has a job.failure.retry_count of 0, which would be # the second attempt in our case. - retry_count = job.dig('failure', 'retry_count') + retry_count = job.dig("failure", "retry_count") attempt = retry_count ? retry_count + 1 : 0 - limit = [job['retry'].to_i, threshold].min + limit = [job["retry"].to_i, threshold].min return if attempt < limit end - opts[:component] = job['jobtype'] - opts[:action] = 'perform' + opts[:component] = job["jobtype"] + opts[:action] = "perform" end Honeybadger.notify(ex, opts) diff --git a/lib/honeybadger/plugins/karafka.rb b/lib/honeybadger/plugins/karafka.rb index a7d84f536..bb7e0982f 100644 --- a/lib/honeybadger/plugins/karafka.rb +++ b/lib/honeybadger/plugins/karafka.rb @@ -1,4 +1,4 @@ -require 'honeybadger/plugin' +require "honeybadger/plugin" module Honeybadger module Plugins @@ -6,9 +6,9 @@ module Plugins requirement { defined?(::Karafka) && ::Karafka.respond_to?(:monitor) } execution do - require 'honeybadger/karafka' + require "honeybadger/karafka" - if Honeybadger.config[:'exceptions.enabled'] + if Honeybadger.config[:"exceptions.enabled"] errors_listener = ::Honeybadger::Karafka::ErrorsListener.new ::Karafka.monitor.subscribe(errors_listener) ::Karafka.producer.monitor.subscribe(errors_listener) if ::Karafka.respond_to?(:producer) diff --git a/lib/honeybadger/plugins/lambda.rb b/lib/honeybadger/plugins/lambda.rb index 7ffe3b935..f12fa496e 100644 --- a/lib/honeybadger/plugins/lambda.rb +++ b/lib/honeybadger/plugins/lambda.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/util/lambda' +require "honeybadger/plugin" +require "honeybadger/util/lambda" module Honeybadger module Plugins @@ -38,7 +38,7 @@ def hb_wrap_handler(*handler_names) end end - self.singleton_class.prepend(mod) + singleton_class.prepend(mod) Kernel.singleton_class.prepend(mod) if self == TOPLEVEL_BINDING.eval("self") end end @@ -49,7 +49,7 @@ def hb_wrap_handler(*handler_names) execution do config[:sync] = true - config[:'exceptions.notify_at_exit'] = false + config[:"exceptions.notify_at_exit"] = false main = TOPLEVEL_BINDING.eval("self") main.extend(LambdaExtension) diff --git a/lib/honeybadger/plugins/local_variables.rb b/lib/honeybadger/plugins/local_variables.rb index bc369ea2c..2f68785b1 100644 --- a/lib/honeybadger/plugins/local_variables.rb +++ b/lib/honeybadger/plugins/local_variables.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/backtrace' +require "honeybadger/plugin" +require "honeybadger/backtrace" module Honeybadger module Plugins @@ -24,7 +24,7 @@ def __honeybadger_bindings_stack end Plugin.register do - requirement { config[:'exceptions.local_variables'] } + requirement { config[:"exceptions.local_variables"] } requirement { defined?(::BindingOfCaller) } requirement do if res = defined?(::BetterErrors) diff --git a/lib/honeybadger/plugins/net_http.rb b/lib/honeybadger/plugins/net_http.rb index 5adc00f5b..eec36b542 100644 --- a/lib/honeybadger/plugins/net_http.rb +++ b/lib/honeybadger/plugins/net_http.rb @@ -1,7 +1,7 @@ -require 'net/http' -require 'honeybadger/plugin' -require 'honeybadger/instrumentation' -require 'resolv' +require "net/http" +require "honeybadger/plugin" +require "honeybadger/instrumentation" +require "resolv" module Honeybadger module Plugins @@ -25,31 +25,31 @@ def request(request_data, body = nil, &block) }.merge(parsed_uri_data(request_data)) if @@hb_config.load_plugin_insights_events?(:net_http) - Honeybadger.event('request.net_http', context) + Honeybadger.event("request.net_http", context) end if @@hb_config.load_plugin_insights_metrics?(:net_http) context.delete(:url) - Honeybadger.gauge('duration.request', context.merge(metric_source: 'net_http')) + Honeybadger.gauge("duration.request", context.merge(metric_source: "net_http")) end end[1] # return the response data only end def hb? - address.to_s[/#{@@hb_config[:'connection.host'].to_s}/] + address.to_s[/#{@@hb_config[:"connection.host"]}/] end def parsed_uri_data(request_data) uri = request_data.uri || build_uri(request_data) {}.tap do |uri_data| uri_data[:host] = uri.host - uri_data[:url] = uri.to_s if @@hb_config[:'net_http.insights.full_url'] + uri_data[:url] = uri.to_s if @@hb_config[:"net_http.insights.full_url"] end end def build_uri(request_data) - hostname = (address[/#{Resolv::IPv6::Regex}/]) ? "[#{address}]" : address - URI.parse("#{use_ssl? ? 'https' : 'http'}://#{hostname}#{request_data.path}") + hostname = address[/#{Resolv::IPv6::Regex}/o] ? "[#{address}]" : address + URI.parse("#{use_ssl? ? "https" : "http"}://#{hostname}#{request_data.path}") end Plugin.register :net_http do diff --git a/lib/honeybadger/plugins/passenger.rb b/lib/honeybadger/plugins/passenger.rb index e6f868f50..e2eb4180d 100644 --- a/lib/honeybadger/plugins/passenger.rb +++ b/lib/honeybadger/plugins/passenger.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/agent' +require "honeybadger/plugin" +require "honeybadger/agent" module Honeybadger module Plugins @@ -9,11 +9,11 @@ module Passenger execution do ::PhusionPassenger.on_event(:starting_worker_process) do |forked| - logger.debug('Starting passenger worker process') + logger.debug("Starting passenger worker process") end ::PhusionPassenger.on_event(:stopping_worker_process) do - logger.debug('Stopping passenger worker process') + logger.debug("Stopping passenger worker process") Honeybadger.stop end end diff --git a/lib/honeybadger/plugins/rails.rb b/lib/honeybadger/plugins/rails.rb index 5b8b039d1..3902b365f 100644 --- a/lib/honeybadger/plugins/rails.rb +++ b/lib/honeybadger/plugins/rails.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/notification_subscriber' +require "honeybadger/plugin" +require "honeybadger/notification_subscriber" module Honeybadger module Plugins @@ -15,7 +15,7 @@ module ExceptionsCatcher # @return The super value of the middleware's +#render_exception()+ # method. def render_exception(arg, exception, *args) - if arg.kind_of?(::ActionDispatch::Request) + if arg.is_a?(::ActionDispatch::Request) request = arg env = request.env else @@ -23,10 +23,14 @@ def render_exception(arg, exception, *args) env = arg end - env['honeybadger.exception'] = exception - env['honeybadger.request.url'] = request.url rescue nil + env["honeybadger.exception"] = exception + env["honeybadger.request.url"] = begin + request.url + rescue + nil + end - super(arg, exception, *args) + super end end @@ -45,7 +49,7 @@ def self.report(exception, handled:, severity:, context: {}, source: nil) end def self.source_ignored?(source) - source && ::Honeybadger.config[:'rails.subscriber_ignore_sources'].any? do |ignored_source| + source && ::Honeybadger.config[:"rails.subscriber_ignore_sources"].any? do |ignored_source| ignored_source.is_a?(Regexp) ? ignored_source.match?(source) : (ignored_source == source) end end @@ -55,7 +59,7 @@ def self.source_ignored?(source) requirement { defined?(::Rails.application) && ::Rails.application } execution do - require 'rack/request' + require "rack/request" if defined?(::ActionDispatch::DebugExceptions) # Rails 3.2.x+ ::ActionDispatch::DebugExceptions.prepend(ExceptionsCatcher) @@ -64,7 +68,7 @@ def self.source_ignored?(source) ::ActionDispatch::ShowExceptions.prepend(ExceptionsCatcher) end - if Honeybadger.config[:'exceptions.enabled'] && defined?(::ActiveSupport::ErrorReporter) # Rails 7 + if Honeybadger.config[:"exceptions.enabled"] && defined?(::ActiveSupport::ErrorReporter) # Rails 7 if defined?(::ActiveSupport::ExecutionContext) ::ActiveSupport::ExecutionContext.after_change do Honeybadger.context(::ActiveSupport::ExecutionContext.to_h) diff --git a/lib/honeybadger/plugins/resque.rb b/lib/honeybadger/plugins/resque.rb index 8ec04aca2..a5910ff53 100644 --- a/lib/honeybadger/plugins/resque.rb +++ b/lib/honeybadger/plugins/resque.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/ruby' +require "honeybadger/plugin" +require "honeybadger/ruby" module Honeybadger module Plugins @@ -18,18 +18,18 @@ def after_perform_with_honeybadger(*args) # Error notifications must be synchronous as the +on_failure+ hook is # executed after +around_perform+. def on_failure_with_honeybadger(e, *args) - Honeybadger.notify(e, parameters: { job_arguments: args }, sync: true) if send_exception_to_honeybadger?(e, args) + Honeybadger.notify(e, parameters: {job_arguments: args}, sync: true) if send_exception_to_honeybadger?(e, args) ensure Honeybadger.clear! end def send_exception_to_honeybadger?(e, args) return true unless respond_to?(:retry_criteria_valid?) - return true if ::Honeybadger.config[:'resque.resque_retry.send_exceptions_when_retrying'] + return true if ::Honeybadger.config[:"resque.resque_retry.send_exceptions_when_retrying"] !retry_criteria_valid?(e) rescue => e - Honeybadger.notify(e, parameters: { job_arguments: args }, sync: true) + Honeybadger.notify(e, parameters: {job_arguments: args}, sync: true) end end @@ -64,7 +64,7 @@ def payload_class_with_honeybadger end execution do - return unless Honeybadger.config[:'exceptions.enabled'] + return unless Honeybadger.config[:"exceptions.enabled"] ::Resque::Job.send(:include, Installer) end end diff --git a/lib/honeybadger/plugins/shoryuken.rb b/lib/honeybadger/plugins/shoryuken.rb index d15f10cde..f9c028dbd 100644 --- a/lib/honeybadger/plugins/shoryuken.rb +++ b/lib/honeybadger/plugins/shoryuken.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/ruby' +require "honeybadger/plugin" +require "honeybadger/ruby" module Honeybadger module Plugins @@ -22,17 +22,17 @@ def call(_worker, _queue, sqs_msg, body) private def attempt_threshold - ::Honeybadger.config[:'shoryuken.attempt_threshold'].to_i + ::Honeybadger.config[:"shoryuken.attempt_threshold"].to_i end def receive_count(sqs_msg) return 0 if sqs_msg.is_a?(Array) - sqs_msg.attributes['ApproximateReceiveCount'.freeze].to_i + sqs_msg.attributes["ApproximateReceiveCount".freeze].to_i end def notification_params(body) - body.is_a?(Array) ? { batch: body } : { body: body } + body.is_a?(Array) ? {batch: body} : {body: body} end end @@ -40,7 +40,7 @@ def notification_params(body) requirement { defined?(::Shoryuken) } execution do - return unless Honeybadger.config[:'exceptions.enabled'] + return unless Honeybadger.config[:"exceptions.enabled"] ::Shoryuken.configure_server do |config| config.server_middleware do |chain| chain.add Middleware diff --git a/lib/honeybadger/plugins/sidekiq.rb b/lib/honeybadger/plugins/sidekiq.rb index ceb266da3..6d3eb28a0 100644 --- a/lib/honeybadger/plugins/sidekiq.rb +++ b/lib/honeybadger/plugins/sidekiq.rb @@ -1,6 +1,6 @@ -require 'honeybadger/instrumentation_helper' -require 'honeybadger/plugin' -require 'honeybadger/ruby' +require "honeybadger/instrumentation_helper" +require "honeybadger/plugin" +require "honeybadger/ruby" module Honeybadger module Plugins @@ -16,14 +16,14 @@ class ServerMiddlewareInstrumentation include Honeybadger::InstrumentationHelper def call(worker, msg, queue, &block) - if msg["wrapped"] - context = { + context = if msg["wrapped"] + { jid: msg["jid"], worker: msg["wrapped"], queue: queue } else - context = { + { jid: msg["jid"], worker: msg["class"], queue: queue @@ -32,19 +32,19 @@ def call(worker, msg, queue, &block) begin duration = Honeybadger.instrumentation.monotonic_timer { block.call }[0] - status = 'success' - rescue Exception => e - status = 'failure' + status = "success" + rescue Exception + status = "failure" raise ensure context.merge!(duration: duration, status: status) if Honeybadger.config.load_plugin_insights_events?(:sidekiq) - Honeybadger.event('perform.sidekiq', context) + Honeybadger.event("perform.sidekiq", context) end if Honeybadger.config.load_plugin_insights_metrics?(:sidekiq) - metric_source 'sidekiq' - gauge 'perform', context.slice(:worker, :queue, :duration) + metric_source "sidekiq" + gauge "perform", context.slice(:worker, :queue, :duration) end end end @@ -60,7 +60,7 @@ def call(worker, msg, queue, _redis) } if Honeybadger.config.load_plugin_insights_events?(:sidekiq) - Honeybadger.event('enqueue.sidekiq', context) + Honeybadger.event("enqueue.sidekiq", context) end yield @@ -73,57 +73,56 @@ def call(worker, msg, queue, _redis) requirement { defined?(::Sidekiq) } execution do - if Honeybadger.config[:'exceptions.enabled'] + if Honeybadger.config[:"exceptions.enabled"] ::Sidekiq.configure_server do |sidekiq| sidekiq.server_middleware do |chain| chain.prepend Middleware end end - if defined?(::Sidekiq::VERSION) && ::Sidekiq::VERSION > '3' + if defined?(::Sidekiq::VERSION) && ::Sidekiq::VERSION > "3" ::Sidekiq.configure_server do |sidekiq| - - sidekiq_default_configuration = (::Sidekiq::VERSION > '7') ? + sidekiq_default_configuration = (::Sidekiq::VERSION > "7") ? ::Sidekiq.default_configuration : Class.new sidekiq.error_handlers << lambda { |ex, sidekiq_params, sidekiq_config = sidekiq_default_configuration| params = sidekiq_params.dup if defined?(::Sidekiq::Config) - if params[:_config].is_a?(::Sidekiq::Config) # Sidekiq > 6 and < 7.1.5 - params[:_config] = params[:_config].instance_variable_get(:@options) + params[:_config] = if params[:_config].is_a?(::Sidekiq::Config) # Sidekiq > 6 and < 7.1.5 + params[:_config].instance_variable_get(:@options) else # Sidekiq >= 7.1.5 - params[:_config] = sidekiq_config.instance_variable_get(:@options) + sidekiq_config.instance_variable_get(:@options) end end job = params[:job] || params - job_retry = job['retry'.freeze] + job_retry = job["retry".freeze] - if (threshold = config[:'sidekiq.attempt_threshold'].to_i) > 0 && job_retry + if (threshold = config[:"sidekiq.attempt_threshold"].to_i) > 0 && job_retry # We calculate the job attempts to determine the need to # skip. Sidekiq's first job execution will have nil for the # 'retry_count' job key. The first retry will have 0 set for # the 'retry_count' key, incrementing on each execution # afterwards. - retry_count = job['retry_count'.freeze] + retry_count = job["retry_count".freeze] attempt = retry_count ? retry_count + 1 : 0 - max_retries = (::Sidekiq::VERSION > '7') ? + max_retries = (::Sidekiq::VERSION > "7") ? ::Sidekiq.default_configuration[:max_retries] : sidekiq.options[:max_retries] # Ensure we account for modified max_retries setting default_max_retry_attempts = defined?(::Sidekiq::JobRetry::DEFAULT_MAX_RETRY_ATTEMPTS) ? ::Sidekiq::JobRetry::DEFAULT_MAX_RETRY_ATTEMPTS : 25 - retry_limit = job_retry == true ? (max_retries || default_max_retry_attempts) : job_retry.to_i + retry_limit = (job_retry == true) ? (max_retries || default_max_retry_attempts) : job_retry.to_i limit = [retry_limit, threshold].min return if attempt < limit end - opts = { parameters: params } - if config[:'sidekiq.use_component'] - opts[:component] = job['wrapped'.freeze] || job['class'.freeze] - opts[:action] = 'perform' if opts[:component] + opts = {parameters: params} + if config[:"sidekiq.use_component"] + opts[:component] = job["wrapped".freeze] || job["class".freeze] + opts[:action] = "perform" if opts[:component] end Honeybadger.notify(ex, opts) @@ -136,7 +135,7 @@ def call(worker, msg, queue, _redis) require "sidekiq" require "sidekiq/api" - if Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new('6.5') + if Gem::Version.new(::Sidekiq::VERSION) >= Gem::Version.new("6.5") require "sidekiq/component" class SidekiqClusterCollectionChecker @@ -212,13 +211,13 @@ def collect? stats = collect_sidekiq_stats.call if Honeybadger.config.load_plugin_insights_events?(:sidekiq) - Honeybadger.event('stats.sidekiq', stats.except('stats').merge(stats['stats'])) + Honeybadger.event("stats.sidekiq", stats.except("stats").merge(stats["stats"])) end if Honeybadger.config.load_plugin_insights_metrics?(:sidekiq) - metric_source 'sidekiq' + metric_source "sidekiq" - stats['stats'].each do |name, value| + stats["stats"].each do |name, value| gauge name, value: value end @@ -228,8 +227,8 @@ def collect? end end - gauge 'capacity', value: stats[:capacity] if stats[:capacity] - gauge 'utilization', value: stats[:utilization] if stats[:utilization] + gauge "capacity", value: stats[:capacity] if stats[:capacity] + gauge "utilization", value: stats[:utilization] if stats[:utilization] end end end diff --git a/lib/honeybadger/plugins/solid_queue.rb b/lib/honeybadger/plugins/solid_queue.rb index 84407984b..edaa7d52a 100644 --- a/lib/honeybadger/plugins/solid_queue.rb +++ b/lib/honeybadger/plugins/solid_queue.rb @@ -19,7 +19,7 @@ module SolidQueue data[:queues] = {} ::SolidQueue::Queue.all.each do |queue| - data[:queues][queue.name] = { depth: queue.size } + data[:queues][queue.name] = {depth: queue.size} end data @@ -30,11 +30,11 @@ module SolidQueue if config.cluster_collection?(:solid_queue) if Honeybadger.config.load_plugin_insights_events?(:solid_queue) - Honeybadger.event('stats.solid_queue', stats.except(:stats).merge(stats[:stats])) + Honeybadger.event("stats.solid_queue", stats.except(:stats).merge(stats[:stats])) end if Honeybadger.config.load_plugin_insights_metrics?(:solid_queue) - metric_source 'solid_queue' + metric_source "solid_queue" stats[:stats].each do |stat_name, value| gauge stat_name, value: value end diff --git a/lib/honeybadger/plugins/sucker_punch.rb b/lib/honeybadger/plugins/sucker_punch.rb index d67f8fca6..a7afe64f1 100644 --- a/lib/honeybadger/plugins/sucker_punch.rb +++ b/lib/honeybadger/plugins/sucker_punch.rb @@ -1,17 +1,17 @@ -require 'honeybadger/plugin' -require 'honeybadger/ruby' +require "honeybadger/plugin" +require "honeybadger/ruby" module Honeybadger Plugin.register do requirement { defined?(::SuckerPunch) } execution do - return unless Honeybadger.config[:'exceptions.enabled'] + return unless Honeybadger.config[:"exceptions.enabled"] if SuckerPunch.respond_to?(:exception_handler=) # >= v2 - SuckerPunch.exception_handler = ->(ex, klass, args) { Honeybadger.notify(ex, { :component => klass, :parameters => args }) } + SuckerPunch.exception_handler = ->(ex, klass, args) { Honeybadger.notify(ex, {component: klass, parameters: args}) } else SuckerPunch.exception_handler do |ex, klass, args| - Honeybadger.notify(ex, { :component => klass, :parameters => args }) + Honeybadger.notify(ex, {component: klass, parameters: args}) end end end diff --git a/lib/honeybadger/plugins/system.rb b/lib/honeybadger/plugins/system.rb index 2202b0aba..380ed76d7 100644 --- a/lib/honeybadger/plugins/system.rb +++ b/lib/honeybadger/plugins/system.rb @@ -1,5 +1,5 @@ -require 'honeybadger/util/stats' -require 'honeybadger/plugin' +require "honeybadger/util/stats" +require "honeybadger/plugin" module Honeybadger module Plugins @@ -8,7 +8,7 @@ module System requirement { Util::Stats::HAS_MEM || Util::Stats::HAS_LOAD } collect do - Honeybadger.event('report.system', Util::Stats.all) + Honeybadger.event("report.system", Util::Stats.all) end end end diff --git a/lib/honeybadger/plugins/thor.rb b/lib/honeybadger/plugins/thor.rb index b8247e370..18a789ddc 100644 --- a/lib/honeybadger/plugins/thor.rb +++ b/lib/honeybadger/plugins/thor.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/ruby' +require "honeybadger/plugin" +require "honeybadger/ruby" module Honeybadger module Plugins @@ -25,7 +25,7 @@ def invoke_command_with_honeybadger(*args) requirement { defined?(::Thor.no_commands) } execution do - return unless Honeybadger.config[:'exceptions.enabled'] + return unless Honeybadger.config[:"exceptions.enabled"] ::Thor.send(:include, Thor) end end diff --git a/lib/honeybadger/plugins/warden.rb b/lib/honeybadger/plugins/warden.rb index 7aa8c15b4..e1682d594 100644 --- a/lib/honeybadger/plugins/warden.rb +++ b/lib/honeybadger/plugins/warden.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/ruby' +require "honeybadger/plugin" +require "honeybadger/ruby" module Honeybadger Plugin.register do @@ -9,8 +9,8 @@ module Honeybadger ::Warden::Manager.after_set_user do |user, auth, opts| if user.respond_to?(:id) ::Honeybadger.context({ - :user_scope => opts[:scope].to_s, - :user_id => user.id.to_s + user_scope: opts[:scope].to_s, + user_id: user.id.to_s }) end end diff --git a/lib/honeybadger/rack/error_notifier.rb b/lib/honeybadger/rack/error_notifier.rb index eed127591..91000202b 100644 --- a/lib/honeybadger/rack/error_notifier.rb +++ b/lib/honeybadger/rack/error_notifier.rb @@ -1,7 +1,7 @@ -require 'forwardable' -require 'rack/request' +require "forwardable" +require "rack/request" -require 'honeybadger/ruby' +require "honeybadger/ruby" module Honeybadger module Rack @@ -23,22 +23,22 @@ class ErrorNotifier def initialize(app, agent = nil) @app = app - @agent = agent.kind_of?(Agent) && agent + @agent = agent.is_a?(Agent) && agent end def call(env) agent.with_rack_env(env) do begin - env['honeybadger.config'] = config + env["honeybadger.config"] = config response = @app.call(env) rescue Exception => raised - env['honeybadger.error_id'] = notify_honeybadger(raised, env) + env["honeybadger.error_id"] = notify_honeybadger(raised, env) raise end framework_exception = framework_exception(env) if framework_exception - env['honeybadger.error_id'] = notify_honeybadger(framework_exception, env) + env["honeybadger.error_id"] = notify_honeybadger(framework_exception, env) end response @@ -57,15 +57,15 @@ def agent end def ignored_user_agent?(env) - true if config[:'exceptions.ignored_user_agents']. - flatten. - any? { |ua| ua === env['HTTP_USER_AGENT'] } + true if config[:"exceptions.ignored_user_agents"] + .flatten + .any? { |ua| ua === env["HTTP_USER_AGENT"] } end def notify_honeybadger(exception, env) return if ignored_user_agent?(env) - if config[:'breadcrumbs.enabled'] + if config[:"breadcrumbs.enabled"] # Drop the last breadcrumb only if the message contains the error class name agent.breadcrumbs.drop_previous_breadcrumb_if do |bc| bc.category == "log" && bc.message.include?(exception.class.to_s) @@ -84,8 +84,8 @@ def notify_honeybadger(exception, env) end def framework_exception(env) - env['action_dispatch.exception'] || env['rack.exception'] || - env['sinatra.error'] || env['honeybadger.exception'] + env["action_dispatch.exception"] || env["rack.exception"] || + env["sinatra.error"] || env["honeybadger.exception"] end end end diff --git a/lib/honeybadger/rack/user_feedback.rb b/lib/honeybadger/rack/user_feedback.rb index edbee7920..f113efd11 100644 --- a/lib/honeybadger/rack/user_feedback.rb +++ b/lib/honeybadger/rack/user_feedback.rb @@ -1,13 +1,13 @@ -require 'erb' -require 'uri' -require 'forwardable' +require "erb" +require "uri" +require "forwardable" begin - require 'i18n' + require "i18n" rescue LoadError module Honeybadger module I18n - def self.t(key, options={}) + def self.t(key, options = {}) options[:default] end end @@ -23,18 +23,18 @@ class UserFeedback def initialize(app, agent = nil) @app = app - @agent = agent.kind_of?(Agent) && agent + @agent = agent.is_a?(Agent) && agent end def call(env) status, headers, body = @app.call(env) - if env['honeybadger.error_id'] && form = render_form(env['honeybadger.error_id']) + if env["honeybadger.error_id"] && form = render_form(env["honeybadger.error_id"]) new_body = [] body.each do |chunk| new_body << chunk.gsub("", form) end body.close if body.respond_to?(:close) - headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s + headers["Content-Length"] = new_body.reduce(0) { |a, e| a + e.bytesize }.to_s body = new_body end [status, headers, body] @@ -43,7 +43,7 @@ def call(env) # @private # @todo Make this method and others actually private. def action - URI.parse("#{config.connection_protocol}://#{config[:'connection.host']}:#{config.connection_port}/v1/feedback/").to_s + URI.parse("#{config.connection_protocol}://#{config[:"connection.host"]}:#{config.connection_port}/v1/feedback/").to_s rescue URI::InvalidURIError nil end @@ -56,7 +56,7 @@ def render_form(error_id, action = action()) # @private def custom_template_file - @custom_template_file ||= File.join(config[:root], 'lib', 'honeybadger', 'templates', 'feedback_form.erb') + @custom_template_file ||= File.join(config[:root], "lib", "honeybadger", "templates", "feedback_form.erb") end # @private @@ -69,7 +69,7 @@ def template_file if custom_template_file? custom_template_file else - File.expand_path('../../templates/feedback_form.erb', __FILE__) + File.expand_path("../../templates/feedback_form.erb", __FILE__) end end @@ -81,7 +81,6 @@ def template_file def agent @agent || Honeybadger::Agent.instance end - end end end diff --git a/lib/honeybadger/rack/user_informer.rb b/lib/honeybadger/rack/user_informer.rb index 3720a0efb..51942af9b 100644 --- a/lib/honeybadger/rack/user_informer.rb +++ b/lib/honeybadger/rack/user_informer.rb @@ -1,4 +1,4 @@ -require 'forwardable' +require "forwardable" module Honeybadger module Rack @@ -9,23 +9,23 @@ class UserInformer def initialize(app, agent = nil) @app = app - @agent = agent.kind_of?(Agent) && agent + @agent = agent.is_a?(Agent) && agent end def replacement(with) - config[:'user_informer.info'].gsub(/\{\{\s*error_id\s*\}\}/, with.to_s) + config[:"user_informer.info"].gsub(/\{\{\s*error_id\s*\}\}/, with.to_s) end def call(env) status, headers, body = @app.call(env) - if env['honeybadger.error_id'] + if env["honeybadger.error_id"] new_body = [] - replace = replacement(env['honeybadger.error_id']) + replace = replacement(env["honeybadger.error_id"]) body.each do |chunk| new_body << chunk.gsub("", replace) end body.close if body.respond_to?(:close) - headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s + headers["Content-Length"] = new_body.reduce(0) { |a, e| a + e.bytesize }.to_s body = new_body end [status, headers, body] diff --git a/lib/honeybadger/registry.rb b/lib/honeybadger/registry.rb index 77322258b..2b472690e 100644 --- a/lib/honeybadger/registry.rb +++ b/lib/honeybadger/registry.rb @@ -2,7 +2,7 @@ module Honeybadger class Registry def initialize @mutex = Mutex.new - @metrics = Hash.new + @metrics = {} end def register(metric) @@ -19,7 +19,7 @@ def get(metric_type, name, attributes) def flush @mutex.synchronize do - @metrics = Hash.new + @metrics = {} end end diff --git a/lib/honeybadger/registry_execution.rb b/lib/honeybadger/registry_execution.rb index 93c8688d6..a349ba992 100644 --- a/lib/honeybadger/registry_execution.rb +++ b/lib/honeybadger/registry_execution.rb @@ -4,7 +4,7 @@ def initialize(registry, config, options) @registry = registry @config = config @options = options - @interval = config[:'insights.registry_flush_interval'] || options.fetch(:interval, 60) + @interval = config[:"insights.registry_flush_interval"] || options.fetch(:interval, 60) @end_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) + @interval end diff --git a/lib/honeybadger/ruby.rb b/lib/honeybadger/ruby.rb index df006c24c..87e0b8b04 100644 --- a/lib/honeybadger/ruby.rb +++ b/lib/honeybadger/ruby.rb @@ -1,2 +1,2 @@ -require 'honeybadger/const' -require 'honeybadger/singleton' +require "honeybadger/const" +require "honeybadger/singleton" diff --git a/lib/honeybadger/singleton.rb b/lib/honeybadger/singleton.rb index 0b8f0ee23..4df73f782 100644 --- a/lib/honeybadger/singleton.rb +++ b/lib/honeybadger/singleton.rb @@ -1,5 +1,5 @@ -require 'forwardable' -require 'honeybadger/agent' +require "forwardable" +require "honeybadger/agent" # Honeybadger's public API is made up of two parts: the {Honeybadger} singleton # module, and the {Agent} class. The singleton module delegates its methods to @@ -25,42 +25,42 @@ module Honeybadger # @!method $2(...) # Forwards to {$1}. # @see Agent#$2 - def_delegator :'Honeybadger::Agent.instance', :check_in - def_delegator :'Honeybadger::Agent.instance', :context - def_delegator :'Honeybadger::Agent.instance', :configure - def_delegator :'Honeybadger::Agent.instance', :get_context - def_delegator :'Honeybadger::Agent.instance', :flush - def_delegator :'Honeybadger::Agent.instance', :stop - def_delegator :'Honeybadger::Agent.instance', :exception_filter - def_delegator :'Honeybadger::Agent.instance', :exception_fingerprint - def_delegator :'Honeybadger::Agent.instance', :backtrace_filter - def_delegator :'Honeybadger::Agent.instance', :add_breadcrumb - def_delegator :'Honeybadger::Agent.instance', :breadcrumbs - def_delegator :'Honeybadger::Agent.instance', :clear! - def_delegator :'Honeybadger::Agent.instance', :track_deployment - def_delegator :'Honeybadger::Agent.instance', :event - def_delegator :'Honeybadger::Agent.instance', :collect - def_delegator :'Honeybadger::Agent.instance', :registry - def_delegator :'Honeybadger::Agent.instance', :instrumentation - def_delegator :'Honeybadger::Agent.instance', :time - def_delegator :'Honeybadger::Agent.instance', :histogram - def_delegator :'Honeybadger::Agent.instance', :gauge - def_delegator :'Honeybadger::Agent.instance', :increment_counter - def_delegator :'Honeybadger::Agent.instance', :decrement_counter + def_delegator :"Honeybadger::Agent.instance", :check_in + def_delegator :"Honeybadger::Agent.instance", :context + def_delegator :"Honeybadger::Agent.instance", :configure + def_delegator :"Honeybadger::Agent.instance", :get_context + def_delegator :"Honeybadger::Agent.instance", :flush + def_delegator :"Honeybadger::Agent.instance", :stop + def_delegator :"Honeybadger::Agent.instance", :exception_filter + def_delegator :"Honeybadger::Agent.instance", :exception_fingerprint + def_delegator :"Honeybadger::Agent.instance", :backtrace_filter + def_delegator :"Honeybadger::Agent.instance", :add_breadcrumb + def_delegator :"Honeybadger::Agent.instance", :breadcrumbs + def_delegator :"Honeybadger::Agent.instance", :clear! + def_delegator :"Honeybadger::Agent.instance", :track_deployment + def_delegator :"Honeybadger::Agent.instance", :event + def_delegator :"Honeybadger::Agent.instance", :collect + def_delegator :"Honeybadger::Agent.instance", :registry + def_delegator :"Honeybadger::Agent.instance", :instrumentation + def_delegator :"Honeybadger::Agent.instance", :time + def_delegator :"Honeybadger::Agent.instance", :histogram + def_delegator :"Honeybadger::Agent.instance", :gauge + def_delegator :"Honeybadger::Agent.instance", :increment_counter + def_delegator :"Honeybadger::Agent.instance", :decrement_counter # @!macro [attach] def_delegator # @!method $2(...) # @api private # Forwards to {$1}. # @see Agent#$2 - def_delegator :'Honeybadger::Agent.instance', :config - def_delegator :'Honeybadger::Agent.instance', :init! - def_delegator :'Honeybadger::Agent.instance', :with_rack_env + def_delegator :"Honeybadger::Agent.instance", :config + def_delegator :"Honeybadger::Agent.instance", :init! + def_delegator :"Honeybadger::Agent.instance", :with_rack_env # @!method notify(...) # Forwards to {Agent.instance}. # @see Agent#notify - def notify(exception_or_opts=nil, opts = {}, **kwargs) + def notify(exception_or_opts = nil, opts = {}, **kwargs) # Note this is defined directly (instead of via forwardable) so that # generated stack traces work as expected. Agent.instance.notify(exception_or_opts, opts, **kwargs) @@ -68,45 +68,46 @@ def notify(exception_or_opts=nil, opts = {}, **kwargs) # @api private def load_plugins! - Dir[File.expand_path('../plugins/*.rb', __FILE__)].each do |plugin| + Dir[File.expand_path("../plugins/*.rb", __FILE__)].each do |plugin| require plugin end - Plugin.load!(self.config) + Plugin.load!(config) end # @api private def install_at_exit_callback at_exit do - if $! && !ignored_exception?($!) && Honeybadger.config[:'exceptions.notify_at_exit'] - Honeybadger.notify($!, component: 'at_exit', sync: true) + if $! && !ignored_exception?($!) && Honeybadger.config[:"exceptions.notify_at_exit"] + Honeybadger.notify($!, component: "at_exit", sync: true) end - Honeybadger.stop if Honeybadger.config[:'send_data_at_exit'] + Honeybadger.stop if Honeybadger.config[:send_data_at_exit] end end # @deprecated def start(config = {}) - raise NoMethodError, <<-WARNING -`Honeybadger.start` is no longer necessary and has been removed. - - Use `Honeybadger.configure` to explicitly configure the agent from Ruby moving forward: - - Honeybadger.configure do |config| - config.api_key = 'project api key' - config.exceptions.ignore += [CustomError] - end -WARNING + raise NoMethodError, <<~WARNING + `Honeybadger.start` is no longer necessary and has been removed. + + Use `Honeybadger.configure` to explicitly configure the agent from Ruby moving forward: + + Honeybadger.configure do |config| + config.api_key = 'project api key' + config.exceptions.ignore += [CustomError] + end + WARNING end private + # @api private def ignored_exception?(exception) exception.is_a?(SystemExit) || - ( exception.is_a?(SignalException) && - ( (exception.respond_to?(:signm) && exception.signm == "SIGTERM") || + (exception.is_a?(SignalException) && + ((exception.respond_to?(:signm) && exception.signm == "SIGTERM") || # jruby has a missing #signm implementation - ["TERM", "SIGTERM"].include?(exception.to_s) ) - ) + ["TERM", "SIGTERM"].include?(exception.to_s)) + ) end end diff --git a/lib/honeybadger/tasks.rb b/lib/honeybadger/tasks.rb index c45c42147..a83a30aa6 100644 --- a/lib/honeybadger/tasks.rb +++ b/lib/honeybadger/tasks.rb @@ -5,18 +5,18 @@ def warn_task_moved(old_name, new_cmd = "honeybadger help #{old_name}") desc "Verify your gem installation by sending a test exception to the honeybadger service" task :test do - warn_task_moved('test') + warn_task_moved("test") end desc "Notify Honeybadger of a new deploy." task :deploy do - warn_task_moved('deploy') + warn_task_moved("deploy") end namespace :heroku do desc "Install Heroku deploy notifications addon" task :add_deploy_notification do - warn_task_moved('heroku:add_deploy_notification', 'honeybadger heroku help install_deploy_notification') + warn_task_moved("heroku:add_deploy_notification", "honeybadger heroku help install_deploy_notification") end end end diff --git a/lib/honeybadger/timer.rb b/lib/honeybadger/timer.rb index d8b956b8d..a4502010f 100644 --- a/lib/honeybadger/timer.rb +++ b/lib/honeybadger/timer.rb @@ -1,4 +1,4 @@ -require 'honeybadger/gauge' +require "honeybadger/gauge" module Honeybadger class Timer < Gauge diff --git a/lib/honeybadger/util/http.rb b/lib/honeybadger/util/http.rb index d20304157..a3a0d340b 100644 --- a/lib/honeybadger/util/http.rb +++ b/lib/honeybadger/util/http.rb @@ -1,11 +1,11 @@ -require 'forwardable' -require 'net/http' -require 'json' -require 'zlib' -require 'openssl' +require "forwardable" +require "net/http" +require "json" +require "zlib" +require "openssl" -require 'honeybadger/version' -require 'honeybadger/logging' +require "honeybadger/version" +require "honeybadger/logging" module Honeybadger module Util @@ -15,23 +15,23 @@ class HTTP include Honeybadger::Logging::Helper HEADERS = { - 'Content-type'.freeze => 'application/json'.freeze, - 'Content-Encoding'.freeze => 'deflate'.freeze, - 'Accept'.freeze => 'text/json, application/json'.freeze, - 'User-Agent'.freeze => "HB-Ruby #{VERSION}; #{RUBY_VERSION}; #{RUBY_PLATFORM}".freeze + "Content-type".freeze => "application/json".freeze, + "Content-Encoding".freeze => "deflate".freeze, + "Accept".freeze => "text/json, application/json".freeze, + "User-Agent".freeze => "HB-Ruby #{VERSION}; #{RUBY_VERSION}; #{RUBY_PLATFORM}".freeze }.freeze ERRORS = [Timeout::Error, - Errno::EINVAL, - Errno::ECONNRESET, - Errno::ECONNREFUSED, - Errno::ENETUNREACH, - EOFError, - Net::HTTPBadResponse, - Net::HTTPHeaderSyntaxError, - Net::ProtocolError, - OpenSSL::SSL::SSLError, - SocketError].freeze + Errno::EINVAL, + Errno::ECONNRESET, + Errno::ECONNREFUSED, + Errno::ENETUNREACH, + EOFError, + Net::HTTPBadResponse, + Net::HTTPHeaderSyntaxError, + Net::ProtocolError, + OpenSSL::SSL::SSLError, + SocketError].freeze def initialize(config) @config = config @@ -66,19 +66,19 @@ def http_connection def http_headers(headers = nil) {}.tap do |hash| hash.merge!(HEADERS) - hash.merge!({'X-API-Key' => config[:api_key].to_s}) + hash.merge!({"X-API-Key" => config[:api_key].to_s}) hash.merge!(headers) if headers end end def setup_http_connection - http_class = Net::HTTP::Proxy(config[:'connection.proxy_host'], config[:'connection.proxy_port'], config[:'connection.proxy_user'], config[:'connection.proxy_pass']) - http = http_class.new(config[:'connection.host'], config.connection_port) + http_class = Net::HTTP::Proxy(config[:"connection.proxy_host"], config[:"connection.proxy_port"], config[:"connection.proxy_user"], config[:"connection.proxy_pass"]) + http = http_class.new(config[:"connection.host"], config.connection_port) - http.read_timeout = config[:'connection.http_read_timeout'] - http.open_timeout = config[:'connection.http_open_timeout'] + http.read_timeout = config[:"connection.http_read_timeout"] + http.open_timeout = config[:"connection.http_open_timeout"] - if config[:'connection.secure'] + if config[:"connection.secure"] http.use_ssl = true http.ca_file = config.ca_bundle_path diff --git a/lib/honeybadger/util/request_hash.rb b/lib/honeybadger/util/request_hash.rb index 7f638a436..8cc194995 100644 --- a/lib/honeybadger/util/request_hash.rb +++ b/lib/honeybadger/util/request_hash.rb @@ -1,13 +1,13 @@ -require 'set' +require "set" module Honeybadger module Util # Constructs a request hash from a Rack::Request matching the /v1/notices # API specification. module RequestHash - HTTP_HEADER_PREFIX = 'HTTP_'.freeze + HTTP_HEADER_PREFIX = "HTTP_".freeze - CGI_WHITELIST = %w( + CGI_WHITELIST = %w[ AUTH_TYPE CONTENT_LENGTH CONTENT_TYPE @@ -22,7 +22,7 @@ module RequestHash SERVER_PORT SERVER_PROTOCOL SERVER_SOFTWARE - ).freeze + ].freeze def self.from_env(env) return {} unless defined?(::Rack::Request) @@ -32,8 +32,8 @@ def self.from_env(env) hash[:url] = extract_url(request) hash[:params] = extract_params(request) - hash[:component] = hash[:params]['controller'] - hash[:action] = hash[:params]['action'] + hash[:component] = hash[:params]["controller"] + hash[:action] = hash[:params]["action"] hash[:session] = extract_session(request) hash[:cgi_data] = extract_cgi_data(request) @@ -41,15 +41,15 @@ def self.from_env(env) end def self.extract_url(request) - request.env['honeybadger.request.url'] || request.url + request.env["honeybadger.request.url"] || request.url rescue => e "Failed to access URL -- #{e}" end def self.extract_params(request) - (request.env['action_dispatch.request.parameters'] || request.params).to_hash || {} + (request.env["action_dispatch.request.parameters"] || request.params).to_hash || {} rescue => e - { error: "Failed to access params -- #{e}" } + {error: "Failed to access params -- #{e}"} end def self.extract_session(request) @@ -58,11 +58,11 @@ def self.extract_session(request) # Rails raises ArgumentError when `config.secret_token` is missing, and # ActionDispatch::Session::SessionRestoreError when the session can't be # restored. - { error: "Failed to access session data -- #{e}" } + {error: "Failed to access session data -- #{e}"} end def self.extract_cgi_data(request) - request.env.each_with_object({}) do |(k,v), env| + request.env.each_with_object({}) do |(k, v), env| next unless k.is_a?(String) next unless k.start_with?(HTTP_HEADER_PREFIX) || CGI_WHITELIST.include?(k) env[k] = v diff --git a/lib/honeybadger/util/request_payload.rb b/lib/honeybadger/util/request_payload.rb index aa05e7992..1046f7ac4 100644 --- a/lib/honeybadger/util/request_payload.rb +++ b/lib/honeybadger/util/request_payload.rb @@ -1,4 +1,4 @@ -require 'honeybadger/util/sanitizer' +require "honeybadger/util/sanitizer" module Honeybadger module Util @@ -18,7 +18,7 @@ module RequestPayload KEYS = DEFAULTS.keys.freeze # The cgi_data key where the raw Cookie header is stored. - HTTP_COOKIE_KEY = 'HTTP_COOKIE'.freeze + HTTP_COOKIE_KEY = "HTTP_COOKIE".freeze def self.build(opts = {}) sanitizer = opts.fetch(:sanitizer) { Sanitizer.new } diff --git a/lib/honeybadger/util/revision.rb b/lib/honeybadger/util/revision.rb index 7d0c45175..722681e77 100644 --- a/lib/honeybadger/util/revision.rb +++ b/lib/honeybadger/util/revision.rb @@ -20,18 +20,26 @@ def detect(root = Dir.pwd) # # See https://devcenter.heroku.com/articles/dyno-metadata def from_heroku - ENV['HEROKU_SLUG_COMMIT'] + ENV["HEROKU_SLUG_COMMIT"] end def from_capistrano(root) - file = File.join(root, 'REVISION') + file = File.join(root, "REVISION") return nil unless File.file?(file) - File.read(file) rescue nil + begin + File.read(file) + rescue + nil + end end def from_git - return nil unless File.directory?('.git') - `git rev-parse HEAD 2> #{File::NULL}` rescue nil + return nil unless File.directory?(".git") + begin + `git rev-parse HEAD 2> #{File::NULL}` + rescue + nil + end end end end diff --git a/lib/honeybadger/util/sanitizer.rb b/lib/honeybadger/util/sanitizer.rb index 8e8e7ba2f..b572bfed2 100644 --- a/lib/honeybadger/util/sanitizer.rb +++ b/lib/honeybadger/util/sanitizer.rb @@ -1,6 +1,6 @@ -require 'set' +require "set" -require 'honeybadger/conversions' +require "honeybadger/conversions" module Honeybadger module Util @@ -8,17 +8,17 @@ module Util # are based on Rails' HTTP parameter filter. class Sanitizer COOKIE_PAIRS = /[;,]\s?/ - COOKIE_SEP = '='.freeze - COOKIE_PAIR_SEP = '; '.freeze + COOKIE_SEP = "=".freeze + COOKIE_PAIR_SEP = "; ".freeze - ENCODE_OPTS = { invalid: :replace, undef: :replace, replace: '?'.freeze }.freeze + ENCODE_OPTS = {invalid: :replace, undef: :replace, replace: "?".freeze}.freeze - BASIC_OBJECT = '#'.freeze - DEPTH = '[DEPTH]'.freeze - FILTERED = '[FILTERED]'.freeze - RAISED = '[RAISED]'.freeze - RECURSION = '[RECURSION]'.freeze - TRUNCATED = '[TRUNCATED]'.freeze + BASIC_OBJECT = "#".freeze + DEPTH = "[DEPTH]".freeze + FILTERED = "[FILTERED]".freeze + RAISED = "[RAISED]".freeze + RECURSION = "[RECURSION]".freeze + TRUNCATED = "[TRUNCATED]".freeze IMMUTABLE = [NilClass, FalseClass, TrueClass, Symbol, Numeric, Method].freeze @@ -51,8 +51,8 @@ def initialize(max_depth: 20, filters: []) @deep_regexps, @regexps = @regexps.partition { |r| r.to_s.include?('\\.'.freeze) } deep_strings, @strings = strings.partition { |s| s.include?('\\.'.freeze) } - @regexps << Regexp.new(strings.join('|'.freeze), true) unless strings.empty? - @deep_regexps << Regexp.new(deep_strings.join('|'.freeze), true) unless deep_strings.empty? + @regexps << Regexp.new(strings.join("|".freeze), true) unless strings.empty? + @deep_regexps << Regexp.new(deep_strings.join("|".freeze), true) unless deep_strings.empty? end def sanitize(data, depth = 0, stack = nil, parents = []) @@ -74,12 +74,12 @@ def sanitize(data, depth = 0, stack = nil, parents = []) hash.each_pair do |key, value| parents.push(key) if deep_regexps - key = key.kind_of?(Symbol) ? key : sanitize(key, depth+1, stack, parents) + key = key.is_a?(Symbol) ? key : sanitize(key, depth + 1, stack, parents) if filter_key?(key, parents) new_hash[key] = FILTERED else - value = sanitize(value, depth+1, stack, parents) + value = sanitize(value, depth + 1, stack, parents) if blocks.any? && !recursive?(value) key = key.dup if can_dup?(key) @@ -98,13 +98,13 @@ def sanitize(data, depth = 0, stack = nil, parents = []) return DEPTH if depth >= max_depth data.to_a.map do |value| - sanitize(value, depth+1, stack, parents) + sanitize(value, depth + 1, stack, parents) end when Numeric, TrueClass, FalseClass, NilClass data when String sanitize_string(data) - when -> (d) { d.respond_to?(:to_honeybadger) } + when ->(d) { d.respond_to?(:to_honeybadger) } return DEPTH if depth >= max_depth begin @@ -113,7 +113,7 @@ def sanitize(data, depth = 0, stack = nil, parents = []) return RAISED end - sanitize(data, depth+1, stack, parents) + sanitize(data, depth + 1, stack, parents) else # all other objects klass = data.class @@ -156,7 +156,7 @@ def filter_url(url) filtered_url end - private + private attr_reader :max_depth, :regexps, :deep_regexps, :blocks @@ -180,7 +180,7 @@ def sanitize_string(string) def valid_encoding?(string) string.valid_encoding? && ( VALID_ENCODINGS.include?(string.encoding) || - VALID_ENCODINGS.include?(Encoding.compatible?(''.freeze, string)) + VALID_ENCODINGS.include?(Encoding.compatible?("".freeze, string)) ) end @@ -202,7 +202,7 @@ def basic_object?(object) end def can_dup?(obj) - !IMMUTABLE.any? {|k| obj.kind_of?(k) } + !IMMUTABLE.any? { |k| obj.is_a?(k) } end def inspected?(string) diff --git a/lib/honeybadger/util/stats.rb b/lib/honeybadger/util/stats.rb index 86a21cdb6..71e3a1466 100644 --- a/lib/honeybadger/util/stats.rb +++ b/lib/honeybadger/util/stats.rb @@ -6,14 +6,17 @@ class Stats class << self def all - { :mem => memory, :load => load } + {mem: memory, load: load} end # From https://github.com/bloopletech/webstats/blob/master/server/data_providers/mem_info.rb def memory out = {} if HAS_MEM && (meminfo = run_meminfo) - out[:total], out[:free], out[:buffers], out[:cached] = meminfo[0..4].map { |l| l =~ /^.*?\: +(.*?) kB$/; ($1.to_i / 1024.0).to_f } + out[:total], out[:free], out[:buffers], out[:cached] = meminfo[0..4].map { |l| + l =~ /^.*?: +(.*?) kB$/ + ($1.to_i / 1024.0).to_f + } out[:free_total] = out[:free] + out[:buffers] + out[:cached] end out @@ -23,7 +26,7 @@ def memory def load out = {} if HAS_LOAD && (loadavg = run_loadavg) - out[:one], out[:five], out[:fifteen] = loadavg.split(' ', 4).map(&:to_f) + out[:one], out[:five], out[:fifteen] = loadavg.split(" ", 4).map(&:to_f) end out end diff --git a/lib/honeybadger/version.rb b/lib/honeybadger/version.rb index a0b0e6bb3..63f7409a3 100644 --- a/lib/honeybadger/version.rb +++ b/lib/honeybadger/version.rb @@ -1,4 +1,4 @@ module Honeybadger # The current String Honeybadger version. - VERSION = '5.26.2'.freeze + VERSION = "5.26.2".freeze end diff --git a/lib/honeybadger/worker.rb b/lib/honeybadger/worker.rb index e0b450cc7..c0d9f8d37 100644 --- a/lib/honeybadger/worker.rb +++ b/lib/honeybadger/worker.rb @@ -1,7 +1,7 @@ -require 'forwardable' -require 'net/http' +require "forwardable" +require "net/http" -require 'honeybadger/logging' +require "honeybadger/logging" module Honeybadger # A concurrent queue to notify the backend. @@ -38,7 +38,7 @@ def push(msg) return false unless start if queue.size >= config.max_queue_size - warn { sprintf('Unable to report error; reached max queue size of %s. id=%s', queue.size, msg.id) } + warn { sprintf("Unable to report error; reached max queue size of %s. id=%s", queue.size, msg.id) } return false end @@ -50,7 +50,7 @@ def send_now(msg) end def shutdown(force = false) - d { 'shutting down worker' } + d { "shutting down worker" } mutex.synchronize do @shutdown = true @@ -60,11 +60,11 @@ def shutdown(force = false) return true unless thread&.alive? if throttled? - warn { sprintf('Unable to report %s error(s) to Honeybadger (currently throttled)', queue.size) } unless queue.empty? + warn { sprintf("Unable to report %s error(s) to Honeybadger (currently throttled)", queue.size) } unless queue.empty? return true end - info { sprintf('Waiting to report %s error(s) to Honeybadger', queue.size) } unless queue.empty? + info { sprintf("Waiting to report %s error(s) to Honeybadger", queue.size) } unless queue.empty? queue.push(SHUTDOWN) !!thread.join @@ -125,7 +125,7 @@ def throttled? end def kill! - d { 'killing worker thread' } + d { "killing worker thread" } if thread Thread.kill(thread) @@ -147,7 +147,7 @@ def suspend(interval) def run begin - d { 'worker started' } + d { "worker started" } loop do case msg = queue.pop when SHUTDOWN then break @@ -156,7 +156,7 @@ def run end end ensure - d { 'stopping worker' } + d { "stopping worker" } end rescue Exception => e error { @@ -171,13 +171,13 @@ def work(msg) send_now(msg) if shutdown? && throttled? - warn { sprintf('Unable to report %s error(s) to Honeybadger (currently throttled)', queue.size) } if queue.size > 1 + warn { sprintf("Unable to report %s error(s) to Honeybadger (currently throttled)", queue.size) } if queue.size > 1 kill! return end sleep(throttle_interval) - rescue StandardError => e + rescue => e error { msg = "Error in worker thread class=%s message=%s\n\t%s" sprintf(msg, e.class, e.message.dump, Array(e.backtrace).join("\n\t")) @@ -185,12 +185,12 @@ def work(msg) end def notify_backend(payload) - d { sprintf('worker notifying backend id=%s', payload.id) } + d { sprintf("worker notifying backend id=%s", payload.id) } backend.notify(:notices, payload) end def calc_throttle_interval - ((BASE_THROTTLE ** throttle) - 1).round(3) + ((BASE_THROTTLE**throttle) - 1).round(3) end def inc_throttle @@ -211,33 +211,33 @@ def dec_throttle end def handle_response(msg, response) - d { sprintf('worker response id=%s code=%s message=%s', msg.id, response.code, response.message.to_s.dump) } + d { sprintf("worker response id=%s code=%s message=%s", msg.id, response.code, response.message.to_s.dump) } case response.code when 429, 503 throttle = inc_throttle - warn { sprintf('Error report failed: project is sending too many errors. id=%s code=%s throttle=%s interval=%s', msg.id, response.code, throttle, throttle_interval) } + warn { sprintf("Error report failed: project is sending too many errors. id=%s code=%s throttle=%s interval=%s", msg.id, response.code, throttle, throttle_interval) } when 402 - warn { sprintf('Error report failed: payment is required. id=%s code=%s', msg.id, response.code) } + warn { sprintf("Error report failed: payment is required. id=%s code=%s", msg.id, response.code) } suspend(3600) when 403 - warn { sprintf('Error report failed: API key is invalid. id=%s code=%s', msg.id, response.code) } + warn { sprintf("Error report failed: API key is invalid. id=%s code=%s", msg.id, response.code) } suspend(3600) when 413 - warn { sprintf('Error report failed: Payload is too large. id=%s code=%s', msg.id, response.code) } + warn { sprintf("Error report failed: Payload is too large. id=%s code=%s", msg.id, response.code) } when 201 - host = config.get(:'connection.ui_host') + host = config.get(:"connection.ui_host") if throttle = dec_throttle - info { sprintf('Success ⚡ https://%s/notice/%s id=%s code=%s throttle=%s interval=%s', host, msg.id, msg.id, response.code, throttle, throttle_interval) } + info { sprintf("Success ⚡ https://%s/notice/%s id=%s code=%s throttle=%s interval=%s", host, msg.id, msg.id, response.code, throttle, throttle_interval) } else - info { sprintf('Success ⚡ https://%s/notice/%s id=%s code=%s', host, msg.id, msg.id, response.code) } + info { sprintf("Success ⚡ https://%s/notice/%s id=%s code=%s", host, msg.id, msg.id, response.code) } end when :stubbed - info { sprintf('Success ⚡ Development mode is enabled; this error will be reported if it occurs after you deploy your app. id=%s', msg.id) } + info { sprintf("Success ⚡ Development mode is enabled; this error will be reported if it occurs after you deploy your app. id=%s", msg.id) } when :error - warn { sprintf('Error report failed: an unknown error occurred. code=%s error=%s', response.code, response.message.to_s.dump) } + warn { sprintf("Error report failed: an unknown error occurred. code=%s error=%s", response.code, response.message.to_s.dump) } else - warn { sprintf('Error report failed: unknown response from server. code=%s', response.code) } + warn { sprintf("Error report failed: unknown response from server. code=%s", response.code) } end end diff --git a/lib/puma/plugin/honeybadger.rb b/lib/puma/plugin/honeybadger.rb index 564398962..1f68dec2d 100644 --- a/lib/puma/plugin/honeybadger.rb +++ b/lib/puma/plugin/honeybadger.rb @@ -1,10 +1,10 @@ -require 'honeybadger/instrumentation_helper' +require "honeybadger/instrumentation_helper" module Honeybadger class PumaPlugin include Honeybadger::InstrumentationHelper - STATS_KEYS = %i(pool_capacity max_threads requests_count backlog running).freeze + STATS_KEYS = %i[pool_capacity max_threads requests_count backlog running].freeze ::Puma::Plugin.create do def start(launcher) @@ -19,14 +19,18 @@ def start(launcher) end def record - metric_source 'puma' + metric_source "puma" - stats = ::Puma.stats rescue {} + stats = begin + ::Puma.stats + rescue + {} + end stats = stats.is_a?(Hash) ? stats : JSON.parse(stats, symbolize_names: true) if stats[:worker_status].is_a?(Array) stats[:worker_status].each do |worker_data| - context = { worker: worker_data[:index] } + context = {worker: worker_data[:index]} record_puma_stats(worker_data[:last_status], context) end else @@ -34,14 +38,14 @@ def record end end - def record_puma_stats(stats, context={}) + def record_puma_stats(stats, context = {}) if Honeybadger.config.load_plugin_insights_events?(:puma) - Honeybadger.event('stats.puma', context.merge(stats)) + Honeybadger.event("stats.puma", context.merge(stats)) end if Honeybadger.config.load_plugin_insights_metrics?(:puma) STATS_KEYS.each do |stat| - gauge stat, context, ->{ stats[stat] } if stats[stat] + gauge stat, context, -> { stats[stat] } if stats[stat] end end end diff --git a/spec/features/at_exit_spec.rb b/spec/features/at_exit_spec.rb index 005e7734d..14490f6bf 100644 --- a/spec/features/at_exit_spec.rb +++ b/spec/features/at_exit_spec.rb @@ -1,18 +1,18 @@ feature "Rescuing exceptions at exit" do - let(:crash_cmd) { "ruby #{ FIXTURES_PATH.join('ruby_crash.rb') }" } + let(:crash_cmd) { "ruby #{FIXTURES_PATH.join("ruby_crash.rb")}" } def custom_crash_cmd(crash_type) - "ruby #{ FIXTURES_PATH.join('ruby_custom_crash.rb') } #{ crash_type }" + "ruby #{FIXTURES_PATH.join("ruby_custom_crash.rb")} #{crash_type}" end before do - set_environment_variable('HONEYBADGER_API_KEY', 'asdf') - set_environment_variable('HONEYBADGER_LOGGING_LEVEL', 'DEBUG') + set_environment_variable("HONEYBADGER_API_KEY", "asdf") + set_environment_variable("HONEYBADGER_LOGGING_LEVEL", "DEBUG") end it "reports the exception to Honeybadger" do expect(run_command(crash_cmd)).not_to be_successfully_executed - assert_notification('error' => {'class' => 'RuntimeError', 'message' => 'RuntimeError: badgers!'}) + assert_notification("error" => {"class" => "RuntimeError", "message" => "RuntimeError: badgers!"}) end it "ignores SystemExit" do @@ -27,12 +27,12 @@ def custom_crash_cmd(crash_type) it "reports SignalException of type other than SIGTERM" do expect(run_command(custom_crash_cmd("hup"))).not_to be_successfully_executed - assert_notification('error' => {'class' => 'SignalException', 'message' => 'SignalException: SIGHUP'}) + assert_notification("error" => {"class" => "SignalException", "message" => "SignalException: SIGHUP"}) end context "at_exit is disabled" do before do - set_environment_variable('HONEYBADGER_EXCEPTIONS_NOTIFY_AT_EXIT', 'false') + set_environment_variable("HONEYBADGER_EXCEPTIONS_NOTIFY_AT_EXIT", "false") end it "doesn't report the exception to Honeybadger" do diff --git a/spec/features/capistrano_spec.rb b/spec/features/capistrano_spec.rb index b3e201a17..af96d55e2 100644 --- a/spec/features/capistrano_spec.rb +++ b/spec/features/capistrano_spec.rb @@ -1,10 +1,10 @@ feature "capistrano task" do before do - FileUtils.cp(FIXTURES_PATH.join('Capfile'), current_dir) + FileUtils.cp(FIXTURES_PATH.join("Capfile"), current_dir) end it "outputs the honeybadger task" do - expect(run_command('bundle exec cap -T')).to be_successfully_executed - expect(all_output).to match(/honeybadger\:deploy/i) + expect(run_command("bundle exec cap -T")).to be_successfully_executed + expect(all_output).to match(/honeybadger:deploy/i) end end diff --git a/spec/features/custom_agent_spec.rb b/spec/features/custom_agent_spec.rb index 67a098b92..6f99923d3 100644 --- a/spec/features/custom_agent_spec.rb +++ b/spec/features/custom_agent_spec.rb @@ -1,8 +1,8 @@ feature "Creating a custom agent" do - let(:crash_cmd) { "ruby #{ FIXTURES_PATH.join('ruby_custom.rb') }" } + let(:crash_cmd) { "ruby #{FIXTURES_PATH.join("ruby_custom.rb")}" } it "reports the exception to Honeybadger" do expect(run_command(crash_cmd)).not_to be_successfully_executed - assert_notification('error' => {'class' => 'CustomHoneybadgerException', 'message' => 'Test message'}) + assert_notification("error" => {"class" => "CustomHoneybadgerException", "message" => "Test message"}) end end diff --git a/spec/features/deploy_spec.rb b/spec/features/deploy_spec.rb index 8f7964559..851902b1e 100644 --- a/spec/features/deploy_spec.rb +++ b/spec/features/deploy_spec.rb @@ -1,7 +1,7 @@ -require 'honeybadger' +require "honeybadger" feature "Running the deploy cli command" do - before { set_environment_variable('HONEYBADGER_BACKEND', 'debug') } + before { set_environment_variable("HONEYBADGER_BACKEND", "debug") } it "notifies Honeybadger of the deploy" do output = capture(:stdout) { Honeybadger::CLI.start(%w[deploy --api-key=test-api-key --environment=test-env --revision=test-rev --repository=test-repo --user=test-user]) } @@ -10,16 +10,15 @@ context "when the options are invalid" do it "notifies the user" do - output = capture(:stdout) { expect{Honeybadger::CLI.start(%w[deploy --api-key= --environment=test-env --revision=test-rev --repository=test-repo --user=test-user])}.to raise_error(SystemExit) } + output = capture(:stdout) { expect { Honeybadger::CLI.start(%w[deploy --api-key= --environment=test-env --revision=test-rev --repository=test-repo --user=test-user]) }.to raise_error(SystemExit) } expect(output).to match(/required.+api-key/i) end end context "when there is a server error" do - before { set_environment_variable('DEBUG_BACKEND_STATUS', '500') } + before { set_environment_variable("DEBUG_BACKEND_STATUS", "500") } it "notifies the user" do - cmd = run_command("honeybadger deploy --api-key=test-api-key --environment=test-env --revision=test-rev --repository=test-repo --user=test-user") expect(cmd).not_to be_successfully_executed expect(cmd.output).to match(/request failed/i) @@ -35,10 +34,10 @@ context "when Rails is detected via the presence of environment.rb" do before do - @features_dir = File.join(Dir.pwd, 'tmp', 'features') - config_path = File.join(@features_dir, 'config') + @features_dir = File.join(Dir.pwd, "tmp", "features") + config_path = File.join(@features_dir, "config") Dir.mkdir(config_path) unless File.exist?(config_path) - File.open(File.join(config_path, 'environment.rb'), 'w') + File.open(File.join(config_path, "environment.rb"), "w") @_previous_dir = Dir.pwd Dir.chdir(@features_dir) end diff --git a/spec/features/exec_spec.rb b/spec/features/exec_spec.rb index 63f0b7499..698787c93 100644 --- a/spec/features/exec_spec.rb +++ b/spec/features/exec_spec.rb @@ -1,8 +1,7 @@ -require 'honeybadger' - +require "honeybadger" feature "Running the exec cli command" do - before { set_environment_variable('HONEYBADGER_BACKEND', 'debug') } + before { set_environment_variable("HONEYBADGER_BACKEND", "debug") } it "quietly executes the requested command" do output = capture(:stdout) { Honeybadger::CLI.start(%w[exec --api-key=test-api-key ls]) } @@ -12,7 +11,7 @@ context "when the options are invalid" do it "notifies the user" do output = capture(:stdout) do - expect{ Honeybadger::CLI.start(%w[exec --api-key= ls]) }.to raise_error(SystemExit) + expect { Honeybadger::CLI.start(%w[exec --api-key= ls]) }.to raise_error(SystemExit) end expect(output).to match(/required.+api-key/i) end @@ -21,7 +20,7 @@ context "when the command fails due to a non-zero exit code" do it "notifies Honeybadger of the failure" do output = capture(:stdout) do - expect{Honeybadger::CLI.start(%w[exec --api-key=test-api-key this-command-should-not-exist])}.to raise_error(SystemExit) + expect { Honeybadger::CLI.start(%w[exec --api-key=test-api-key this-command-should-not-exist]) }.to raise_error(SystemExit) end expect(output).to match(/failed.+this-command-should-not-exist/im) expect(output).to match(/Successfully notified Honeybadger/i) @@ -37,7 +36,7 @@ end end -context "when Rails is not detected due to a missing environment.rb" do + context "when Rails is not detected due to a missing environment.rb" do it "skips rails initialization without logging" do output = capture(:stdout) { Honeybadger::CLI.start(%w[exec --api-key=test-api-key --skip-rails-load ls]) } expect(output).to_not match(/Skipping Rails initialization/i) @@ -46,9 +45,9 @@ context "when Rails is detected via the presence of environment.rb" do before(:each) do - @config_path = File.join(Dir.pwd, 'config') + @config_path = File.join(Dir.pwd, "config") FileUtils.mkdir_p(@config_path) unless File.exist?(@config_path) - File.open(File.join(@config_path, 'environment.rb'), 'w') + File.open(File.join(@config_path, "environment.rb"), "w") end after(:each) { FileUtils.rm_rf(@config_path) } diff --git a/spec/features/install_spec.rb b/spec/features/install_spec.rb index 1ad8d4b95..8c17c2254 100644 --- a/spec/features/install_spec.rb +++ b/spec/features/install_spec.rb @@ -1,124 +1,124 @@ -require 'honeybadger/config' -require 'pathname' +require "honeybadger/config" +require "pathname" feature "Installing honeybadger via the cli" do shared_examples_for "cli installer" do |rails| - let(:config) { Honeybadger::Config.new(:api_key => 'asdf', :'config.path' => config_file) } + let(:config) { Honeybadger::Config.new(api_key: "asdf", "config.path": config_file) } - before { set_environment_variable('HONEYBADGER_BACKEND', 'debug') } + before { set_environment_variable("HONEYBADGER_BACKEND", "debug") } it "outputs successful result" do - expect(run_command('honeybadger install asdf')).to be_successfully_executed - expect(all_output).to match /Writing configuration/i - expect(all_output).to match /Happy 'badgering/i - expect(all_output).not_to match /heroku/i - expect(all_output).not_to match /Starting Honeybadger/i + expect(run_command("honeybadger install asdf")).to be_successfully_executed + expect(all_output).to match(/Writing configuration/i) + expect(all_output).to match(/Happy 'badgering/i) + expect(all_output).not_to match(/heroku/i) + expect(all_output).not_to match(/Starting Honeybadger/i) if rails - expect(all_output).to match /Detected Rails/i + expect(all_output).to match(/Detected Rails/i) else - expect(all_output).not_to match /Detected Rails/i + expect(all_output).not_to match(/Detected Rails/i) end end it "creates the configuration file" do expect { - run_command_and_stop('honeybadger install asdf', fail_on_error: true) + run_command_and_stop("honeybadger install asdf", fail_on_error: true) }.to change { config_file.exist? }.from(false).to(true) end it "sends a test notification" do - set_environment_variable('HONEYBADGER_LOGGING_LEVEL', '1') - expect(run_command('honeybadger install asdf')).to be_successfully_executed - assert_notification('error' => {'class' => 'HoneybadgerTestingException'}) + set_environment_variable("HONEYBADGER_LOGGING_LEVEL", "1") + expect(run_command("honeybadger install asdf")).to be_successfully_executed + assert_notification("error" => {"class" => "HoneybadgerTestingException"}) end context "with the --no-test option" do it "skips the test notification" do - set_environment_variable('HONEYBADGER_LOGGING_LEVEL', '1') - expect(run_command('honeybadger install asdf --no-test')).to be_successfully_executed + set_environment_variable("HONEYBADGER_LOGGING_LEVEL", "1") + expect(run_command("honeybadger install asdf --no-test")).to be_successfully_executed assert_no_notification end end context "with the insights flag" do it "enables insights" do - run_command_and_stop('honeybadger install asdf --insights', fail_on_error: true) + run_command_and_stop("honeybadger install asdf --insights", fail_on_error: true) expect(YAML.load_file(config_file).dig("insights", "enabled")).to eq(true) end it "disables insights" do - run_command_and_stop('honeybadger install asdf --no-insights', fail_on_error: true) + run_command_and_stop("honeybadger install asdf --no-insights", fail_on_error: true) expect(YAML.load_file(config_file).dig("insights", "enabled")).to eq(false) end end - + context "with host and/or UI host flags" do let(:yaml) { YAML.load_file(config_file) } - + it "configures the host" do - run_command_and_stop('honeybadger install asdf --host api.honeybadger.io', fail_on_error: true) - expect(yaml.dig("connection", "host")).to eq('api.honeybadger.io') + run_command_and_stop("honeybadger install asdf --host api.honeybadger.io", fail_on_error: true) + expect(yaml.dig("connection", "host")).to eq("api.honeybadger.io") end - + it "configures the UI host" do - run_command_and_stop('honeybadger install asdf --ui_host app.honeybadger.io', fail_on_error: true) - expect(yaml.dig("connection", "ui_host")).to eq('app.honeybadger.io') + run_command_and_stop("honeybadger install asdf --ui_host app.honeybadger.io", fail_on_error: true) + expect(yaml.dig("connection", "ui_host")).to eq("app.honeybadger.io") end - + it "configures both hosts" do - run_command_and_stop('honeybadger install asdf --host api.honeybadger.io --ui_host app.honeybadger.io', fail_on_error: true) - expect(yaml.dig("connection", "host")).to eq('api.honeybadger.io') - expect(yaml.dig("connection", "ui_host")).to eq('app.honeybadger.io') + run_command_and_stop("honeybadger install asdf --host api.honeybadger.io --ui_host app.honeybadger.io", fail_on_error: true) + expect(yaml.dig("connection", "host")).to eq("api.honeybadger.io") + expect(yaml.dig("connection", "ui_host")).to eq("app.honeybadger.io") end end scenario "when the configuration file already exists" do - before { File.write(config_file, <<-YML) } ---- -api_key: 'asdf' -YML + before { File.write(config_file, <<~YML) } + --- + api_key: 'asdf' + YML it "does not overwrite existing configuration" do - expect(run_command('honeybadger install asdf')).to be_successfully_executed + expect(run_command("honeybadger install asdf")).to be_successfully_executed expect { - run_command_and_stop('honeybadger install asdf', fail_on_error: true) + run_command_and_stop("honeybadger install asdf", fail_on_error: true) }.not_to change { config_file.mtime } end it "outputs successful result" do - expect(run_command('honeybadger install asdf')).to be_successfully_executed - expect(all_output).to match /Happy 'badgering/i + expect(run_command("honeybadger install asdf")).to be_successfully_executed + expect(all_output).to match(/Happy 'badgering/i) end end scenario "when capistrano is detected" do - let(:capfile) { Pathname(current_dir).join('Capfile') } - - before { File.write(capfile, <<-YML) } -if respond_to?(:namespace) # cap2 differentiator - load 'deploy' -else - require 'capistrano/setup' - require 'capistrano/deploy' -end -YML + let(:capfile) { Pathname(current_dir).join("Capfile") } + + before { File.write(capfile, <<~YML) } + if respond_to?(:namespace) # cap2 differentiator + load 'deploy' + else + require 'capistrano/setup' + require 'capistrano/deploy' + end + YML it "installs capistrano command" do - expect(run_command('honeybadger install asdf')).to be_successfully_executed - expect(run_command('bundle exec cap -T')).to be_successfully_executed - expect(all_output).to match(/honeybadger\:deploy/i) + expect(run_command("honeybadger install asdf")).to be_successfully_executed + expect(run_command("bundle exec cap -T")).to be_successfully_executed + expect(all_output).to match(/honeybadger:deploy/i) end end end scenario "in a plain ruby project" do - let(:config_file) { Pathname(current_dir).join('honeybadger.yml') } + let(:config_file) { Pathname(current_dir).join("honeybadger.yml") } it_behaves_like "cli installer", false end scenario "in a Rails project", framework: :rails do - let(:config_file) { Pathname(current_dir).join('config', 'honeybadger.yml') } + let(:config_file) { Pathname(current_dir).join("config", "honeybadger.yml") } it_behaves_like "cli installer", true end diff --git a/spec/features/notify_spec.rb b/spec/features/notify_spec.rb index 8da42605b..58be5c037 100644 --- a/spec/features/notify_spec.rb +++ b/spec/features/notify_spec.rb @@ -1,34 +1,34 @@ feature "Running the notify CLI command" do before do - set_environment_variable('HONEYBADGER_API_KEY', 'asdf') - set_environment_variable('HONEYBADGER_LOGGING_LEVEL', 'DEBUG') + set_environment_variable("HONEYBADGER_API_KEY", "asdf") + set_environment_variable("HONEYBADGER_LOGGING_LEVEL", "DEBUG") end it "requires the --message flag" do output = capture(:stderr) { Honeybadger::CLI.start(%w[notify]) } - expect(output).to match('--message') + expect(output).to match("--message") assert_no_notification(output) end context "with a message" do it "reports an exception with a default class" do expect(run_command('honeybadger notify --message "Test error message"')).to be_successfully_executed - assert_notification('error' => {'class' => 'CLI Notification', 'message' => 'Test error message'}) + assert_notification("error" => {"class" => "CLI Notification", "message" => "Test error message"}) end it "overrides the class via --class flag" do expect(run_command('honeybadger notify --class "MyClass" --message "Test error message"')).to be_successfully_executed - assert_notification('error' => {'class' => 'MyClass'}) + assert_notification("error" => {"class" => "MyClass"}) end it "uses configured API key" do expect(run_command('honeybadger notify --message "Test error message"')).to be_successfully_executed - assert_notification('api_key' => 'asdf') + assert_notification("api_key" => "asdf") end it "overrides the API key via --api-key flag" do expect(run_command('honeybadger notify --message "Test error message" --api-key my-key')).to be_successfully_executed - assert_notification('api_key' => 'my-key') + assert_notification("api_key" => "my-key") end end @@ -41,9 +41,9 @@ context "when Rails is detected via the presence of environment.rb" do before do - config_path = File.join(Dir.pwd, 'tmp', 'features', 'config') + config_path = File.join(Dir.pwd, "tmp", "features", "config") Dir.mkdir(config_path) unless File.exist?(config_path) - File.open(File.join(config_path, 'environment.rb'), 'w') + File.open(File.join(config_path, "environment.rb"), "w") end it "skips rails initialization when true" do diff --git a/spec/features/rake_spec.rb b/spec/features/rake_spec.rb index 27415cd5a..2a874004e 100644 --- a/spec/features/rake_spec.rb +++ b/spec/features/rake_spec.rb @@ -1,40 +1,40 @@ feature "Rescuing exceptions in a rake task" do before do - FileUtils.cp(FIXTURES_PATH.join('Rakefile'), current_dir) - set_environment_variable('HONEYBADGER_API_KEY', 'asdf') - set_environment_variable('HONEYBADGER_LOGGING_LEVEL', 'DEBUG') + FileUtils.cp(FIXTURES_PATH.join("Rakefile"), current_dir) + set_environment_variable("HONEYBADGER_API_KEY", "asdf") + set_environment_variable("HONEYBADGER_LOGGING_LEVEL", "DEBUG") end it "reports the exception to Honeybadger" do - expect(run_command('rake honeybadger')).not_to be_successfully_executed - assert_notification('error' => {'class' => 'RuntimeError', 'message' => 'RuntimeError: Jim has left the building :('}) + expect(run_command("rake honeybadger")).not_to be_successfully_executed + assert_notification("error" => {"class" => "RuntimeError", "message" => "RuntimeError: Jim has left the building :("}) end context "rake reporting is disabled" do before do - set_environment_variable('HONEYBADGER_EXCEPTIONS_RESCUE_RAKE', 'false') + set_environment_variable("HONEYBADGER_EXCEPTIONS_RESCUE_RAKE", "false") end it "doesn't report the exception to Honeybadger" do - expect(run_command('rake honeybadger')).not_to be_successfully_executed + expect(run_command("rake honeybadger")).not_to be_successfully_executed assert_no_notification end end context "shell is attached" do it "doesn't report the exception to Honeybadger" do - expect(run_command('rake honeybadger_autodetect_from_terminal')).not_to be_successfully_executed + expect(run_command("rake honeybadger_autodetect_from_terminal")).not_to be_successfully_executed assert_no_notification end context "rake reporting is enabled" do before do - set_environment_variable('HONEYBADGER_EXCEPTIONS_RESCUE_RAKE', 'true') + set_environment_variable("HONEYBADGER_EXCEPTIONS_RESCUE_RAKE", "true") end it "reports the exception to Honeybadger" do - expect(run_command('rake honeybadger_autodetect_from_terminal')).not_to be_successfully_executed - assert_notification('error' => {'class' => 'RuntimeError', 'message' => 'RuntimeError: Jim has left the building :('}) + expect(run_command("rake honeybadger_autodetect_from_terminal")).not_to be_successfully_executed + assert_notification("error" => {"class" => "RuntimeError", "message" => "RuntimeError: Jim has left the building :("}) end end end diff --git a/spec/features/test_spec.rb b/spec/features/test_spec.rb index 2f6552cdf..bbb9325f7 100644 --- a/spec/features/test_spec.rb +++ b/spec/features/test_spec.rb @@ -1,55 +1,55 @@ -require 'honeybadger' +require "honeybadger" feature "Running the test cli command" do scenario "in a standalone project" do it "displays expected debug output and sends notification" do - set_environment_variable('HONEYBADGER_API_KEY', 'asdf') + set_environment_variable("HONEYBADGER_API_KEY", "asdf") expect(run_command("honeybadger test")).to be_successfully_executed - expect(all_output).not_to match /Detected Rails/i - expect(all_output).to match /asdf/ - expect(all_output).to match /HoneybadgerTestingException/ + expect(all_output).not_to match(/Detected Rails/i) + expect(all_output).to match(/asdf/) + expect(all_output).to match(/HoneybadgerTestingException/) # Make sure the worker timeout isn't being exceeded. - expect(all_output).not_to match /kill/ - assert_notification('error' => {'class' => 'HoneybadgerTestingException'}) + expect(all_output).not_to match(/kill/) + assert_notification("error" => {"class" => "HoneybadgerTestingException"}) end - - it "displays init message when debugging" do - set_environment_variable('HONEYBADGER_API_KEY', 'asdf') - set_environment_variable('HONEYBADGER_DEBUG', '1') + + it "displays init message when debugging" do + set_environment_variable("HONEYBADGER_API_KEY", "asdf") + set_environment_variable("HONEYBADGER_DEBUG", "1") expect(run_command("honeybadger test")).to be_successfully_executed - expect(all_output).to match /Initializing Honeybadger/ + expect(all_output).to match(/Initializing Honeybadger/) end - + context "with invalid configuration" do it "displays expected debug output" do expect(run_command("honeybadger test --dry-run")).not_to be_successfully_executed - expect(all_output).not_to match /Detected Rails/i - expect(all_output).to match /API key is missing/i + expect(all_output).not_to match(/Detected Rails/i) + expect(all_output).to match(/API key is missing/i) end end end scenario "in a rails project", framework: :rails do - let(:config_file) { Pathname(current_dir).join('config', 'honeybadger.yml') } + let(:config_file) { Pathname(current_dir).join("config", "honeybadger.yml") } it "displays expected debug output and sends notification" do - File.write(config_file, <<-YML) ---- -api_key: 'asdf' -YML + File.write(config_file, <<~YML) + --- + api_key: 'asdf' + YML expect(run_command("honeybadger test")).to be_successfully_executed - expect(all_output).to match /Detected Rails/i - expect(all_output).to match /asdf/ - expect(all_output).to match /HoneybadgerTestingException/ - assert_notification('error' => {'class' => 'HoneybadgerTestingException'}) + expect(all_output).to match(/Detected Rails/i) + expect(all_output).to match(/asdf/) + expect(all_output).to match(/HoneybadgerTestingException/) + assert_notification("error" => {"class" => "HoneybadgerTestingException"}) end context "with invalid configuration" do it "displays expected debug output" do expect(run_command("honeybadger test --dry-run")).not_to be_successfully_executed - expect(all_output).to match /Detected Rails/i - expect(all_output).to match /API key is missing/i + expect(all_output).to match(/Detected Rails/i) + expect(all_output).to match(/API key is missing/i) end end end diff --git a/spec/fixtures/Capfile b/spec/fixtures/Capfile index e03a9ef85..226be3d58 100644 --- a/spec/fixtures/Capfile +++ b/spec/fixtures/Capfile @@ -1,8 +1,8 @@ if respond_to?(:namespace) # cap2 differentiator - load 'deploy' + load "deploy" else - require 'capistrano/setup' - require 'capistrano/deploy' + require "capistrano/setup" + require "capistrano/deploy" end -require 'capistrano/honeybadger' +require "capistrano/honeybadger" diff --git a/spec/fixtures/Rakefile b/spec/fixtures/Rakefile index c318c1d75..54757ce20 100644 --- a/spec/fixtures/Rakefile +++ b/spec/fixtures/Rakefile @@ -1,19 +1,19 @@ # A test harness for RakeHandler # -require 'rake' -require 'rubygems' +require "rake" +require "rubygems" # Should catch exception task :honeybadger do stub_tty_output(false) - require 'honeybadger' + require "honeybadger" raise_exception end # Should not catch exception as tty_output is true task :honeybadger_autodetect_from_terminal do stub_tty_output(true) - require 'honeybadger' + require "honeybadger" raise_exception end @@ -30,5 +30,5 @@ def stub_tty_output(value) end def raise_exception - raise 'Jim has left the building :(' + raise "Jim has left the building :(" end diff --git a/spec/fixtures/hanami/app.rb b/spec/fixtures/hanami/app.rb index 01700f025..aef86b294 100644 --- a/spec/fixtures/hanami/app.rb +++ b/spec/fixtures/hanami/app.rb @@ -8,7 +8,7 @@ class App < Hanami::App class Routes < Hanami::Routes get "/runtime_error" do - raise 'exception raised from test Hanami app in honeybadger gem test suite' + raise "exception raised from test Hanami app in honeybadger gem test suite" end end end diff --git a/spec/fixtures/rails/config/application.rb b/spec/fixtures/rails/config/application.rb index 7435bdaac..05a204837 100644 --- a/spec/fixtures/rails/config/application.rb +++ b/spec/fixtures/rails/config/application.rb @@ -1,5 +1,5 @@ -require 'rails' -require 'action_controller/railtie' +require "rails" +require "action_controller/railtie" # Duplicating here as some specs don't use the rails helper SKIP_ACTIVE_RECORD = !!(defined?(JRUBY_VERSION) && Rails::VERSION::PRE == "alpha") @@ -10,14 +10,14 @@ class RecordNotFound < StandardError end end else - require 'active_record/railtie' - require 'activerecord-jdbcsqlite3-adapter' if defined?(JRUBY_VERSION) - require 'active_support' - require 'active_support/core_ext/enumerable' - ENV['DATABASE_URL'] = 'sqlite3::memory:' + require "active_record/railtie" + require "activerecord-jdbcsqlite3-adapter" if defined?(JRUBY_VERSION) + require "active_support" + require "active_support/core_ext/enumerable" + ENV["DATABASE_URL"] = "sqlite3::memory:" end -require 'active_job/railtie' +require "active_job/railtie" class RailsApp < Rails::Application # Rails 6+ @@ -25,7 +25,7 @@ class RailsApp < Rails::Application config.hosts << "www.example.com" end - config.secret_key_base = 'test secret key base for test rails app' + config.secret_key_base = "test secret key base for test rails app" config.eager_load = true config.cache_classes = true config.serve_static_files = false @@ -34,9 +34,9 @@ class RailsApp < Rails::Application config.active_job.queue_adapter = :test routes.append do - get '/runtime_error', :to => 'rails#runtime_error' - get '/record_not_found', :to => 'rails#record_not_found' - root to: 'rails#index' + get "/runtime_error", to: "rails#runtime_error" + get "/record_not_found", to: "rails#record_not_found" + root to: "rails#index" end end @@ -46,7 +46,7 @@ class ApplicationController < ActionController::Base class RailsController < ApplicationController def runtime_error - raise 'exception raised from test Rails app in honeybadger gem test suite' + raise "exception raised from test Rails app in honeybadger gem test suite" end def record_not_found @@ -54,12 +54,12 @@ def record_not_found end def index - render plain: 'This is a test Rails app used by the honeybadger gem test suite.' + render plain: "This is a test Rails app used by the honeybadger gem test suite." end end -Rails.env = 'production' +Rails.env = "production" Rails.logger = Logger.new(File::NULL) -require_relative './breadcrumbs' -require_relative './queue_adapter' +require_relative "breadcrumbs" +require_relative "queue_adapter" diff --git a/spec/fixtures/rails/config/breadcrumbs.rb b/spec/fixtures/rails/config/breadcrumbs.rb index cec4cd138..f79370cd0 100644 --- a/spec/fixtures/rails/config/breadcrumbs.rb +++ b/spec/fixtures/rails/config/breadcrumbs.rb @@ -31,7 +31,7 @@ def cache_event private def notice - Honeybadger.notify(StandardError.new('test backend')) + Honeybadger.notify(StandardError.new("test backend")) head 200 end end @@ -41,4 +41,3 @@ def notice get "/breadcrumbs/#{action}", to: "breadcrumb##{action}" end end - diff --git a/spec/fixtures/rails/config/environment.rb b/spec/fixtures/rails/config/environment.rb index 83dee1a01..afb282079 100644 --- a/spec/fixtures/rails/config/environment.rb +++ b/spec/fixtures/rails/config/environment.rb @@ -1,8 +1,8 @@ # Load the rails application -require File.expand_path('../application', __FILE__) +require File.expand_path("../application", __FILE__) # Load honeybadger hooks before initialization. -require 'honeybadger' +require "honeybadger" # Initialize the rails application RailsApp.initialize! diff --git a/spec/fixtures/ruby_crash.rb b/spec/fixtures/ruby_crash.rb index 03f6cd1a9..5caca2830 100644 --- a/spec/fixtures/ruby_crash.rb +++ b/spec/fixtures/ruby_crash.rb @@ -1,2 +1,2 @@ -require 'honeybadger' -raise 'badgers!' +require "honeybadger" +raise "badgers!" diff --git a/spec/fixtures/ruby_custom.rb b/spec/fixtures/ruby_custom.rb index ec5e70e09..98bc9d40c 100644 --- a/spec/fixtures/ruby_custom.rb +++ b/spec/fixtures/ruby_custom.rb @@ -1,14 +1,14 @@ -require 'honeybadger/ruby' +require "honeybadger/ruby" agent = Honeybadger::Agent.new({ - api_key: 'asdf', - backend: 'debug', + api_key: "asdf", + backend: "debug", debug: true, logger: Logger.new(STDOUT) }) -agent.notify(error_class: 'CustomHoneybadgerException', error_message: 'Test message') +agent.notify(error_class: "CustomHoneybadgerException", error_message: "Test message") agent.flush -raise 'This should not be reported.' +raise "This should not be reported." diff --git a/spec/fixtures/ruby_custom_crash.rb b/spec/fixtures/ruby_custom_crash.rb index 1c9334d7f..c18c213d3 100644 --- a/spec/fixtures/ruby_custom_crash.rb +++ b/spec/fixtures/ruby_custom_crash.rb @@ -1,11 +1,11 @@ -require 'honeybadger' +require "honeybadger" CRASHES = { - "system_exit" => ->{ exit -1 }, - "sigterm" => ->{ raise SignalException, "TERM" }, - "hup" => ->{ raise SignalException, "SIGHUP" }, + "system_exit" => -> { exit(-1) }, + "sigterm" => -> { raise SignalException, "TERM" }, + "hup" => -> { raise SignalException, "SIGHUP" } } crash_type = ARGV.first || (raise "Invalid argument") -(CRASHES[crash_type] || ->{ raise "Invalid crash type" }).() +(CRASHES[crash_type] || -> { raise "Invalid crash type" }).call diff --git a/spec/fixtures/sinatra/app.rb b/spec/fixtures/sinatra/app.rb index 91bf288e7..8e5178286 100644 --- a/spec/fixtures/sinatra/app.rb +++ b/spec/fixtures/sinatra/app.rb @@ -1,19 +1,19 @@ -require 'sinatra/base' +require "sinatra/base" class SinatraApp < Sinatra::Base - set :host_authorization, { permitted_hosts: [] } + set :host_authorization, {permitted_hosts: []} set :show_exceptions, false - set :honeybadger_api_key, 'gem testing' + set :honeybadger_api_key, "gem testing" - get '/runtime_error' do - raise 'exception raised from test Sinatra app in honeybadger gem test suite' + get "/runtime_error" do + raise "exception raised from test Sinatra app in honeybadger gem test suite" end - get '/' do - 'This is a test Sinatra app used by the honeybadger gem test suite.' + get "/" do + "This is a test Sinatra app used by the honeybadger gem test suite." end error 500 do - 'An error happened. ' + "An error happened. " end end diff --git a/spec/integration/hanami_spec.rb b/spec/integration/hanami_spec.rb index f7113ddcc..42b7aa672 100644 --- a/spec/integration/hanami_spec.rb +++ b/spec/integration/hanami_spec.rb @@ -1,18 +1,18 @@ begin - require 'hanami' - require 'rack/test' + require "hanami" + require "rack/test" HANAMI_PRESENT = true rescue LoadError HANAMI_PRESENT = false - puts 'Skipping Hanami integration specs.' + puts "Skipping Hanami integration specs." end return unless HANAMI_PRESENT -require FIXTURES_PATH.join('hanami', 'app.rb') -require 'honeybadger/init/hanami' +require FIXTURES_PATH.join("hanami", "app.rb") +require "honeybadger/init/hanami" -describe 'Hanami integration' do +describe "Hanami integration" do include Rack::Test::Methods def app @@ -21,8 +21,8 @@ def app before(:each) do Honeybadger.configure do |config| - config.api_key = 'gem testing' - config.backend = 'test' + config.api_key = "gem testing" + config.backend = "test" end end @@ -31,9 +31,9 @@ def app end it "reports exceptions" do - error_message = 'exception raised from test Hanami app in honeybadger gem test suite' + error_message = "exception raised from test Hanami app in honeybadger gem test suite" Honeybadger.flush do - expect { get '/runtime_error' }.to raise_error(error_message) + expect { get "/runtime_error" }.to raise_error(error_message) end expect(Honeybadger::Backend::Test.notifications[:notices].size).to eq(1) @@ -41,4 +41,3 @@ def app expect(notice.error_message).to match(error_message) end end - diff --git a/spec/integration/rails/active_job_adapter_spec.rb b/spec/integration/rails/active_job_adapter_spec.rb index 9e4f96a8b..ebe6b00d5 100644 --- a/spec/integration/rails/active_job_adapter_spec.rb +++ b/spec/integration/rails/active_job_adapter_spec.rb @@ -1,47 +1,47 @@ -require_relative '../rails_helper' +require_relative "../rails_helper" -describe 'Rails ActiveJob Adapter Test', if: RAILS_PRESENT, type: :request do +describe "Rails ActiveJob Adapter Test", if: RAILS_PRESENT, type: :request do include ActiveJob::TestHelper if RAILS_PRESENT load_rails_hooks(self) - it 'reports exceptions' do + it "reports exceptions" do Honeybadger.flush do perform_enqueued_jobs do expect do - ErrorJob.perform_later({ some: 'data' }) + ErrorJob.perform_later({some: "data"}) end.to raise_error(StandardError) end end expect(Honeybadger::Backend::Test.notifications[:notices].size).to eq(1) - expect(Honeybadger::Backend::Test.notifications[:notices][0].params[:arguments][0]).to eq({ some: 'data' }) + expect(Honeybadger::Backend::Test.notifications[:notices][0].params[:arguments][0]).to eq({some: "data"}) expect(Honeybadger::Backend::Test.notifications[:notices][0].context).to \ include( component: ErrorJob, - action: 'perform', + action: "perform", enqueued_at: anything, executions: 1, job_class: ErrorJob, job_id: anything, priority: anything, - queue_name: 'default', + queue_name: "default", scheduled_at: anything ) end - it 'does not report exceptions if the attempt threshold is not reached' do - Honeybadger.config[:'active_job.attempt_threshold'] = 2 + it "does not report exceptions if the attempt threshold is not reached" do + Honeybadger.config[:"active_job.attempt_threshold"] = 2 Honeybadger.flush do perform_enqueued_jobs do expect do - ErrorJob.perform_later({ some: 'data' }) + ErrorJob.perform_later({some: "data"}) end.to raise_error(StandardError) end end expect(Honeybadger::Backend::Test.notifications[:notices].size).to eq(0) - Honeybadger.config[:'active_job.attempt_threshold'] = 0 + Honeybadger.config[:"active_job.attempt_threshold"] = 0 end end diff --git a/spec/integration/rails/basic_spec.rb b/spec/integration/rails/basic_spec.rb index e76c6a9c0..b8f45d421 100644 --- a/spec/integration/rails/basic_spec.rb +++ b/spec/integration/rails/basic_spec.rb @@ -1,4 +1,4 @@ -require_relative '../rails_helper' +require_relative "../rails_helper" describe "Rails integration", if: RAILS_PRESENT, type: :request do load_rails_hooks(self) diff --git a/spec/integration/rails/breadcrumb_spec.rb b/spec/integration/rails/breadcrumb_spec.rb index 0bea1e108..cb4cc2dcd 100644 --- a/spec/integration/rails/breadcrumb_spec.rb +++ b/spec/integration/rails/breadcrumb_spec.rb @@ -1,6 +1,6 @@ -require_relative '../rails_helper' +require_relative "../rails_helper" -describe 'Rails Breadcrumbs integration', if: RAILS_PRESENT, type: :request do +describe "Rails Breadcrumbs integration", if: RAILS_PRESENT, type: :request do # The plugin is defaulted to off, we need to make sure we re-load plugins # after config as plugins only check requirement only at load time before(:all) do @@ -46,7 +46,7 @@ def get_trail(notice) expect(notices.first).to contain_breadcrumb_including({ category: "log", message: "test log event", - metadata: include({ severity: "INFO" }) + metadata: include({severity: "INFO"}) }) end diff --git a/spec/integration/rails/error_subscriber_spec.rb b/spec/integration/rails/error_subscriber_spec.rb index 9a27d0bf1..0c1a8ac62 100644 --- a/spec/integration/rails/error_subscriber_spec.rb +++ b/spec/integration/rails/error_subscriber_spec.rb @@ -1,24 +1,24 @@ -require_relative '../rails_helper' +require_relative "../rails_helper" RAILS_ERROR_REPORTER_SUPPORTED = defined?(::ActiveSupport::ErrorReporter) return unless RAILS_ERROR_REPORTER_SUPPORTED -RAILS_ERROR_SOURCE_SUPPORTED = ::Rails::VERSION::STRING >= '7.1' +RAILS_ERROR_SOURCE_SUPPORTED = ::Rails::VERSION::STRING >= "7.1" describe "Rails error subscriber integration" do load_rails_hooks(self) it "always reports handled exceptions" do Honeybadger.flush do - Rails.error.handle(severity: :warning, context: { key: 'value' }) do - raise RuntimeError, "Oh no" + Rails.error.handle(severity: :warning, context: {key: "value"}) do + raise "Oh no" end end expect(Honeybadger::Backend::Test.notifications[:notices].size).to eq(1) notice = Honeybadger::Backend::Test.notifications[:notices].first expect(notice.error_class).to eq("RuntimeError") - expect(notice.context).to eq({ key: 'value' }) + expect(notice.context).to eq({key: "value"}) tags = ["severity:warning", "handled:true"] tags << "source:application" if RAILS_ERROR_SOURCE_SUPPORTED expect(notice.tags).to eq(tags) @@ -28,8 +28,8 @@ expect do Honeybadger.flush do Rails.application.executor.wrap do - Rails.error.set_context(key: 'value') - raise RuntimeError, "Oh no" + Rails.error.set_context(key: "value") + raise "Oh no" end end end.to raise_error(RuntimeError, "Oh no") @@ -41,8 +41,8 @@ expect do Honeybadger.flush do Rails.application.executor.wrap do - Rails.error.set_context(key: 'value') - raise RuntimeError, "Oh no" + Rails.error.set_context(key: "value") + raise "Oh no" end end end.to raise_error(RuntimeError, "Oh no") @@ -52,15 +52,15 @@ it "reports exceptions with source", if: RAILS_ERROR_SOURCE_SUPPORTED do Honeybadger.flush do - Rails.error.handle(severity: :warning, context: { key: 'value' }, source: "task") do - raise RuntimeError, "Oh no" + Rails.error.handle(severity: :warning, context: {key: "value"}, source: "task") do + raise "Oh no" end end expect(Honeybadger::Backend::Test.notifications[:notices].size).to eq(1) notice = Honeybadger::Backend::Test.notifications[:notices].first expect(notice.error_class).to eq("RuntimeError") - expect(notice.context).to eq({ key: 'value' }) + expect(notice.context).to eq({key: "value"}) expect(notice.tags).to eq(["severity:warning", "handled:true", "source:task"]) end @@ -70,8 +70,8 @@ end Honeybadger.flush do - Rails.error.handle(severity: :warning, context: { key: 'value' }, source: "ignored_source") do - raise RuntimeError, "Oh no" + Rails.error.handle(severity: :warning, context: {key: "value"}, source: "ignored_source") do + raise "Oh no" end end diff --git a/spec/integration/rails_helper.rb b/spec/integration/rails_helper.rb index 87318ee02..cf506d247 100644 --- a/spec/integration/rails_helper.rb +++ b/spec/integration/rails_helper.rb @@ -1,9 +1,9 @@ begin - # Require these early to work around https://github.com/jruby/jruby#6547 + # Require these early to work around https://github.com/jruby/jruby#6547 # can be pulled out > 9.2.14 of jruby. - require 'i18n' - require 'i18n/backend/simple' - require 'rails' + require "i18n" + require "i18n/backend/simple" + require "rails" RAILS_PRESENT = true # We are unable to run Activerecord with rails edge on jruby as the sqlite @@ -11,13 +11,13 @@ # that runtime and Rails version SKIP_ACTIVE_RECORD = !!(defined?(JRUBY_VERSION) && Rails::VERSION::PRE == "alpha") - require FIXTURES_PATH.join('rails', 'config', 'application.rb') - require 'honeybadger/init/rails' - require 'rspec/rails' + require FIXTURES_PATH.join("rails", "config", "application.rb") + require "honeybadger/init/rails" + require "rspec/rails" rescue LoadError RAILS_PRESENT = false SKIP_ACTIVE_RECORD = true - puts 'Skipping Rails integration specs.' + puts "Skipping Rails integration specs." end # Defining this as a method as we only want to include these hooks in rails @@ -37,8 +37,8 @@ def load_rails_hooks(spec) spec.before(:each) do Honeybadger.configure do |config| - config.api_key = 'gem testing' - config.backend = 'test' + config.api_key = "gem testing" + config.backend = "test" end end diff --git a/spec/integration/resque_spec.rb b/spec/integration/resque_spec.rb index 0f5ee6e15..95b559b51 100644 --- a/spec/integration/resque_spec.rb +++ b/spec/integration/resque_spec.rb @@ -1,16 +1,16 @@ begin - require 'resque' - require 'mock_redis' + require "resque" + require "mock_redis" RESQUE_PRESENT = true rescue LoadError RESQUE_PRESENT = false - puts 'Skipping Resque integration specs.' + puts "Skipping Resque integration specs." end if RESQUE_PRESENT - require 'honeybadger' + require "honeybadger" - ERROR = StandardError.new('This is a failure inside Honeybadger integration test suite') + ERROR = StandardError.new("This is a failure inside Honeybadger integration test suite") class TestWorker @queue = :test @@ -28,7 +28,7 @@ def self.perform end end - describe 'Resque integration' do + describe "Resque integration" do let(:worker) { Resque::Worker.new(:test) } before(:all) do @@ -36,7 +36,7 @@ def self.perform end it "reports failed jobs to Honeybadger" do - job = Resque::Job.new(:jobs, {'class' => 'TestWorker', 'args' => nil}) + job = Resque::Job.new(:jobs, {"class" => "TestWorker", "args" => nil}) expect(Honeybadger).to receive(:notify).once.with(ERROR, anything) @@ -44,7 +44,7 @@ def self.perform end it "reports DirtyExit to Honeybadger" do - job = Resque::Job.new(:jobs, {'class' => 'TestWorker', 'args' => nil}) + job = Resque::Job.new(:jobs, {"class" => "TestWorker", "args" => nil}) expect(Honeybadger).to receive(:notify).once.with(kind_of(Resque::DirtyExit), anything) diff --git a/spec/integration/sidekiq_spec.rb b/spec/integration/sidekiq_spec.rb index 532a655cd..aff55b9c8 100644 --- a/spec/integration/sidekiq_spec.rb +++ b/spec/integration/sidekiq_spec.rb @@ -1,6 +1,6 @@ begin - require 'ostruct' - require 'sidekiq' + require "ostruct" + require "sidekiq" SIDEKIQ_PRESENT = true rescue LoadError SIDEKIQ_PRESENT = false @@ -10,24 +10,24 @@ Sidekiq.define_singleton_method(:server?) { true } # So Sidekiq.configure_server block is run -String.define_method(:constantize) { Object.const_get(self) } if Sidekiq::VERSION < '7' +String.define_method(:constantize) { Object.const_get(self) } if Sidekiq::VERSION < "7" -require 'sidekiq/processor' +require "sidekiq/processor" def run_sidekiq_job(klass, args) - config = Sidekiq::VERSION >= '7' ? ::Sidekiq.default_configuration.default_capsule : ::Sidekiq + config = (Sidekiq::VERSION >= "7") ? ::Sidekiq.default_configuration.default_capsule : ::Sidekiq processor = Sidekiq::Processor.new(config) job_str = { - 'args' => args, 'class' => klass.to_s, 'jid' => SecureRandom.uuid + "args" => args, "class" => klass.to_s, "jid" => SecureRandom.uuid }.to_json - unit_of_work = OpenStruct.new(job: job_str, queue: 'default') + unit_of_work = OpenStruct.new(job: job_str, queue: "default") processor.__send__(:process, unit_of_work) end -require 'honeybadger' +require "honeybadger" -ERROR = StandardError.new('This is a failure inside Honeybadger integration test suite') +ERROR = StandardError.new("This is a failure inside Honeybadger integration test suite") class SidekiqJobNoRetry include Sidekiq::Job @@ -38,10 +38,10 @@ def perform(*args) end end -describe 'Sidekiq integration' do - it 'calls the error handler' do +describe "Sidekiq integration" do + it "calls the error handler" do expect(Honeybadger).to receive(:notify).once.with(ERROR, anything) - expect { run_sidekiq_job(SidekiqJobNoRetry, ['Tim', 10]) }.to raise_error(ERROR) + expect { run_sidekiq_job(SidekiqJobNoRetry, ["Tim", 10]) }.to raise_error(ERROR) end end diff --git a/spec/integration/sinatra_spec.rb b/spec/integration/sinatra_spec.rb index eebdf1692..d6331010d 100644 --- a/spec/integration/sinatra_spec.rb +++ b/spec/integration/sinatra_spec.rb @@ -1,17 +1,17 @@ begin - require 'sinatra/base' - require 'rack/test' + require "sinatra/base" + require "rack/test" SINATRA_PRESENT = true rescue LoadError SINATRA_PRESENT = false - puts 'Skipping Sinatra integration specs.' + puts "Skipping Sinatra integration specs." end if SINATRA_PRESENT - require FIXTURES_PATH.join('sinatra', 'app.rb') - require 'honeybadger/init/sinatra' + require FIXTURES_PATH.join("sinatra", "app.rb") + require "honeybadger/init/sinatra" - describe 'Sinatra integration' do + describe "Sinatra integration" do include Rack::Test::Methods def app @@ -20,7 +20,7 @@ def app before(:each) do Honeybadger.configure do |config| - config.backend = 'test' + config.backend = "test" end end @@ -30,7 +30,7 @@ def app it "reports exceptions" do Honeybadger.flush do - get '/runtime_error' + get "/runtime_error" expect(last_response.status).to eq(500) end @@ -39,7 +39,7 @@ def app it "includes the exception ID if the user informer magic string is used" do Honeybadger.flush do - get '/runtime_error' + get "/runtime_error" expect(last_response.status).to eq(500) end @@ -50,8 +50,8 @@ def app end it "configures the api key from sinatra config" do - get '/' # Initialize app - expect(Honeybadger.config.get(:api_key)).to eq('gem testing') + get "/" # Initialize app + expect(Honeybadger.config.get(:api_key)).to eq("gem testing") end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 40a494903..e1e53c704 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,34 +1,34 @@ -require 'aruba/rspec' -require 'aruba/api' -require 'fileutils' -require 'logger' -require 'pathname' -require 'rspec/its' -require 'webmock/rspec' +require "aruba/rspec" +require "aruba/api" +require "fileutils" +require "logger" +require "pathname" +require "rspec/its" +require "webmock/rspec" # We don't want this bleeding through in tests. (i.e. from CircleCi) -ENV['RACK_ENV'] = nil -ENV['RAILS_ENV'] = nil +ENV["RACK_ENV"] = nil +ENV["RAILS_ENV"] = nil -require 'honeybadger/ruby' +require "honeybadger/ruby" begin - require 'i18n' + require "i18n" I18n.enforce_available_locales = false rescue LoadError nil end -Dir[File.expand_path('../support/**/*.rb', __FILE__)].each {|f| require f} +Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f } -TMP_DIR = Pathname.new(File.expand_path('../../tmp', __FILE__)) -FIXTURES_PATH = Pathname.new(File.expand_path('../fixtures/', __FILE__)) +TMP_DIR = Pathname.new(File.expand_path("../../tmp", __FILE__)) +FIXTURES_PATH = Pathname.new(File.expand_path("../fixtures/", __FILE__)) NULL_LOGGER = Logger.new(File::NULL) NULL_LOGGER.level = Logger::Severity::DEBUG Aruba.configure do |config| - t = RUBY_PLATFORM == 'java' ? 120 : 12 - config.working_directory = 'tmp/features' + t = (RUBY_PLATFORM == "java") ? 120 : 12 + config.working_directory = "tmp/features" config.exit_timeout = t config.io_wait_timeout = t end @@ -40,7 +40,7 @@ config.run_all_when_everything_filtered = true if config.files_to_run.one? - config.default_formatter = 'doc' + config.default_formatter = "doc" end config.alias_example_group_to :feature, type: :feature @@ -54,14 +54,14 @@ end config.before(:each, type: :feature) do - set_environment_variable('HONEYBADGER_BACKEND', 'debug') - set_environment_variable('HONEYBADGER_LOGGING_PATH', 'STDOUT') + set_environment_variable("HONEYBADGER_BACKEND", "debug") + set_environment_variable("HONEYBADGER_LOGGING_PATH", "STDOUT") end config.include Helpers config.before(:all) do - Honeybadger::Agent.instance = Honeybadger::Agent.new(Honeybadger::Config.new(backend: 'null', logger: NULL_LOGGER)) + Honeybadger::Agent.instance = Honeybadger::Agent.new(Honeybadger::Config.new(backend: "null", logger: NULL_LOGGER)) end config.after(:each) do @@ -71,22 +71,22 @@ begin # Rack is a soft dependency, and so we want to be able to run the test suite # without it. - require 'rack' + require "rack" rescue LoadError - puts 'Excluding specs which depend on Rack.' - config.exclude_pattern = 'spec/unit/honeybadger/rack/*_spec.rb' + puts "Excluding specs which depend on Rack." + config.exclude_pattern = "spec/unit/honeybadger/rack/*_spec.rb" end config.before(:each, framework: :rails) do - FileUtils.cp_r(FIXTURES_PATH.join('rails'), current_dir) - cd('rails') + FileUtils.cp_r(FIXTURES_PATH.join("rails"), current_dir) + cd("rails") end - if ENV['BUNDLE_GEMFILE'] =~ /rails/ + if ENV["BUNDLE_GEMFILE"] =~ /rails/ config.filter_run_excluding framework: ->(v) { !v || v != :rails } - elsif ENV['BUNDLE_GEMFILE'] =~ /sinatra/ + elsif ENV["BUNDLE_GEMFILE"] =~ /sinatra/ config.filter_run_excluding framework: ->(v) { !v || v != :sinatra } - elsif ENV['BUNDLE_GEMFILE'] =~ /rake/ + elsif ENV["BUNDLE_GEMFILE"] =~ /rake/ config.filter_run_excluding framework: ->(v) { !v || v != :rake } else config.filter_run_excluding framework: ->(v) { !v || v != :ruby } diff --git a/spec/support/allocation_stats.rb b/spec/support/allocation_stats.rb index 029a35fa3..0af98a67f 100644 --- a/spec/support/allocation_stats.rb +++ b/spec/support/allocation_stats.rb @@ -1,18 +1,18 @@ skipped = true begin - if ENV['PERF'] - require 'allocation_stats' + if ENV["PERF"] + require "allocation_stats" skipped = false end rescue LoadError nil end -puts 'Skipping AllocationStats.' if skipped +puts "Skipping AllocationStats." if skipped RSpec::Matchers.define :allocate_under do |expected| match do |actual| - return skip('AllocationStats is not available: skipping.') unless defined?(AllocationStats) + return skip("AllocationStats is not available: skipping.") unless defined?(AllocationStats) @trace = actual.is_a?(Proc) ? AllocationStats.trace(&actual) : actual @trace.new_allocations.size < expected end @@ -30,10 +30,10 @@ def output_trace_info(trace) end failure_message do |actual| - "expected under #{ expected } objects to be allocated; got #{ @trace.new_allocations.size }:\n\n" << output_trace_info(@trace) + "expected under #{expected} objects to be allocated; got #{@trace.new_allocations.size}:\n\n" << output_trace_info(@trace) end description do - "allocates under #{ expected } objects" + "allocates under #{expected} objects" end end diff --git a/spec/support/backtraced_exception.rb b/spec/support/backtraced_exception.rb index 50b96b1d2..ea4bd6685 100644 --- a/spec/support/backtraced_exception.rb +++ b/spec/support/backtraced_exception.rb @@ -3,6 +3,7 @@ class BacktracedException < Exception def initialize(opts) @backtrace = opts[:backtrace] end + def set_backtrace(bt) @backtrace = bt end diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb index 1eab03a11..a8045fce1 100644 --- a/spec/support/feature_helpers.rb +++ b/spec/support/feature_helpers.rb @@ -1,7 +1,7 @@ -require 'json' +require "json" module FeatureHelpers - # https://github.com/erikhuda/thor/blob/011dc48b5ea92767445b062f971664235973c8b4/spec/helper.rb#L49 + # https://github.com/erikhuda/thor/blob/011dc48b5ea92767445b062f971664235973c8b4/spec/helper.rb#L49 def capture(stream) begin stream = stream.to_s @@ -21,7 +21,7 @@ def all_output end def current_dir - expand_path('.') + expand_path(".") end def assert_no_notification(output = all_output) @@ -30,14 +30,14 @@ def assert_no_notification(output = all_output) def assert_notification(expected = {}) expect(all_output).to match(/notifying debug backend of feature=notices/) - expect(all_output.scan(/notifying debug backend of feature=notices/).size).to eq 1 - notice = all_output.match(/notifying debug backend of feature=notices\n\t(\{.+\})/) ? JSON.parse($1) : {} + expect(all_output.scan("notifying debug backend of feature=notices").size).to eq 1 + notice = (all_output =~ /notifying debug backend of feature=notices\n\t(\{.+\})/) ? JSON.parse($1) : {} assert_hash_includes(expected, notice) end def assert_hash_includes(expected, actual) - expected.each_pair do |k,v| - if v.kind_of?(Hash) + expected.each_pair do |k, v| + if v.is_a?(Hash) expect(actual[k]).to be_a Hash assert_hash_includes(v, actual[k]) else diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb index a238ba13b..d57bbd8f6 100644 --- a/spec/support/helpers.rb +++ b/spec/support/helpers.rb @@ -1,22 +1,22 @@ module Helpers def stub_http(options = {}) - response = options[:response] || Net::HTTPSuccess.new('1.2', '200', 'OK') + response = options[:response] || Net::HTTPSuccess.new("1.2", "200", "OK") allow(response).to receive(:body).and_return(options[:body] || '{"id":"1234"}') - http = double(:post => response, - :get => response, - :read_timeout= => nil, - :open_timeout= => nil, - :ca_file= => nil, - :verify_mode= => nil, - :use_ssl= => nil) + http = double(:post => response, + :get => response, + :read_timeout= => nil, + :open_timeout= => nil, + :ca_file= => nil, + :verify_mode= => nil, + :use_ssl= => nil) allow(Net::HTTP).to receive(:new).and_return(http) http end def build_exception(opts = {}) backtrace = ["test/honeybadger/rack_test.rb:15:in `build_exception'", - "test/honeybadger/rack_test.rb:52:in `test_delivers_exception_from_rack'", - "/Users/josh/Developer/.rvm/gems/ruby-1.9.3-p0/gems/mocha-0.10.5/lib/mocha/integration/mini_test/version_230_to_262.rb:28:in `run'"] + "test/honeybadger/rack_test.rb:52:in `test_delivers_exception_from_rack'", + "/Users/josh/Developer/.rvm/gems/ruby-1.9.3-p0/gems/mocha-0.10.5/lib/mocha/integration/mini_test/version_230_to_262.rb:28:in `run'"] opts = {backtrace: backtrace}.merge(opts) BacktracedException.new(opts) end diff --git a/spec/unit/honeybadger/agent_spec.rb b/spec/unit/honeybadger/agent_spec.rb index 940c5a219..a97adc750 100644 --- a/spec/unit/honeybadger/agent_spec.rb +++ b/spec/unit/honeybadger/agent_spec.rb @@ -1,9 +1,9 @@ -require 'honeybadger/agent' -require 'honeybadger/events_worker' -require 'timecop' +require "honeybadger/agent" +require "honeybadger/events_worker" +require "timecop" describe Honeybadger::Agent do - NULL_BLOCK = Proc.new{}.freeze + NULL_BLOCK = proc {}.freeze describe "class methods" do subject { described_class } @@ -12,90 +12,90 @@ end describe "#check_in" do - it 'parses check_in id from a url' do - stub_request(:get, "https://api.honeybadger.io/v1/check_in/1MqIo1"). - to_return(status: 200) + it "parses check_in id from a url" do + stub_request(:get, "https://api.honeybadger.io/v1/check_in/1MqIo1") + .to_return(status: 200) - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) - instance.check_in('https://api.honeybadger.io/v1/check_in/1MqIo1') + instance.check_in("https://api.honeybadger.io/v1/check_in/1MqIo1") end - it 'returns true for successful check ins' do - stub_request(:get, "https://api.honeybadger.io/v1/check_in/foobar"). - to_return(status: 200) + it "returns true for successful check ins" do + stub_request(:get, "https://api.honeybadger.io/v1/check_in/foobar") + .to_return(status: 200) - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) - expect(instance.check_in('foobar')).to eq(true) - expect(instance.check_in('/foobar')).to eq(true) - expect(instance.check_in('/foobar/')).to eq(true) + expect(instance.check_in("foobar")).to eq(true) + expect(instance.check_in("/foobar")).to eq(true) + expect(instance.check_in("/foobar/")).to eq(true) end - it 'returns false for failed check ins' do - stub_request(:get, "https://api.honeybadger.io/v1/check_in/danny"). - to_return(status: 400) + it "returns false for failed check ins" do + stub_request(:get, "https://api.honeybadger.io/v1/check_in/danny") + .to_return(status: 400) - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) - expect(instance.check_in('danny')).to eq(false) + expect(instance.check_in("danny")).to eq(false) end end - describe '#track_deployment' do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) } + describe "#track_deployment" do + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) } subject(:instance) { described_class.new(config) } - it 'returns true for successful deployment tracking' do - stub_request(:post, "https://api.honeybadger.io/v1/deploys"). - to_return(status: 200) + it "returns true for successful deployment tracking" do + stub_request(:post, "https://api.honeybadger.io/v1/deploys") + .to_return(status: 200) expect(instance.track_deployment).to eq(true) end - it 'returns false for unsuccessful deployment tracking' do - stub_request(:post, "https://api.honeybadger.io/v1/deploys"). - to_return(status: 400) + it "returns false for unsuccessful deployment tracking" do + stub_request(:post, "https://api.honeybadger.io/v1/deploys") + .to_return(status: 400) expect(instance.track_deployment).to eq(false) end - it 'passes the revision to the servce' do + it "passes the revision to the servce" do allow_any_instance_of(Honeybadger::Util::HTTP).to receive(:compress) { |_, body| body } - stub_request(:post, "https://api.honeybadger.io/v1/deploys"). - with(body: { environment: nil, revision: '1234', local_username: nil, repository: nil }). - to_return(status: 200) + stub_request(:post, "https://api.honeybadger.io/v1/deploys") + .with(body: {environment: nil, revision: "1234", local_username: nil, repository: nil}) + .to_return(status: 200) - expect(instance.track_deployment(revision: '1234')).to eq(true) + expect(instance.track_deployment(revision: "1234")).to eq(true) end end - describe '#context' do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) } + describe "#context" do + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) } subject(:instance) { described_class.new(config) } - it 'sets the context' do + it "sets the context" do instance.context({a: "context"}) expect(instance.get_context).to eq({a: "context"}) end - it 'allows chaining' do + it "allows chaining" do expect(instance.context({a: "context"})).to eq(instance) end - context 'with local context' do - it 'returns the return value of the block' do - expect(instance.context({ bar: :baz }) { :return_value }).to eq(:return_value) + context "with local context" do + it "returns the return value of the block" do + expect(instance.context({bar: :baz}) { :return_value }).to eq(:return_value) end end end describe "#clear!" do - it 'clears all transactional data' do - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + it "clears all transactional data" do + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) instance.context({a: "context"}) instance.add_breadcrumb("Chomp") @@ -109,63 +109,63 @@ describe "#notify" do it "generates a backtrace" do - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) expect(instance.worker).to receive(:push) do |notice| - expect(notice.backtrace.to_a[0]).to match('lib/honeybadger/agent.rb') + expect(notice.backtrace.to_a[0]).to match("lib/honeybadger/agent.rb") end - instance.notify(error_message: 'testing backtrace generation') + instance.notify(error_message: "testing backtrace generation") end it "does not mutate passed in opts" do - opts = {error_message: 'test'} + opts = {error_message: "test"} prev = opts.dup instance = described_class.new(Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER)) - instance.notify('test', opts) + instance.notify("test", opts) expect(prev).to eq(opts) end it "does take keyword arguments" do - opts = {error_message: 'test'} - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + opts = {error_message: "test"} + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) - + expect(instance.worker).to receive(:push) do |notice| - expect(notice.error_message).to match('test') + expect(notice.error_message).to match("test") end instance.notify(**opts) end it "does take keyword arguments as second argument" do - opts = {tags: 'testing, kwargs'} - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + opts = {tags: "testing, kwargs"} + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) - + expect(instance.worker).to receive(:push) do |notice| - expect(notice.error_message).to match('test') - expect(notice.tags).to eq(['testing', 'kwargs']) + expect(notice.error_message).to match("test") + expect(notice.tags).to eq(["testing", "kwargs"]) end - instance.notify('test', **opts) + instance.notify("test", **opts) end it "does take explicit hash as second argument" do - opts = {tags: 'testing, hash'} - config = Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) + opts = {tags: "testing, hash"} + config = Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) instance = described_class.new(config) - + expect(instance.worker).to receive(:push) do |notice| - expect(notice.error_message).to match('test') - expect(notice.tags).to eq(['testing', 'hash']) + expect(notice.error_message).to match("test") + expect(notice.tags).to eq(["testing", "hash"]) end - instance.notify('test', opts) + instance.notify("test", opts) end it "does not report an already reported exception" do instance = described_class.new(Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER)) exception = RuntimeError.new - notice_id = '4g09ko4f' + notice_id = "4g09ko4f" exception.instance_variable_set(:@__hb_notice_id, notice_id) expect(instance.notify(exception)).to be notice_id expect(Honeybadger::Notice).to_not receive(:new) @@ -219,7 +219,7 @@ describe "breadcrumbs" do let(:breadcrumbs) { instance_double(Honeybadger::Breadcrumbs::Collector) } - let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, :'breadcrumbs.enabled' => true) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, "breadcrumbs.enabled": true) } subject { described_class.new(config) } @@ -228,7 +228,7 @@ expect(subject).to receive(:breadcrumbs).and_return(breadcrumbs) expect(subject).to receive(:add_breadcrumb).with( "Honeybadger Notice", - metadata: { error_message: "passed breadcrumbs?" }, + metadata: {error_message: "passed breadcrumbs?"}, category: "notice" ) expect(breadcrumbs).to receive(:dup).and_return(duped_breadcrumbs) @@ -241,7 +241,7 @@ context "breadcrumbs" do let(:breadcrumbs) { instance_double(Honeybadger::Breadcrumbs::Collector, clear!: nil) } - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) } subject { described_class.new(config) } before do @@ -249,22 +249,22 @@ end describe "#breadcrumbs" do - context 'when local_context: true' do - let(:config) { { local_context: true } } + context "when local_context: true" do + let(:config) { {local_context: true} } - it 'creates instance local breadcrumb' do + it "creates instance local breadcrumb" do subject.breadcrumbs expect(Thread.current[:__hb_breadcrumbs]).to be nil end - it 'instantiates the breadcrumb collector with the right config' do + it "instantiates the breadcrumb collector with the right config" do allow(Honeybadger::Breadcrumbs::Collector).to receive(:new).and_call_original subject.breadcrumbs expect(Honeybadger::Breadcrumbs::Collector).to have_received(:new).with(instance_of(Honeybadger::Config)) end end - it 'stores breadcrumbs in thread local' do + it "stores breadcrumbs in thread local" do bc = subject.breadcrumbs expect(Thread.current[:__hb_breadcrumbs]).to eq(bc) end @@ -285,14 +285,14 @@ subject.add_breadcrumb("This is the message", metadata: {a: "b"}, category: "neat") end - it 'has sane defaults' do + it "has sane defaults" do crumb = Honeybadger::Breadcrumbs::Breadcrumb.new(category: "custom", message: "Basic Message", metadata: {}) expect(breadcrumbs).to receive(:add!).with(crumb) subject.add_breadcrumb("Basic Message") end - it 'sanitizes breadcrumb before adding' do + it "sanitizes breadcrumb before adding" do sanitizer = instance_double(Honeybadger::Util::Sanitizer) allow(breadcrumbs).to receive(:add!) expect(Honeybadger::Util::Sanitizer).to receive(:new).with(max_depth: 2).and_return(sanitizer) @@ -305,7 +305,7 @@ end context "#event" do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER, backend: :debug) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, backend: :debug) } let(:events_worker) { double(Honeybadger::EventsWorker.new(config)) } let(:instance) { Honeybadger::Agent.new(config) } @@ -349,8 +349,8 @@ end describe "ignoring events using events.ignore config" do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER, backend: :debug, :'events.ignore' => ignored_events) } - let(:payload) { { some_data: "is here" } } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, backend: :debug, "events.ignore": ignored_events) } + let(:payload) { {some_data: "is here"} } after { subject.event(payload.merge(event_type: event_type)) } @@ -400,7 +400,7 @@ end context "when configured with a hash" do - let(:ignored_events) { [{ "event_type" => "report.system" }] } + let(:ignored_events) { [{"event_type" => "report.system"}] } let(:event_type) { "report.system" } it "does not push an event" do @@ -409,9 +409,9 @@ end context "when configured with a hash with a nested payload" do - let(:ignored_events) { [{ "nested" => { "data" => "test" }}] } + let(:ignored_events) { [{"nested" => {"data" => "test"}}] } let(:event_type) { "report.system" } - let(:payload) { { nested: { data: "test" }} } + let(:payload) { {nested: {data: "test"}} } it "does not push an event" do expect(events_worker).not_to receive(:push) @@ -419,9 +419,9 @@ end context "when configured with a hash with string keys" do - let(:ignored_events) { [{ "nested" => { "data" => "test" }}] } + let(:ignored_events) { [{"nested" => {"data" => "test"}}] } let(:event_type) { "report.system" } - let(:payload) { { nested: { "data" => "test" }} } + let(:payload) { {nested: {"data" => "test"}} } it "does push an event" do expect(events_worker).to receive(:push) @@ -431,7 +431,7 @@ context "by default ignores Rails::HealthController" do let(:ignored_events) { [] } let(:event_type) { "process_action.action_controller" } - let(:payload) { { controller: "Rails::HealthController" } } + let(:payload) { {controller: "Rails::HealthController"} } it "does not push an event" do expect(events_worker).not_to receive(:push) @@ -441,7 +441,7 @@ context "by default ignores active record BEGIN events" do let(:ignored_events) { [] } let(:event_type) { "sql.active_record" } - let(:payload) { { query: "BEGIN" } } + let(:payload) { {query: "BEGIN"} } it "does not push an event" do expect(events_worker).not_to receive(:push) @@ -451,7 +451,7 @@ context "by default ignores active record COMMIT events" do let(:ignored_events) { [] } let(:event_type) { "sql.active_record" } - let(:payload) { { query: "COMMIT" } } + let(:payload) { {query: "COMMIT"} } it "does not push an event" do expect(events_worker).not_to receive(:push) @@ -461,7 +461,7 @@ context "by default ignores solid_queue processor sql events" do let(:ignored_events) { [] } let(:event_type) { "sql.active_record" } - let(:payload) { { query: 'UPDATE "solid_queue_processes" SET "last_heartbeat_at" = ? WHERE "solid_queue_processes"."id" = ?' } } + let(:payload) { {query: 'UPDATE "solid_queue_processes" SET "last_heartbeat_at" = ? WHERE "solid_queue_processes"."id" = ?'} } it "does not push an event" do expect(events_worker).not_to receive(:push) @@ -471,7 +471,7 @@ context "by default ignores good_job processor sql events" do let(:ignored_events) { [] } let(:event_type) { "sql.active_record" } - let(:payload) { { query: 'SELECT * FROM "good_jobs"' } } + let(:payload) { {query: 'SELECT * FROM "good_jobs"'} } it "does not push an event" do expect(events_worker).not_to receive(:push) @@ -479,10 +479,10 @@ end context "override default ignores" do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER, backend: :debug, :'events.ignore_only' => ignore_only) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, backend: :debug, "events.ignore_only": ignore_only) } let(:ignore_only) { [] } let(:event_type) { "sql.active_record" } - let(:payload) { { query: "COMMIT" } } + let(:payload) { {query: "COMMIT"} } it "does not push an event" do expect(events_worker).to receive(:push) @@ -492,7 +492,7 @@ end context "#collect" do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER, debug: true, :'insights.enabled' => true) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, debug: true, "insights.enabled": true) } let(:metrics_worker) { double(Honeybadger::MetricsWorker.new(config)) } let(:instance) { Honeybadger::Agent.new(config) } let(:collection_execution) { double(Honeybadger::Plugin::CollectorExecution) } @@ -547,7 +547,7 @@ end context "when no block is given" do - let(:block) { Proc.new { expecting.call } } + let(:block) { proc { expecting.call } } let(:expecting) { double(call: true) } it { should eq true } @@ -564,11 +564,11 @@ end context "when an exception occurs" do - let(:block) { Proc.new { fail 'oops' } } + let(:block) { proc { fail "oops" } } it "flushes worker" do expect(instance.worker).to receive(:flush) - expect { subject }.to raise_error /oops/ + expect { subject }.to raise_error(/oops/) end end end diff --git a/spec/unit/honeybadger/backend/base_spec.rb b/spec/unit/honeybadger/backend/base_spec.rb index 582bd9ef3..8a062371a 100644 --- a/spec/unit/honeybadger/backend/base_spec.rb +++ b/spec/unit/honeybadger/backend/base_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/backend/base' -require 'honeybadger/config' +require "honeybadger/backend/base" +require "honeybadger/config" describe Honeybadger::Backend::Response do context "when successful" do @@ -47,7 +47,7 @@ describe "#notify" do it "raises NotImplementedError" do - expect { subject.notify(:notices, double('Notice')) }.to raise_error NotImplementedError + expect { subject.notify(:notices, double("Notice")) }.to raise_error NotImplementedError end end diff --git a/spec/unit/honeybadger/backend/debug_spec.rb b/spec/unit/honeybadger/backend/debug_spec.rb index 675649303..637376291 100644 --- a/spec/unit/honeybadger/backend/debug_spec.rb +++ b/spec/unit/honeybadger/backend/debug_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/backend/debug' -require 'honeybadger/config' +require "honeybadger/backend/debug" +require "honeybadger/config" describe Honeybadger::Backend::Debug do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } @@ -17,7 +17,7 @@ it { should respond_to :notify } describe "#notify" do - let(:notice) { double('Notice', to_json: '{}') } + let(:notice) { double("Notice", to_json: "{}") } subject { instance.notify(:notices, notice) } @@ -32,7 +32,7 @@ describe "#check_in" do it "logs the check_in" do expect(logger).to receive(:unknown).with("checking in debug backend with id=10") - + instance.check_in(10) end end diff --git a/spec/unit/honeybadger/backend/null_spec.rb b/spec/unit/honeybadger/backend/null_spec.rb index fa11a21c9..175a22471 100644 --- a/spec/unit/honeybadger/backend/null_spec.rb +++ b/spec/unit/honeybadger/backend/null_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/backend/null' -require 'honeybadger/config' +require "honeybadger/backend/null" +require "honeybadger/config" describe Honeybadger::Backend::Null do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER) } @@ -12,8 +12,8 @@ it { should respond_to :notify } describe "#notify" do - subject { instance.notify(:notices, double('Notice')) } - + subject { instance.notify(:notices, double("Notice")) } + it { should be_a Honeybadger::Backend::Response } end @@ -23,4 +23,3 @@ it { should be_a Honeybadger::Backend::Response } end end - diff --git a/spec/unit/honeybadger/backend/server_spec.rb b/spec/unit/honeybadger/backend/server_spec.rb index b71c58051..268dcb9f7 100644 --- a/spec/unit/honeybadger/backend/server_spec.rb +++ b/spec/unit/honeybadger/backend/server_spec.rb @@ -1,11 +1,11 @@ -require 'logger' -require 'honeybadger/backend/server' -require 'honeybadger/config' +require "logger" +require "honeybadger/backend/server" +require "honeybadger/config" describe Honeybadger::Backend::Server do - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, api_key: 'abc123') } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, api_key: "abc123") } let(:logger) { config.logger } - let(:payload) { double('Notice', to_json: '{}') } + let(:payload) { double("Notice", to_json: "{}") } subject { described_class.new(config) } @@ -16,7 +16,7 @@ describe "#check_in" do it "returns a response" do stub_http - expect(subject.check_in('foobar')).to be_a Honeybadger::Backend::Response + expect(subject.check_in("foobar")).to be_a Honeybadger::Backend::Response end end @@ -28,12 +28,12 @@ context "when payload has an api key" do before do - allow(payload).to receive(:api_key).and_return('badgers') + allow(payload).to receive(:api_key).and_return("badgers") end it "passes the payload api key in extra headers" do http = stub_http - expect(http).to receive(:post).with(anything, anything, hash_including({ 'X-API-Key' => 'badgers'})) + expect(http).to receive(:post).with(anything, anything, hash_including({"X-API-Key" => "badgers"})) notify_backend end end @@ -41,7 +41,7 @@ context "when payload doesn't have an api key" do it "doesn't pass extra headers" do http = stub_http - expect(http).to receive(:post).with(anything, anything, hash_including({ 'X-API-Key' => 'abc123'})) + expect(http).to receive(:post).with(anything, anything, hash_including({"X-API-Key" => "abc123"})) notify_backend end end @@ -49,7 +49,7 @@ context "when encountering exceptions" do context "HTTP connection setup problems" do it "should not be rescued" do - proxy = double() + proxy = double allow(proxy).to receive(:new).and_raise(NoMemoryError) allow(Net::HTTP).to receive(:Proxy).and_return(proxy) expect { notify_backend }.to raise_error(NoMemoryError) @@ -90,7 +90,7 @@ def notify_backend it "adds auth headers" do http = stub_http - expect(http).to receive(:post).with(anything, anything, hash_including({ 'X-API-Key' => 'abc123'})) + expect(http).to receive(:post).with(anything, anything, hash_including({"X-API-Key" => "abc123"})) send_event end @@ -123,9 +123,9 @@ def notify_backend send_event(2) end - def send_event(count=1) + def send_event(count = 1) payload = [] - count.times {|i| payload << {ts: DateTime.now.new_offset(0).rfc3339, event_type: "checkout", sum: "123.23", increment: i} } + count.times { |i| payload << {ts: DateTime.now.new_offset(0).rfc3339, event_type: "checkout", sum: "123.23", increment: i} } subject.event(payload) end end diff --git a/spec/unit/honeybadger/backend/test_spec.rb b/spec/unit/honeybadger/backend/test_spec.rb index d99e42ab3..063082fd2 100644 --- a/spec/unit/honeybadger/backend/test_spec.rb +++ b/spec/unit/honeybadger/backend/test_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/backend/test' -require 'honeybadger/config' +require "honeybadger/backend/test" +require "honeybadger/config" describe Honeybadger::Backend::Test do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER) } @@ -25,9 +25,9 @@ end describe "#notify" do - let(:notice) { double('Notice') } + let(:notice) { double("Notice") } - subject { instance.notify(:notices, double('Notice')) } + subject { instance.notify(:notices, double("Notice")) } it "saves notifications for review" do expect { instance.notify(:notices, notice) }.to change { instance.notifications[:notices] }.from([]).to([notice]) diff --git a/spec/unit/honeybadger/backtrace_spec.rb b/spec/unit/honeybadger/backtrace_spec.rb index f006c39d0..83fab6c3e 100644 --- a/spec/unit/honeybadger/backtrace_spec.rb +++ b/spec/unit/honeybadger/backtrace_spec.rb @@ -1,7 +1,7 @@ -require 'stringio' -require 'honeybadger/backtrace' -require 'honeybadger/config' -require 'honeybadger/notice' +require "stringio" +require "honeybadger/backtrace" +require "honeybadger/config" +require "honeybadger/notice" describe Honeybadger::Backtrace do let(:config) { Honeybadger::Config.new } @@ -15,14 +15,14 @@ backtrace = Honeybadger::Backtrace.parse(array) line = backtrace.lines.first - expect(line.number).to eq '13' - expect(line.file).to eq 'app/models/user.rb' - expect(line.method).to eq 'magic' + expect(line.number).to eq "13" + expect(line.file).to eq "app/models/user.rb" + expect(line.method).to eq "magic" line = backtrace.lines.last - expect(line.number).to eq '8' - expect(line.file).to eq 'app/controllers/users_controller.rb' - expect(line.method).to eq 'index' + expect(line.number).to eq "8" + expect(line.file).to eq "app/controllers/users_controller.rb" + expect(line.method).to eq "index" end it "parses a windows backtrace into lines" do @@ -34,14 +34,14 @@ backtrace = Honeybadger::Backtrace.parse(array) line = backtrace.lines.first - expect(line.number).to eq '13' - expect(line.file).to eq 'C:/Program Files/Server/app/models/user.rb' - expect(line.method).to eq 'magic' + expect(line.number).to eq "13" + expect(line.file).to eq "C:/Program Files/Server/app/models/user.rb" + expect(line.method).to eq "magic" line = backtrace.lines.last - expect(line.number).to eq '8' - expect(line.file).to eq 'C:/Program Files/Server/app/controllers/users_controller.rb' - expect(line.method).to eq 'index' + expect(line.number).to eq "8" + expect(line.file).to eq "C:/Program Files/Server/app/controllers/users_controller.rb" + expect(line.method).to eq "index" end it "infers types from backtace lines" do @@ -49,12 +49,12 @@ double(to_s: "app/models/user.rb:13:in `magic'"), double(to_s: "app/controllers/users_controller.rb:8:in `index'") ]) - backtrace = Honeybadger::Backtrace.parse(array_thing, filters: [lambda {|l| l.sub('foo', 'bar') }]) + backtrace = Honeybadger::Backtrace.parse(array_thing, filters: [lambda { |l| l.sub("foo", "bar") }]) line = backtrace.lines.first - expect(line.number).to eq '13' - expect(line.file).to eq 'app/models/user.rb' - expect(line.method).to eq 'magic' + expect(line.number).to eq "13" + expect(line.file).to eq "app/models/user.rb" + expect(line.method).to eq "magic" end it "is equal with equal lines" do @@ -65,10 +65,10 @@ end it "parses massive one-line exceptions into multiple lines" do - original_backtrace = Honeybadger::Backtrace. - parse(["one:1:in `one'\n two:2:in `two'\n three:3:in `three`"]) - expected_backtrace = Honeybadger::Backtrace. - parse(["one:1:in `one'", "two:2:in `two'", "three:3:in `three`"]) + original_backtrace = Honeybadger::Backtrace + .parse(["one:1:in `one'\n two:2:in `two'\n three:3:in `three`"]) + expected_backtrace = Honeybadger::Backtrace + .parse(["one:1:in `one'", "two:2:in `two'", "three:3:in `three`"]) expect(expected_backtrace).to eq original_backtrace end @@ -92,7 +92,7 @@ "app/controllers/users_controller.rb:8:in `index'" ] - ['app/models/user.rb', 'app/concerns/authenticated_controller.rb', 'app/controllers/users_controller.rb'].each do |file| + ["app/models/user.rb", "app/concerns/authenticated_controller.rb", "app/controllers/users_controller.rb"].each do |file| expect(File).to receive(:exist?).with(file).and_return(true) expect(File).to receive(:open).with(file).and_yield(StringIO.new(source)) end @@ -140,20 +140,22 @@ context "with a project root" do before(:each) do - @project_root = '/some/path' + @project_root = "/some/path" config[:root] = @project_root @backtrace_with_root = Honeybadger::Backtrace.parse( ["#{@project_root}/app/models/user.rb:7:in `latest'", - "#{@project_root}/app/controllers/users_controller.rb:13:in `index'", - "#{@project_root}/vendor/plugins/foo/bar.rb:42:in `baz'", - "/lib/something.rb:41:in `open'"], - :filters => default_filters, :config => config) + "#{@project_root}/app/controllers/users_controller.rb:13:in `index'", + "#{@project_root}/vendor/plugins/foo/bar.rb:42:in `baz'", + "/lib/something.rb:41:in `open'"], + filters: default_filters, config: config + ) @backtrace_without_root = Honeybadger::Backtrace.parse( ["[PROJECT_ROOT]/app/models/user.rb:7:in `latest'", - "[PROJECT_ROOT]/app/controllers/users_controller.rb:13:in `index'", - "[PROJECT_ROOT]/vendor/plugins/foo/bar.rb:42:in `baz'", - "/lib/something.rb:41:in `open'"]) + "[PROJECT_ROOT]/app/controllers/users_controller.rb:13:in `index'", + "[PROJECT_ROOT]/vendor/plugins/foo/bar.rb:42:in `baz'", + "/lib/something.rb:41:in `open'"] + ) end it "filters out the project root" do @@ -172,37 +174,39 @@ context "with a project root equals to a part of file name" do before(:each) do # Heroku-like - @project_root = '/app' + @project_root = "/app" config[:root] = @project_root end it "filters out the project root" do backtrace_with_root = Honeybadger::Backtrace.parse( ["#{@project_root}/app/models/user.rb:7:in `latest'", - "#{@project_root}/app/controllers/users_controller.rb:13:in `index'", - "/lib/app/something.rb:41:in `open'"], - :filters => default_filters, :config => config) - backtrace_without_root = Honeybadger::Backtrace.parse( - ["[PROJECT_ROOT]/app/models/user.rb:7:in `latest'", - "[PROJECT_ROOT]/app/controllers/users_controller.rb:13:in `index'", - "/lib/app/something.rb:41:in `open'"]) - - expect(backtrace_without_root).to eq backtrace_with_root + "#{@project_root}/app/controllers/users_controller.rb:13:in `index'", + "/lib/app/something.rb:41:in `open'"], + filters: default_filters, config: config + ) + backtrace_without_root = Honeybadger::Backtrace.parse( + ["[PROJECT_ROOT]/app/models/user.rb:7:in `latest'", + "[PROJECT_ROOT]/app/controllers/users_controller.rb:13:in `index'", + "/lib/app/something.rb:41:in `open'"] + ) + + expect(backtrace_without_root).to eq backtrace_with_root end end context "with a blank project root" do before(:each) do - config[:root] = '' + config[:root] = "" end it "does not filter line numbers with respect to any project root" do backtrace = ["/app/models/user.rb:7:in `latest'", - "/app/controllers/users_controller.rb:13:in `index'", - "/lib/something.rb:41:in `open'"] + "/app/controllers/users_controller.rb:13:in `index'", + "/lib/something.rb:41:in `open'"] backtrace_with_root = - Honeybadger::Backtrace.parse(backtrace, :filters => default_filters, :config => config) + Honeybadger::Backtrace.parse(backtrace, filters: default_filters, config: config) backtrace_without_root = Honeybadger::Backtrace.parse(backtrace) @@ -212,20 +216,20 @@ end it "removes notifier trace" do - inside_notifier = ['lib/honeybadger.rb:13:in `voodoo`'] - outside_notifier = ['users_controller:8:in `index`'] + inside_notifier = ["lib/honeybadger.rb:13:in `voodoo`"] + outside_notifier = ["users_controller:8:in `index`"] without_inside = Honeybadger::Backtrace.parse(outside_notifier) - with_inside = Honeybadger::Backtrace.parse(inside_notifier + outside_notifier, - :filters => default_filters) + with_inside = Honeybadger::Backtrace.parse(inside_notifier + outside_notifier, + filters: default_filters) expect(without_inside).to eq with_inside end it "runs filters on the backtrace" do - filters = [lambda { |line| line.sub('foo', 'bar') }] + filters = [lambda { |line| line.sub("foo", "bar") }] input = Honeybadger::Backtrace.parse(["foo:13:in `one'", "baz:14:in `two'"], - :filters => filters) + filters: filters) expected = Honeybadger::Backtrace.parse(["bar:13:in `one'", "baz:14:in `two'"]) expect(expected).to eq input end @@ -238,7 +242,7 @@ it "generates json from to_array template" do backtrace = Honeybadger::Backtrace.parse(build_backtrace_array) - array = [{'foo' => 'bar'}] + array = [{"foo" => "bar"}] expect(backtrace).to receive(:to_ary).once.and_return(array) json = backtrace.to_json @@ -250,7 +254,7 @@ def build_backtrace_array ["app/models/user.rb:13:in `magic'", - "app/controllers/users_controller.rb:8:in `index'"] + "app/controllers/users_controller.rb:8:in `index'"] end def default_filters diff --git a/spec/unit/honeybadger/breadcrumbs/breadcrumb_spec.rb b/spec/unit/honeybadger/breadcrumbs/breadcrumb_spec.rb index 3b42ee9ec..db5be4452 100644 --- a/spec/unit/honeybadger/breadcrumbs/breadcrumb_spec.rb +++ b/spec/unit/honeybadger/breadcrumbs/breadcrumb_spec.rb @@ -1,10 +1,10 @@ -require 'timecop' -require 'honeybadger/breadcrumbs/ring_buffer' +require "timecop" +require "honeybadger/breadcrumbs/ring_buffer" describe Honeybadger::Breadcrumbs::Breadcrumb do let(:category) { :test } let(:message) { "A test message" } - let(:metadata) {{ a: "foo" }} + let(:metadata) { {a: "foo"} } subject { described_class.new(category: category, message: message, metadata: metadata) } @@ -28,7 +28,7 @@ end describe "#comparable" do - it 'can be compared on hash content' do + it "can be compared on hash content" do expect(subject == subject.dup).to be(true) end end diff --git a/spec/unit/honeybadger/breadcrumbs/collector_spec.rb b/spec/unit/honeybadger/breadcrumbs/collector_spec.rb index e6e220851..97670b598 100644 --- a/spec/unit/honeybadger/breadcrumbs/collector_spec.rb +++ b/spec/unit/honeybadger/breadcrumbs/collector_spec.rb @@ -1,24 +1,23 @@ -require 'honeybadger/breadcrumbs/breadcrumb' -require 'honeybadger/breadcrumbs/collector' +require "honeybadger/breadcrumbs/breadcrumb" +require "honeybadger/breadcrumbs/collector" describe Honeybadger::Breadcrumbs::Collector do let(:buffer) { double("Buffer") } - let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, :'breadcrumbs.enabled' => true) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, "breadcrumbs.enabled": true) } subject { described_class.new(config, buffer) } - context 'buffer delegation' do - it '#clear!' do + context "buffer delegation" do + it "#clear!" do expect(buffer).to receive(:clear!) subject.clear! end - it '#each' do + it "#each" do expect(buffer).to receive(:each) subject.each end end - describe "#add!" do it "delegates to " do crumb = double("Crumb") @@ -27,9 +26,9 @@ end context "breadcrumbs disabled in config" do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER, :'breadcrumbs.enabled' => false) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER, "breadcrumbs.enabled": false) } - it 'does not call buffer' do + it "does not call buffer" do crumb = double("Crumb") expect(buffer).to_not receive(:add!) subject.add!(crumb) @@ -38,13 +37,13 @@ end describe "#<<" do - it 'delegates to add!' do + it "delegates to add!" do expect(subject.method(:<<)).to eq(subject.method(:add!)) end end describe "#drop_previous_breadcrumb_if" do - it 'calls drop on buffer if block returns truthy' do + it "calls drop on buffer if block returns truthy" do crumb = double("Crumb") expect(subject).to receive(:previous).twice.and_return(crumb) expect(buffer).to receive(:drop) @@ -54,14 +53,14 @@ end end - it 'does not call drop on buffer if block returns falsey' do + it "does not call drop on buffer if block returns falsey" do crumb = double("Crumb") expect(subject).to receive(:previous).twice.and_return(crumb) expect(buffer).to_not receive(:drop) subject.drop_previous_breadcrumb_if { |c| false } end - it 'does not call drop on buffer if buffer is empty' do + it "does not call drop on buffer if buffer is empty" do expect(subject).to receive(:previous).and_return(nil) expect(buffer).to_not receive(:drop) subject.drop_previous_breadcrumb_if { |c| true } @@ -73,28 +72,30 @@ allow(subject).to receive(:trail).and_return([]) end - it 'contains trail summary' do + it "contains trail summary" do trail = [buffer] expect(buffer).to receive(:to_h).and_return({test: "buffer"}) expect(subject).to receive(:trail).and_return(trail) - expect(subject.to_h).to match(hash_including({ trail: [{test: "buffer"}] })) + expect(subject.to_h).to match(hash_including({trail: [{test: "buffer"}]})) end - it 'works with empty trail' do - expect(subject.to_h).to match(hash_including({ trail: [] })) + it "works with empty trail" do + expect(subject.to_h).to match(hash_including({trail: []})) end - it 'contains enabled flag' do - expect(subject.to_h).to match(hash_including({ enabled: true })) + it "contains enabled flag" do + expect(subject.to_h).to match(hash_including({enabled: true})) end end describe "#trail" do let(:active_breadcrumb) { instance_double(Honeybadger::Breadcrumbs::Breadcrumb, active?: true) } - let(:buffer) {[ - instance_double(Honeybadger::Breadcrumbs::Breadcrumb, active?: false), - active_breadcrumb, - ]} + let(:buffer) { + [ + instance_double(Honeybadger::Breadcrumbs::Breadcrumb, active?: false), + active_breadcrumb + ] + } it "only returns active breadcrumbs" do expect(subject.trail.length).to eq(1) diff --git a/spec/unit/honeybadger/breadcrumbs/log_subscriber_injector_spec.rb b/spec/unit/honeybadger/breadcrumbs/log_subscriber_injector_spec.rb index 3c1db5351..04bcc0743 100644 --- a/spec/unit/honeybadger/breadcrumbs/log_subscriber_injector_spec.rb +++ b/spec/unit/honeybadger/breadcrumbs/log_subscriber_injector_spec.rb @@ -1,7 +1,7 @@ -require 'honeybadger/breadcrumbs/logging' +require "honeybadger/breadcrumbs/logging" describe Honeybadger::Breadcrumbs::LogSubscriberInjector do - LOGGING_LEVELS = %w(info debug warn error fatal unknown) + LOGGING_LEVELS = %w[info debug warn error fatal unknown] let(:logger) do Class.new do diff --git a/spec/unit/honeybadger/breadcrumbs/logging_spec.rb b/spec/unit/honeybadger/breadcrumbs/logging_spec.rb index a9bab5c40..a5f22c976 100644 --- a/spec/unit/honeybadger/breadcrumbs/logging_spec.rb +++ b/spec/unit/honeybadger/breadcrumbs/logging_spec.rb @@ -1,4 +1,4 @@ -require 'honeybadger/breadcrumbs/logging' +require "honeybadger/breadcrumbs/logging" describe Honeybadger::Breadcrumbs::LogWrapper do let(:logger) do @@ -21,41 +21,41 @@ def format_severity(str) subject { logger.new } - it 'adds a breadcrumb' do + it "adds a breadcrumb" do expect(subject).to receive(:format_severity).and_return("debug") expect(Honeybadger).to receive(:add_breadcrumb).with("Message", hash_including(category: :log, metadata: hash_including(severity: "debug", progname: "none"))) subject.add("test", "Message", "none") end - it 'handles non-string objects' do + it "handles non-string objects" do expect(Honeybadger).to receive(:add_breadcrumb).with("{}", anything) subject.add("DEBUG", {}) end - it 'does not mutate the message' do - subject.add("DEBUG", {}, 'Honeybadger') - expect(subject.severity).to eq('DEBUG') + it "does not mutate the message" do + subject.add("DEBUG", {}, "Honeybadger") + expect(subject.severity).to eq("DEBUG") expect(subject.message).to eq({}) - expect(subject.progname).to eq('Honeybadger') + expect(subject.progname).to eq("Honeybadger") end describe "ignores messages on" do before { expect(Honeybadger).to_not receive(:add_breadcrumb) } - it 'nil message' do + it "nil message" do subject.add("test", nil) end - it 'empty string' do + it "empty string" do subject.add("test", "") end - it 'honeybadger progname' do + it "honeybadger progname" do subject.add("test", "noop", "honeybadger") end - it 'within log_subscriber call' do + it "within log_subscriber call" do Thread.current[:__hb_within_log_subscriber] = true subject.add("test", "a message") Thread.current[:__hb_within_log_subscriber] = false diff --git a/spec/unit/honeybadger/breadcrumbs/ring_buffer_spec.rb b/spec/unit/honeybadger/breadcrumbs/ring_buffer_spec.rb index d63fcec8f..277f7de29 100644 --- a/spec/unit/honeybadger/breadcrumbs/ring_buffer_spec.rb +++ b/spec/unit/honeybadger/breadcrumbs/ring_buffer_spec.rb @@ -1,13 +1,13 @@ -require 'honeybadger/breadcrumbs/ring_buffer' +require "honeybadger/breadcrumbs/ring_buffer" describe Honeybadger::Breadcrumbs::RingBuffer do describe "#add" do - it 'adds items' do + it "adds items" do subject.add!(:a) expect(subject.buffer).to eq([:a]) end - it 'shifts when size limit is hit' do + it "shifts when size limit is hit" do buffer = described_class.new(2) buffer.add!(:a) buffer.add!(:b) @@ -18,7 +18,7 @@ end describe "#clear" do - it 'clears data' do + it "clears data" do subject.add!(:a) subject.clear! expect(subject.buffer).to be_empty @@ -34,7 +34,7 @@ end describe "#drop" do - it 'removes the last inserted item' do + it "removes the last inserted item" do subject.add!(:a) subject.add!(:b) subject.drop @@ -43,7 +43,7 @@ end describe "#previous" do - it 'returns the last inserted item' do + it "returns the last inserted item" do subject.add!(:a) subject.add!(:b) expect(subject.previous).to eq(:b) diff --git a/spec/unit/honeybadger/config/env_spec.rb b/spec/unit/honeybadger/config/env_spec.rb index fbd2717f7..692fe7cda 100644 --- a/spec/unit/honeybadger/config/env_spec.rb +++ b/spec/unit/honeybadger/config/env_spec.rb @@ -1,4 +1,4 @@ -require 'honeybadger/config' +require "honeybadger/config" describe Honeybadger::Config::Env do subject { described_class.new(env) } @@ -6,34 +6,34 @@ let(:env) { {} } before do - env['HONEYBADGER_API_KEY'] = 'asdf' - env['HONEYBADGER_EXCEPTIONS_ENABLED'] = 'false' - env['HONEYBADGER_ENV'] = 'production' - env['HONEYBADGER_LOGGING_PATH'] = 'log/' - env['HONEYBADGER_EXCEPTIONS_IGNORE'] = 'Foo, Bar, Baz' + env["HONEYBADGER_API_KEY"] = "asdf" + env["HONEYBADGER_EXCEPTIONS_ENABLED"] = "false" + env["HONEYBADGER_ENV"] = "production" + env["HONEYBADGER_LOGGING_PATH"] = "log/" + env["HONEYBADGER_EXCEPTIONS_IGNORE"] = "Foo, Bar, Baz" end it { should be_a Hash } - specify { expect(subject[:api_key]).to eq 'asdf' } - specify { expect(subject[:env]).to eq 'production' } - specify { expect(subject[:'logging.path']).to eq 'log/' } - specify { expect(subject[:'exceptions.ignore']).to eq ['Foo', 'Bar', 'Baz'] } - specify { expect(subject[:'exceptions.enabled']).to eq false } + specify { expect(subject[:api_key]).to eq "asdf" } + specify { expect(subject[:env]).to eq "production" } + specify { expect(subject[:"logging.path"]).to eq "log/" } + specify { expect(subject[:"exceptions.ignore"]).to eq ["Foo", "Bar", "Baz"] } + specify { expect(subject[:"exceptions.enabled"]).to eq false } context "with invalid options" do before do - env['HONEYBADGER_BAD_OPTION'] = 'log/' + env["HONEYBADGER_BAD_OPTION"] = "log/" end - specify { expect(subject).not_to have_key(:'bad_option') } + specify { expect(subject).not_to have_key(:bad_option) } end context "with ignorable type" do before do - env['HONEYBADGER_BREADCRUMBS_ACTIVE_SUPPORT_NOTIFICATIONS'] = '{}' + env["HONEYBADGER_BREADCRUMBS_ACTIVE_SUPPORT_NOTIFICATIONS"] = "{}" end - specify { expect(subject).not_to have_key(:'breadcrumbs.active_support_notifications') } + specify { expect(subject).not_to have_key(:"breadcrumbs.active_support_notifications") } end end diff --git a/spec/unit/honeybadger/config/ruby_spec.rb b/spec/unit/honeybadger/config/ruby_spec.rb index 184ad6f94..2e52a2b29 100644 --- a/spec/unit/honeybadger/config/ruby_spec.rb +++ b/spec/unit/honeybadger/config/ruby_spec.rb @@ -1,43 +1,43 @@ -require 'honeybadger/config' +require "honeybadger/config" describe Honeybadger::Config::Ruby do subject { described_class.new(config) } - let(:config) { Honeybadger::Config.new(api_key: 'foo', :'user_informer.enabled' => true) } + let(:config) { Honeybadger::Config.new(api_key: "foo", "user_informer.enabled": true) } it { should respond_to(:api_key) } it "returns config values" do - expect(subject.api_key).to eq('foo') + expect(subject.api_key).to eq("foo") expect(subject.user_informer.enabled).to eq(true) end it "returns config local values first" do - subject.api_key = 'bar' + subject.api_key = "bar" subject.user_informer.enabled = false - expect(subject.api_key).to eq('bar') + expect(subject.api_key).to eq("bar") expect(subject.user_informer.enabled).to eq(false) end it "converts config values to dotted Hash keys" do - subject.api_key = 'bar' + subject.api_key = "bar" subject.user_informer.enabled = false expect(subject.to_hash).to eq({ - :api_key => 'bar', - :'user_informer.enabled' => false + api_key: "bar", + "user_informer.enabled": false }) end it "doesn't respond to invalid methods" do - expect { subject.foo = 'bar' }.to raise_error(NoMethodError) + expect { subject.foo = "bar" }.to raise_error(NoMethodError) expect { subject.foo }.to raise_error(NoMethodError) end describe "#logger=" do it "assigns the logger to the Hash" do - logger = double() + logger = double subject.logger = logger expect(subject.to_hash).to eq({ logger: logger @@ -47,7 +47,7 @@ describe "#logger" do it "returns the assigned logger" do - logger = double() + logger = double subject.logger = logger expect(subject.logger).to eq(logger) end @@ -55,7 +55,7 @@ describe "#backend=" do it "assigns the logger to the Hash" do - backend = double() + backend = double subject.backend = backend expect(subject.to_hash).to eq({ backend: backend @@ -65,7 +65,7 @@ describe "#backend" do it "returns the assigned backend" do - backend = double() + backend = double subject.backend = backend expect(subject.backend).to eq(backend) end @@ -73,7 +73,7 @@ describe "#backtrace_filter" do it "assigns the backtrace_filter" do - block = ->{} + block = -> {} subject.backtrace_filter(&block) expect(subject.to_hash).to eq({ backtrace_filter: block @@ -108,8 +108,8 @@ end it "configures multiple hooks" do - subject.before_notify {|n| n } - subject.before_notify {|n| n } + subject.before_notify { |n| n } + subject.before_notify { |n| n } expect(subject.before_notify.size).to eq(2) end @@ -117,7 +117,7 @@ describe "#exception_filter" do it "assigns the exception_filter" do - block = ->{} + block = -> {} subject.exception_filter(&block) expect(subject.to_hash).to eq({ exception_filter: block @@ -127,7 +127,7 @@ describe "#exception_fingerprint" do it "assigns the exception_fingerprint" do - block = ->{} + block = -> {} subject.exception_fingerprint(&block) expect(subject.to_hash).to eq({ exception_fingerprint: block diff --git a/spec/unit/honeybadger/config/yaml_spec.rb b/spec/unit/honeybadger/config/yaml_spec.rb index 7f3c2e908..6d0e01e51 100644 --- a/spec/unit/honeybadger/config/yaml_spec.rb +++ b/spec/unit/honeybadger/config/yaml_spec.rb @@ -1,40 +1,40 @@ -require 'honeybadger/config' +require "honeybadger/config" describe Honeybadger::Config::Yaml do subject { described_class.new(path, env) } - let(:path) { FIXTURES_PATH.join('honeybadger.yml') } - let(:env) { 'production' } + let(:path) { FIXTURES_PATH.join("honeybadger.yml") } + let(:env) { "production" } it { should be_a Hash } context "when options are nested" do it "converts deeply nested options to dotted hash syntax" do - expect(subject[:'a.really.deeply.nested']).to eq 'option' + expect(subject[:"a.really.deeply.nested"]).to eq "option" end end context "when an environment namespace is present" do it "prioritizes the namespace" do - expect(subject[:api_key]).to eq 'asdf' + expect(subject[:api_key]).to eq "asdf" end context "and the environment collides with an option name" do - let(:env) { 'api_key' } + let(:env) { "api_key" } it "prioritizes the option name" do - expect(subject[:api_key]).to eq 'zxcv' + expect(subject[:api_key]).to eq "zxcv" end end context "and the environment collides with an option namespace" do - let(:env) { 'logging' } - let(:yaml) { <<-YAML } -api_key: "cobras" -top: true -logging: - api_key: "badgers" - path: "log/my.log" - level: "DEBUG" + let(:env) { "logging" } + let(:yaml) { <<~YAML } + api_key: "cobras" + top: true + logging: + api_key: "badgers" + path: "log/my.log" + level: "DEBUG" YAML before do @@ -42,32 +42,32 @@ end it "merges all the options" do - expect(subject[:'logging.path']).to eq 'log/my.log' - expect(subject[:'logging.level']).to eq 'DEBUG' - expect(subject[:'logging.api_key']).to eq 'badgers' - expect(subject[:api_key]).to eq 'badgers' + expect(subject[:"logging.path"]).to eq "log/my.log" + expect(subject[:"logging.level"]).to eq "DEBUG" + expect(subject[:"logging.api_key"]).to eq "badgers" + expect(subject[:api_key]).to eq "badgers" expect(subject[:top]).to eq true end end end context "when an environment namespace is not present" do - subject { described_class.new(FIXTURES_PATH.join('honeybadger.yml'), 'foo') } + subject { described_class.new(FIXTURES_PATH.join("honeybadger.yml"), "foo") } it "falls back to the top level namespace" do - expect(subject[:api_key]).to eq 'zxcv' + expect(subject[:api_key]).to eq "zxcv" end end context "when ERB is used" do it "evaluates ERB" do - expect(subject[:erb]).to eq 'erb!' + expect(subject[:erb]).to eq "erb!" end end context "when file is not found" do it "raises a ConfigError" do - expect { described_class.new('foo.yml') }.to raise_error(Honeybadger::Config::ConfigError) + expect { described_class.new("foo.yml") }.to raise_error(Honeybadger::Config::ConfigError) end end @@ -81,23 +81,23 @@ before { allow(path).to receive(:read).and_return(yaml) } context "nil" do - let(:yaml) { '---' } + let(:yaml) { "---" } it { should eq({}) } end context "empty" do - let(:yaml) { '' } + let(:yaml) { "" } it { should eq({}) } end context "invalid" do - let(:yaml) { 'foo' } + let(:yaml) { "foo" } specify { expect { subject }.to raise_error(Honeybadger::Config::ConfigError) } end context "valid" do - let(:yaml) { 'foo: bar' } - it { should eq({ foo: 'bar' }) } + let(:yaml) { "foo: bar" } + it { should eq({foo: "bar"}) } end end @@ -105,7 +105,7 @@ before { allow(path).to receive(:read).and_return(yaml) } let(:yaml) { "foo: !ruby/regexp '/credit_card/i'" } - it { should eq({ foo: /credit_card/i }) } + it { should eq({foo: /credit_card/i}) } end context "when an unknown error occurs" do @@ -120,11 +120,11 @@ end context "when an error occurs in ERB" do - let(:config_path) { FIXTURES_PATH.join('honeybadger.yml') } - let(:yaml) { <<-YAML } ---- -api_key: "<%= MyApp.config.nonexistant_var %>" -YAML + let(:config_path) { FIXTURES_PATH.join("honeybadger.yml") } + let(:yaml) { <<~YAML } + --- + api_key: "<%= MyApp.config.nonexistant_var %>" + YAML before do allow(config_path).to receive(:read).and_return(yaml) diff --git a/spec/unit/honeybadger/config_spec.rb b/spec/unit/honeybadger/config_spec.rb index ff4773ebb..932830b93 100644 --- a/spec/unit/honeybadger/config_spec.rb +++ b/spec/unit/honeybadger/config_spec.rb @@ -1,10 +1,10 @@ -require 'honeybadger/config' -require 'honeybadger/backend/base' -require 'net/http' +require "honeybadger/config" +require "honeybadger/backend/base" +require "net/http" describe Honeybadger::Config do specify { expect(subject[:env]).to eq nil } - specify { expect(subject[:'delayed_job.attempt_threshold']).to eq 0 } + specify { expect(subject[:"delayed_job.attempt_threshold"]).to eq 0 } specify { expect(subject[:debug]).to eq false } describe "#init!" do @@ -22,31 +22,31 @@ end it "prefers ENV to options" do - env['HONEYBADGER_API_KEY'] = 'dan' - config.init!({api_key: 'muj'}, env) - expect(config[:api_key]).to eq 'dan' + env["HONEYBADGER_API_KEY"] = "dan" + config.init!({api_key: "muj"}, env) + expect(config[:api_key]).to eq "dan" end it "prefers file to options" do - config.init!(:'config.path' => FIXTURES_PATH.join('honeybadger.yml'), api_key: 'bar') - expect(config[:api_key]).to eq 'zxcv' + config.init!("config.path": FIXTURES_PATH.join("honeybadger.yml"), api_key: "bar") + expect(config[:api_key]).to eq "zxcv" end it "prefers ENV to file" do - env['HONEYBADGER_API_KEY'] = 'foo' - config.init!({:'config.path' => FIXTURES_PATH.join('honeybadger.yml'), api_key: 'bar'}, env) - expect(config[:api_key]).to eq 'foo' + env["HONEYBADGER_API_KEY"] = "foo" + config.init!({"config.path": FIXTURES_PATH.join("honeybadger.yml"), api_key: "bar"}, env) + expect(config[:api_key]).to eq "foo" end end context "when a logging path is defined" do - let(:log_file) { TMP_DIR.join('honeybadger.log') } + let(:log_file) { TMP_DIR.join("honeybadger.log") } before { log_file.delete if log_file.exist? } it "creates a log file" do expect(log_file.exist?).to eq false - Honeybadger::Config.new.init!(:'logging.path' => log_file) + Honeybadger::Config.new.init!("logging.path": log_file) expect(log_file.exist?).to eq true end end @@ -56,15 +56,15 @@ allow(NULL_LOGGER).to receive(:add) expect(NULL_LOGGER).to receive(:add).with(Logger::Severity::ERROR, /foo/, "honeybadger") config = Honeybadger::Config.new.init!(logger: NULL_LOGGER) - config.logger.error('foo') + config.logger.error("foo") end end context "when the config path is defined" do - let(:config_file) { TMP_DIR.join('honeybadger.yml') } - let(:instance) { Honeybadger::Config.new(:'config.path' => config_file) } + let(:config_file) { TMP_DIR.join("honeybadger.yml") } + let(:instance) { Honeybadger::Config.new("config.path": config_file) } - before { File.write(config_file, '') } + before { File.write(config_file, "") } after { File.unlink(config_file) } def init_instance @@ -74,7 +74,7 @@ def init_instance context "when a config error occurs while loading file" do before do allow(instance.logger).to receive(:add) - allow(Honeybadger::Config::Yaml).to receive(:new).and_raise(Honeybadger::Config::ConfigError.new('ouch')) + allow(Honeybadger::Config::Yaml).to receive(:new).and_raise(Honeybadger::Config::ConfigError.new("ouch")) end it "raises the exception" do @@ -85,7 +85,7 @@ def init_instance context "when a generic error occurs while loading file" do before do allow(instance.logger).to receive(:add) - allow(Honeybadger::Config::Yaml).to receive(:new).and_raise(RuntimeError.new('ouch')) + allow(Honeybadger::Config::Yaml).to receive(:new).and_raise(RuntimeError.new("ouch")) end it "raises the exception" do @@ -100,33 +100,33 @@ def init_instance let(:opts) { {} } context "when a normal option doesn't exist" do - it 'returns the default option value' do + it "returns the default option value" do expect(instance.get(:development_environments)).to eq Honeybadger::Config::DEFAULTS[:development_environments] end end context "when a normal option exists" do - let(:opts) { { :development_environments => ['foo']} } + let(:opts) { {development_environments: ["foo"]} } - it 'returns the option value' do - expect(instance.get(:development_environments)).to eq ['foo'] + it "returns the option value" do + expect(instance.get(:development_environments)).to eq ["foo"] end end end describe "#ignored_classes" do let(:instance) { Honeybadger::Config.new({logger: NULL_LOGGER, debug: true}.merge!(opts)) } - let(:opts) { { :'exceptions.ignore' => ['foo']} } + let(:opts) { {"exceptions.ignore": ["foo"]} } it "returns the exceptions.ignore option value plus defaults" do - expect(instance.ignored_classes).to eq(Honeybadger::Config::DEFAULTS[:'exceptions.ignore'] | ['foo']) + expect(instance.ignored_classes).to eq(Honeybadger::Config::DEFAULTS[:"exceptions.ignore"] | ["foo"]) end context "when exceptions.ignore_only is configured" do - let(:opts) { { :'exceptions.ignore' => ['foo'], :'exceptions.ignore_only' => ['bar']} } + let(:opts) { {"exceptions.ignore": ["foo"], "exceptions.ignore_only": ["bar"]} } it "returns the override" do - expect(instance.ignored_classes).to eq(['bar']) + expect(instance.ignored_classes).to eq(["bar"]) end end end @@ -155,7 +155,7 @@ def init_instance end context "framework is configured" do - before { subject[:framework] = 'rack' } + before { subject[:framework] = "rack" } its(:detected_framework) { should eq :rack } end @@ -164,7 +164,7 @@ def init_instance before do rails = Module.new version = Module.new - version.const_set(:STRING, '4.1.5') + version.const_set(:STRING, "4.1.5") rails.const_set(:VERSION, version) Object.const_set(:Rails, rails) end @@ -172,31 +172,34 @@ def init_instance after { Object.send(:remove_const, :Rails) } its(:detected_framework) { should eq :rails } - its(:framework_name) { should match /Rails 4\.1\.5/ } + its(:framework_name) { should match(/Rails 4\.1\.5/) } end context "Sinatra is installed" do before do sinatra = Module.new - sinatra.const_set(:VERSION, '1.4.5') + sinatra.const_set(:VERSION, "1.4.5") Object.const_set(:Sinatra, sinatra) end after { Object.send(:remove_const, :Sinatra) } its(:detected_framework) { should eq :sinatra } - its(:framework_name) { should match /Sinatra 1\.4\.5/ } + its(:framework_name) { should match(/Sinatra 1\.4\.5/) } end context "Rack is installed" do before do - Object.const_set(:Rack, Module.new { def self.release; '1.0'; end; }) + Object.const_set(:Rack, Module.new { + def self.release + "1.0" + end; }) end after { Object.send(:remove_const, :Rack) } its(:detected_framework) { should eq :rack } - its(:framework_name) { should match /Rack 1\.0/ } + its(:framework_name) { should match(/Rack 1\.0/) } end end @@ -209,7 +212,7 @@ def init_instance end context "when environment is not a development environment" do - before { subject[:env] = 'production' } + before { subject[:env] = "production" } its(:default_backend) { should be_a Honeybadger::Backend::Server } context "when disabled explicitly" do @@ -219,7 +222,7 @@ def init_instance end context "when environment is a development environment" do - before { subject[:env] = 'development' } + before { subject[:env] = "development" } its(:default_backend) { should be_a Honeybadger::Backend::Null } context "when enabled explicitly" do @@ -240,13 +243,13 @@ def init_instance end context "when root is present" do - let(:root) { '/bar' } - it { should match '/bar/baz' } - it { should_not match '/foo/bar/baz' } + let(:root) { "/bar" } + it { should match "/bar/baz" } + it { should_not match "/foo/bar/baz" } end context "when root is blank" do - let(:root) { '' } + let(:root) { "" } it { should be_nil } end end @@ -265,17 +268,17 @@ def init_instance expect(CONFIGURE_LOGGER).to receive(:add).with(Logger::Severity::ERROR, /foo/, "honeybadger") - honeybadger.logger.error('foo') + honeybadger.logger.error("foo") end end it "configures multiple before_notify hooks" do subject.configure do |config| - config.before_notify {|n| n } + config.before_notify { |n| n } end subject.configure do |config| - config.before_notify {|n| n } + config.before_notify { |n| n } end expect(subject.before_notify_hooks.size).to eq(2) @@ -286,11 +289,11 @@ def init_instance unknown_key_response = nil subject.configure do |config| - known_key_response = config.respond_to?("api_key") + known_key_response = config.respond_to?(:api_key) end subject.configure do |config| - unknown_key_response = config.respond_to?("ejfhjskdhfkdjhf=") + unknown_key_response = config.respond_to?(:ejfhjskdhfkdjhf=) end expect(known_key_response).to eq(true) diff --git a/spec/unit/honeybadger/counter_spec.rb b/spec/unit/honeybadger/counter_spec.rb index 4da351ad2..dca796892 100644 --- a/spec/unit/honeybadger/counter_spec.rb +++ b/spec/unit/honeybadger/counter_spec.rb @@ -1,15 +1,13 @@ -# encoding: utf-8 - describe Honeybadger::Counter do describe "#payloads" do let(:metric) { described_class.new(name, attributes) } let(:name) { "perform" } - let(:attributes) { { foo: "bar" } } + let(:attributes) { {foo: "bar"} } subject { metric.payloads } before { metric.count } - it { should eq [{ counter: 1 }] } + it { should eq [{counter: 1}] } end end diff --git a/spec/unit/honeybadger/event_spec.rb b/spec/unit/honeybadger/event_spec.rb index 0085d9197..949c4ae2a 100644 --- a/spec/unit/honeybadger/event_spec.rb +++ b/spec/unit/honeybadger/event_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/event' -require 'timecop' +require "honeybadger/event" +require "timecop" describe Honeybadger::Event do let(:event_type) { "event_type" } @@ -19,10 +19,10 @@ context "event_type is passed as part of payload" do subject { described_class.new(event_type) } - let(:event_type) { { event_type: "action" } } + let(:event_type) { {event_type: "action"} } its(:event_type) { should eq "action" } - its(:payload) { should eq({ event_type: "action" }) } + its(:payload) { should eq({event_type: "action"}) } end end @@ -46,11 +46,11 @@ describe "as_json" do let(:event_type) { "action" } - let(:payload) { { data1: 1 } } + let(:payload) { {data1: 1} } before { Timecop.freeze } after { Timecop.unfreeze } - its(:as_json) { should eq({ event_type: "action", ts: Time.now.utc.strftime("%FT%T.%LZ"), data1: 1 }) } + its(:as_json) { should eq({event_type: "action", ts: Time.now.utc.strftime("%FT%T.%LZ"), data1: 1}) } end end diff --git a/spec/unit/honeybadger/events_worker_spec.rb b/spec/unit/honeybadger/events_worker_spec.rb index 42bb27855..43127da02 100644 --- a/spec/unit/honeybadger/events_worker_spec.rb +++ b/spec/unit/honeybadger/events_worker_spec.rb @@ -1,17 +1,17 @@ -require 'timecop' -require 'thread' +require "timecop" +require "thread" -require 'honeybadger/events_worker' -require 'honeybadger/config' -require 'honeybadger/backend' +require "honeybadger/events_worker" +require "honeybadger/config" +require "honeybadger/backend" describe Honeybadger::EventsWorker do let!(:instance) { described_class.new(config) } let(:config) { Honeybadger::Config.new( - logger: NULL_LOGGER, debug: true, backend: 'null', - :'events.batch_size' => 5, - :'events.timeout' => 10_000 + logger: NULL_LOGGER, debug: true, backend: "null", + "events.batch_size": 5, + "events.timeout": 10_000 ) } let(:event) { {event_type: "test", ts: "not-important"} } @@ -20,14 +20,14 @@ after do Thread.list.each do |thread| - next unless thread.kind_of?(Honeybadger::EventsWorker::Thread) + next unless thread.is_a?(Honeybadger::EventsWorker::Thread) Thread.kill(thread) end end context "when an exception happens in the worker loop" do before do - allow(instance.send(:queue)).to receive(:pop).and_raise('fail') + allow(instance.send(:queue)).to receive(:pop).and_raise("fail") end it "does not raise when shutting down" do @@ -56,7 +56,7 @@ context "when an exception happens during processing" do before do allow(instance).to receive(:sleep) - allow(instance).to receive(:handle_response).and_raise('fail') + allow(instance).to receive(:handle_response).and_raise("fail") end def flush @@ -214,7 +214,7 @@ def flush context "when throttled during shutdown" do before do - allow(subject.send(:backend)).to receive(:event).with(anything).and_return(Honeybadger::Backend::Response.new(429) ) + allow(subject.send(:backend)).to receive(:event).with(anything).and_return(Honeybadger::Backend::Response.new(429)) end it "shuts down immediately" do @@ -339,7 +339,7 @@ def handle_response end context "when error" do - let(:response) { Honeybadger::Backend::Response.new(:error, nil, 'test error message') } + let(:response) { Honeybadger::Backend::Response.new(:error, nil, "test error message") } it "warns the logger" do expect(config.logger).to receive(:warn).with(/test error message/) @@ -359,14 +359,14 @@ def handle_response context "timeout" do let(:config) { Honeybadger::Config.new( - logger: NULL_LOGGER, debug: true, backend: 'null', - :'events.batch_size' => 5, - :'events.timeout' => 100 + logger: NULL_LOGGER, debug: true, backend: "null", + "events.batch_size": 5, + "events.timeout": 100 ) } it "should send after timeout when sending another" do - expect(subject.send(:backend)).to receive(:event).with([event]).twice().and_return(Honeybadger::Backend::Null::StubbedResponse.new) + expect(subject.send(:backend)).to receive(:event).with([event]).twice.and_return(Honeybadger::Backend::Null::StubbedResponse.new) subject.push(event) sleep(0.25) subject.push(event) diff --git a/spec/unit/honeybadger/gauge_spec.rb b/spec/unit/honeybadger/gauge_spec.rb index 44c18a2dd..f15e4c589 100644 --- a/spec/unit/honeybadger/gauge_spec.rb +++ b/spec/unit/honeybadger/gauge_spec.rb @@ -1,15 +1,13 @@ -# encoding: utf-8 - describe Honeybadger::Gauge do describe "#payloads" do let(:metric) { described_class.new(name, attributes) } let(:name) { "perform" } - let(:attributes) { { foo: "bar" } } + let(:attributes) { {foo: "bar"} } subject { metric.payloads } before { metric.record(1) } - it { should eq [{ total: 1, avg: 1.0, latest: 1, max: 1, min: 1 }] } + it { should eq [{total: 1, avg: 1.0, latest: 1, max: 1, min: 1}] } end end diff --git a/spec/unit/honeybadger/histogram_spec.rb b/spec/unit/honeybadger/histogram_spec.rb index 67257671d..a8be428d4 100644 --- a/spec/unit/honeybadger/histogram_spec.rb +++ b/spec/unit/honeybadger/histogram_spec.rb @@ -1,10 +1,8 @@ -# encoding: utf-8 - describe Honeybadger::Histogram do describe "#payloads" do let(:metric) { described_class.new(name, attributes) } let(:name) { "perform" } - let(:attributes) { { foo: "bar" } } + let(:attributes) { {foo: "bar"} } subject { metric.payloads } diff --git a/spec/unit/honeybadger/instrumentation_helper_spec.rb b/spec/unit/honeybadger/instrumentation_helper_spec.rb index 8f1ac4ce2..453bcc9a6 100644 --- a/spec/unit/honeybadger/instrumentation_helper_spec.rb +++ b/spec/unit/honeybadger/instrumentation_helper_spec.rb @@ -1,57 +1,57 @@ -require 'honeybadger/instrumentation_helper' +require "honeybadger/instrumentation_helper" describe Honeybadger::InstrumentationHelper do - let(:test_object) { Object.new.tap { |o| o.extend(described_class) }} + let(:test_object) { Object.new.tap { |o| o.extend(described_class) } } before do Honeybadger.registry.flush end - describe '#metric_source' do - let(:metric_source) { 'test-source' } + describe "#metric_source" do + let(:metric_source) { "test-source" } - it 'sets the metric_source attribute' do + it "sets the metric_source attribute" do test_object.metric_source metric_source - gauge = test_object.gauge('test_gauge', ->{ 1 }) + gauge = test_object.gauge("test_gauge", -> { 1 }) expect(gauge.base_payload[:metric_source]).to eq metric_source end end - describe '#metric_attributes' do - let(:metric_attributes) { { foo: 'bar' } } + describe "#metric_attributes" do + let(:metric_attributes) { {foo: "bar"} } - it 'merges the attributes' do + it "merges the attributes" do test_object.metric_attributes metric_attributes - gauge = test_object.gauge('test_gauge', ->{ 1 }) + gauge = test_object.gauge("test_gauge", -> { 1 }) expect(gauge.attributes.keys).to include(:foo) - expect(gauge.attributes[:foo]).to eq 'bar' + expect(gauge.attributes[:foo]).to eq "bar" end end - describe '#time' do - context 'by keyword argument' do - it 'creates a timer object' do - timer = test_object.time('test_timer', duration: 0.1) + describe "#time" do + context "by keyword argument" do + it "creates a timer object" do + timer = test_object.time("test_timer", duration: 0.1) expect(timer).to be_a Honeybadger::Timer expect(timer.payloads[0][:latest]).to be > 0 end end - context 'by lambda' do - it 'creates a timer object' do - timer = test_object.time('test_timer', ->{ sleep(0.1) }) + context "by lambda" do + it "creates a timer object" do + timer = test_object.time("test_timer", -> { sleep(0.1) }) expect(timer).to be_a Honeybadger::Timer expect(timer.payloads[0][:latest]).to be > 0 end end - context 'by block' do - it 'creates a timer object' do - timer = test_object.time('test_timer') { sleep(0.1) } + context "by block" do + it "creates a timer object" do + timer = test_object.time("test_timer") { sleep(0.1) } expect(timer).to be_a Honeybadger::Timer expect(timer.payloads[0][:latest]).to be > 0 @@ -59,11 +59,11 @@ end end - describe '#gauge' do - context 'by keyword argument' do - it 'creates a gauge object' do - gauge = test_object.gauge('test_gauge', value: 1) - test_object.gauge('test_gauge', value: 10) + describe "#gauge" do + context "by keyword argument" do + it "creates a gauge object" do + gauge = test_object.gauge("test_gauge", value: 1) + test_object.gauge("test_gauge", value: 10) expect(gauge).to be_a Honeybadger::Gauge expect(gauge.payloads[0][:latest]).to eq(10) @@ -73,10 +73,10 @@ end end - context 'by lambda' do - it 'creates a gauge object' do - gauge = test_object.gauge('test_gauge', ->{ 1 }) - test_object.gauge('test_gauge', -> { 10 }) + context "by lambda" do + it "creates a gauge object" do + gauge = test_object.gauge("test_gauge", -> { 1 }) + test_object.gauge("test_gauge", -> { 10 }) expect(gauge).to be_a Honeybadger::Gauge expect(gauge.payloads[0][:latest]).to eq(10) @@ -86,10 +86,10 @@ end end - context 'by block' do - it 'creates a gauge object' do - gauge = test_object.gauge('test_gauge') { 1 } - test_object.gauge('test_gauge') { 10 } + context "by block" do + it "creates a gauge object" do + gauge = test_object.gauge("test_gauge") { 1 } + test_object.gauge("test_gauge") { 10 } expect(gauge).to be_a Honeybadger::Gauge expect(gauge.payloads[0][:latest]).to eq(10) @@ -99,37 +99,37 @@ end end end - describe '#increment_counter' do - context 'by default increment' do - it 'creates a counter object' do - counter = test_object.increment_counter('test_counter') + describe "#increment_counter" do + context "by default increment" do + it "creates a counter object" do + counter = test_object.increment_counter("test_counter") expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) end end - context 'by keyword argument' do - it 'creates a counter object' do - counter = test_object.increment_counter('test_counter', by: 1) + context "by keyword argument" do + it "creates a counter object" do + counter = test_object.increment_counter("test_counter", by: 1) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) end end - context 'by lambda' do - it 'creates a counter object' do - counter = test_object.increment_counter('test_counter', ->{ 1 }) + context "by lambda" do + it "creates a counter object" do + counter = test_object.increment_counter("test_counter", -> { 1 }) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) end end - context 'by block' do - it 'creates a counter object' do - counter = test_object.increment_counter('test_counter') { 1 } + context "by block" do + it "creates a counter object" do + counter = test_object.increment_counter("test_counter") { 1 } expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) @@ -137,37 +137,37 @@ end end - describe '#decrement_counter' do - context 'by default decrement' do - it 'creates a counter object' do - counter = test_object.decrement_counter('test_counter') + describe "#decrement_counter" do + context "by default decrement" do + it "creates a counter object" do + counter = test_object.decrement_counter("test_counter") expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) end end - context 'by keyword argument' do - it 'creates a counter object' do - counter = test_object.decrement_counter('test_counter', by: 1) + context "by keyword argument" do + it "creates a counter object" do + counter = test_object.decrement_counter("test_counter", by: 1) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) end end - context 'by lambda' do - it 'creates a counter object' do - counter = test_object.decrement_counter('test_counter', ->{ 1 }) + context "by lambda" do + it "creates a counter object" do + counter = test_object.decrement_counter("test_counter", -> { 1 }) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) end end - context 'by block' do - it 'creates a counter object' do - counter = test_object.decrement_counter('test_counter') { 1 } + context "by block" do + it "creates a counter object" do + counter = test_object.decrement_counter("test_counter") { 1 } expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) @@ -175,28 +175,28 @@ end end - describe '#histogram' do - context 'by keyword argument' do - it 'creates a histogram object' do - histogram = test_object.histogram('test_histogram', duration: 0.0001) + describe "#histogram" do + context "by keyword argument" do + it "creates a histogram object" do + histogram = test_object.histogram("test_histogram", duration: 0.0001) expect(histogram).to be_a Honeybadger::Histogram expect(histogram.payloads[0][:bins].map { |b| b[1] }).to include 1 end end - context 'by lambda' do - it 'creates a histogram object' do - histogram = test_object.histogram('test_histogram', ->{ sleep(0.0001) }) + context "by lambda" do + it "creates a histogram object" do + histogram = test_object.histogram("test_histogram", -> { sleep(0.0001) }) expect(histogram).to be_a Honeybadger::Histogram expect(histogram.payloads[0][:bins].map { |b| b[1] }).to include 1 end end - context 'by block' do - it 'creates a histogram object' do - histogram = test_object.histogram('test_histogram') { sleep(0.0001) } + context "by block" do + it "creates a histogram object" do + histogram = test_object.histogram("test_histogram") { sleep(0.0001) } expect(histogram).to be_a Honeybadger::Histogram expect(histogram.payloads[0][:bins].map { |b| b[1] }).to include 1 diff --git a/spec/unit/honeybadger/instrumentation_spec.rb b/spec/unit/honeybadger/instrumentation_spec.rb index a85918ed3..3d438dfbc 100644 --- a/spec/unit/honeybadger/instrumentation_spec.rb +++ b/spec/unit/honeybadger/instrumentation_spec.rb @@ -1,4 +1,4 @@ -require 'honeybadger/instrumentation' +require "honeybadger/instrumentation" describe Honeybadger::Instrumentation do let(:agent) { Honeybadger::Agent.new } @@ -8,28 +8,28 @@ agent.registry.flush end - describe '.time' do - context 'by keyword argument' do - it 'creates a timer object' do - timer = instrumentation.time('test_timer', duration: 0.1) + describe ".time" do + context "by keyword argument" do + it "creates a timer object" do + timer = instrumentation.time("test_timer", duration: 0.1) expect(timer).to be_a Honeybadger::Timer expect(timer.payloads[0][:latest]).to be > 0 end end - context 'by lambda' do - it 'creates a timer object' do - timer = instrumentation.time('test_timer', ->{ sleep(0.1) }) + context "by lambda" do + it "creates a timer object" do + timer = instrumentation.time("test_timer", -> { sleep(0.1) }) expect(timer).to be_a Honeybadger::Timer expect(timer.payloads[0][:latest]).to be > 0 end end - context 'by block' do - it 'creates a timer object' do - timer = instrumentation.time('test_timer') { sleep(0.1) } + context "by block" do + it "creates a timer object" do + timer = instrumentation.time("test_timer") { sleep(0.1) } expect(timer).to be_a Honeybadger::Timer expect(timer.payloads[0][:latest]).to be > 0 @@ -37,11 +37,11 @@ end end - describe '#gauge' do - context 'by keyword arg' do - it 'creates a gauge object' do - gauge = instrumentation.gauge('test_gauge', value: 1) - instrumentation.gauge('test_gauge', value: 10) + describe "#gauge" do + context "by keyword arg" do + it "creates a gauge object" do + gauge = instrumentation.gauge("test_gauge", value: 1) + instrumentation.gauge("test_gauge", value: 10) expect(gauge).to be_a Honeybadger::Gauge expect(gauge.payloads[0][:latest]).to eq(10) @@ -51,10 +51,10 @@ end end - context 'by lambda' do - it 'creates a gauge object' do - gauge = instrumentation.gauge('test_gauge', ->{ 1 }) - instrumentation.gauge('test_gauge', ->{ 10 }) + context "by lambda" do + it "creates a gauge object" do + gauge = instrumentation.gauge("test_gauge", -> { 1 }) + instrumentation.gauge("test_gauge", -> { 10 }) expect(gauge).to be_a Honeybadger::Gauge expect(gauge.payloads[0][:latest]).to eq(10) @@ -64,10 +64,10 @@ end end - context 'by block' do - it 'creates a gauge object' do - gauge = instrumentation.gauge('test_gauge') { 1 } - instrumentation.gauge('test_gauge') { 10 } + context "by block" do + it "creates a gauge object" do + gauge = instrumentation.gauge("test_gauge") { 1 } + instrumentation.gauge("test_gauge") { 10 } expect(gauge).to be_a Honeybadger::Gauge expect(gauge.payloads[0][:latest]).to eq(10) @@ -78,37 +78,37 @@ end end - describe '#increment_counter' do - context 'default increment' do - it 'creates a counter object' do - counter = instrumentation.increment_counter('test_counter') + describe "#increment_counter" do + context "default increment" do + it "creates a counter object" do + counter = instrumentation.increment_counter("test_counter") expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) end end - context 'by keyword arg' do - it 'creates a counter object' do - counter = instrumentation.increment_counter('test_counter', by: 1) + context "by keyword arg" do + it "creates a counter object" do + counter = instrumentation.increment_counter("test_counter", by: 1) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) end end - context 'by lambda' do - it 'creates a counter object' do - counter = instrumentation.increment_counter('test_counter', ->{ 1 }) + context "by lambda" do + it "creates a counter object" do + counter = instrumentation.increment_counter("test_counter", -> { 1 }) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) end end - context 'by block' do - it 'creates a counter object' do - counter = instrumentation.increment_counter('test_counter') { 1 } + context "by block" do + it "creates a counter object" do + counter = instrumentation.increment_counter("test_counter") { 1 } expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(1) @@ -116,37 +116,37 @@ end end - describe '#decrement_counter' do - context 'default decrement' do - it 'creates a counter object' do - counter = instrumentation.decrement_counter('test_counter') + describe "#decrement_counter" do + context "default decrement" do + it "creates a counter object" do + counter = instrumentation.decrement_counter("test_counter") expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) end end - context 'by keyword arg' do - it 'creates a counter object' do - counter = instrumentation.decrement_counter('test_counter', by: 1) + context "by keyword arg" do + it "creates a counter object" do + counter = instrumentation.decrement_counter("test_counter", by: 1) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) end end - context 'by lambda' do - it 'creates a counter object' do - counter = instrumentation.decrement_counter('test_counter', ->{ 1 }) + context "by lambda" do + it "creates a counter object" do + counter = instrumentation.decrement_counter("test_counter", -> { 1 }) expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) end end - context 'by block' do - it 'creates a counter object' do - counter = instrumentation.decrement_counter('test_counter') { 1 } + context "by block" do + it "creates a counter object" do + counter = instrumentation.decrement_counter("test_counter") { 1 } expect(counter).to be_a Honeybadger::Counter expect(counter.payloads[0][:counter]).to eq(-1) @@ -154,28 +154,28 @@ end end - describe '#histogram' do - context 'by keyword argument' do - it 'creates a histogram object' do - histogram = instrumentation.histogram('test_histogram', duration: 0.0001) + describe "#histogram" do + context "by keyword argument" do + it "creates a histogram object" do + histogram = instrumentation.histogram("test_histogram", duration: 0.0001) expect(histogram).to be_a Honeybadger::Histogram expect(histogram.payloads[0][:bins].map { |b| b[1] }).to include 1 end end - context 'by lambda' do - it 'creates a histogram object' do - histogram = instrumentation.histogram('test_histogram', ->{ sleep(0.0001) }) + context "by lambda" do + it "creates a histogram object" do + histogram = instrumentation.histogram("test_histogram", -> { sleep(0.0001) }) expect(histogram).to be_a Honeybadger::Histogram expect(histogram.payloads[0][:bins].map { |b| b[1] }).to include 1 end end - context 'by block' do - it 'creates a histogram object' do - histogram = instrumentation.histogram('test_histogram') { sleep(0.0001) } + context "by block" do + it "creates a histogram object" do + histogram = instrumentation.histogram("test_histogram") { sleep(0.0001) } expect(histogram).to be_a Honeybadger::Histogram expect(histogram.payloads[0][:bins].map { |b| b[1] }).to include 1 diff --git a/spec/unit/honeybadger/logging_spec.rb b/spec/unit/honeybadger/logging_spec.rb index 7ac13489e..683921ee9 100644 --- a/spec/unit/honeybadger/logging_spec.rb +++ b/spec/unit/honeybadger/logging_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/logging' -require 'honeybadger/config' +require "honeybadger/logging" +require "honeybadger/config" LOG_SEVERITIES = [:debug, :info, :warn, :error, :fatal].freeze @@ -10,7 +10,7 @@ describe "#add" do it "requires subclass to define it" do - expect { subject.add(1, 'snakes!').to raise_error NotImplementedError } + expect { subject.add(1, "snakes!").to raise_error NotImplementedError } end end end @@ -30,7 +30,7 @@ it "flushes ##{severity} messages to logger" do subject.send(severity, :foo) - logger = double('Logger') + logger = double("Logger") expect(logger).to receive(:add).with(Logger::Severity.const_get(severity.to_s.upcase), :foo) subject.flush(logger) end @@ -53,9 +53,9 @@ end describe Honeybadger::Logging::ConfigLogger do - let(:config) { Honeybadger::Config.new(debug: true, :'logging.tty_level' => tty_level) } + let(:config) { Honeybadger::Config.new(debug: true, "logging.tty_level": tty_level) } let(:logger) { Logger.new(File::NULL) } - let(:tty_level) { 'ERROR' } + let(:tty_level) { "ERROR" } subject { described_class.new(config, logger) } @@ -67,7 +67,7 @@ LOG_SEVERITIES.each do |severity| it "delegates ##{severity} to configured logger" do # Debug is logged at the info level. - const = Logger::Severity.const_get((severity == :debug ? :info : severity).to_s.upcase) + const = Logger::Severity.const_get(((severity == :debug) ? :info : severity).to_s.upcase) expect(logger).to receive(:add).with(const, :foo, "honeybadger") subject.send(severity, :foo) end @@ -90,12 +90,12 @@ end context "and logging.tty is enabled" do - let(:tty_level) { 'DEBUG' } + let(:tty_level) { "DEBUG" } LOG_SEVERITIES.each do |severity| it "delegates ##{severity} to configured logger" do # Debug is logged at the info level. - const = Logger::Severity.const_get((severity == :debug ? :info : severity).to_s.upcase) + const = Logger::Severity.const_get(((severity == :debug) ? :info : severity).to_s.upcase) expect(logger).to receive(:add).with(const, :foo, "honeybadger") subject.send(severity, :foo) end diff --git a/spec/unit/honeybadger/metric_spec.rb b/spec/unit/honeybadger/metric_spec.rb index c85be92f1..25085eb01 100644 --- a/spec/unit/honeybadger/metric_spec.rb +++ b/spec/unit/honeybadger/metric_spec.rb @@ -1,11 +1,9 @@ -# encoding: utf-8 - describe Honeybadger::Metric do let(:registry) { Honeybadger::Registry.new } describe ".register" do let(:name) { "capacity" } - let(:attributes) { { foo: "bar" } } + let(:attributes) { {foo: "bar"} } subject { described_class.register(registry, name, attributes) } @@ -28,7 +26,7 @@ context "with metric_type, name, and attributes" do let(:metric_type) { "gauge" } let(:name) { "capacity" } - let(:attributes) { { foo: "bar" } } + let(:attributes) { {foo: "bar"} } it { should eq Digest::SHA1.hexdigest("gauge-capacity-foo-bar").to_sym } end @@ -39,7 +37,7 @@ context "with name, and attributes" do let(:name) { "capacity" } - let(:attributes) { { foo: "bar" } } + let(:attributes) { {foo: "bar"} } it { should eq Digest::SHA1.hexdigest("metric-capacity-foo-bar").to_sym } end diff --git a/spec/unit/honeybadger/metrics_worker_spec.rb b/spec/unit/honeybadger/metrics_worker_spec.rb index 0d2f749c2..ba468b831 100644 --- a/spec/unit/honeybadger/metrics_worker_spec.rb +++ b/spec/unit/honeybadger/metrics_worker_spec.rb @@ -1,25 +1,25 @@ -require 'timecop' -require 'thread' +require "timecop" +require "thread" -require 'honeybadger/metrics_worker' -require 'honeybadger/config' +require "honeybadger/metrics_worker" +require "honeybadger/config" describe Honeybadger::MetricsWorker do let!(:instance) { described_class.new(config) } - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'insights.enabled' => true) } - let(:obj) { double('CollectionExecution', tick: 1) } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "insights.enabled": true) } + let(:obj) { double("CollectionExecution", tick: 1) } subject { instance } after do Thread.list.each do |thread| - next unless thread.kind_of?(Honeybadger::MetricsWorker::Thread) + next unless thread.is_a?(Honeybadger::MetricsWorker::Thread) Thread.kill(thread) end end describe "work depends on tick" do - let(:obj) { double('CollectionExecution', tick: tick) } + let(:obj) { double("CollectionExecution", tick: tick) } before do allow(instance).to receive(:sleep) @@ -53,7 +53,7 @@ def flush context "when an exception happens in the worker loop" do before do - allow(instance.send(:queue)).to receive(:pop).and_raise('fail') + allow(instance.send(:queue)).to receive(:pop).and_raise("fail") end it "does not raise when shutting down" do @@ -80,11 +80,11 @@ def flush end context "when an exception happens during processing" do - let(:obj) { double('CollectionExecution', tick: 0, call: nil, reset: nil) } + let(:obj) { double("CollectionExecution", tick: 0, call: nil, reset: nil) } before do allow(instance).to receive(:sleep) - allow(obj).to receive(:call).and_raise('fail') + allow(obj).to receive(:call).and_raise("fail") end def flush diff --git a/spec/unit/honeybadger/notice_spec.rb b/spec/unit/honeybadger/notice_spec.rb index ee3776a05..84996900d 100644 --- a/spec/unit/honeybadger/notice_spec.rb +++ b/spec/unit/honeybadger/notice_spec.rb @@ -1,15 +1,13 @@ -# encoding: utf-8 - -require 'honeybadger/notice' -require 'honeybadger/config' -require 'honeybadger/plugins/local_variables' -require 'timecop' +require "honeybadger/notice" +require "honeybadger/config" +require "honeybadger/plugins/local_variables" +require "timecop" describe Honeybadger::Notice do let(:config) { build_config } def build_config(opts = {}) - Honeybadger::Config.new({logger: NULL_LOGGER, api_key: 'asdf'}.merge(opts)) + Honeybadger::Config.new({logger: NULL_LOGGER, api_key: "asdf"}.merge(opts)) end def build_notice(opts = {}) @@ -45,7 +43,7 @@ def assert_array_starts_with(expected, actual) it "generates json from as_json template" do notice = build_notice - hash = {'foo' => 'bar'} + hash = {"foo" => "bar"} expect(notice).to receive(:as_json).once.and_return(hash) json = notice.to_json @@ -56,45 +54,45 @@ def assert_array_starts_with(expected, actual) end it "accepts a component" do - expect(build_notice(component: 'users_controller').controller).to eq 'users_controller' + expect(build_notice(component: "users_controller").controller).to eq "users_controller" end it "aliases the component as controller" do - expect(build_notice(controller: 'users_controller').component).to eq 'users_controller' - expect(build_notice(controller: 'users_controller').controller).to eq 'users_controller' + expect(build_notice(controller: "users_controller").component).to eq "users_controller" + expect(build_notice(controller: "users_controller").controller).to eq "users_controller" end it "aliases component method as controller" do notice = build_notice - notice.component = 'users_controller' + notice.component = "users_controller" - expect(notice.controller).to eq 'users_controller' + expect(notice.controller).to eq "users_controller" end it "aliases component= method as controller=" do notice = build_notice - notice.controller = 'users_controller' + notice.controller = "users_controller" - expect(notice.component).to eq 'users_controller' + expect(notice.component).to eq "users_controller" end it "aliases the params as parameters" do - expect(build_notice(parameters: {foo: 'foo'}).params).to eq({foo: 'foo'}) - expect(build_notice(params: {bar: 'bar'}).parameters).to eq({bar: 'bar'}) + expect(build_notice(parameters: {foo: "foo"}).params).to eq({foo: "foo"}) + expect(build_notice(params: {bar: "bar"}).parameters).to eq({bar: "bar"}) end it "accepts an action" do - expect(build_notice(action: 'index').action).to eq 'index' + expect(build_notice(action: "index").action).to eq "index" end it "accepts a url" do - url = 'http://some.host/uri' + url = "http://some.host/uri" notice = build_notice(url: url) expect(notice.url).to eq url end it "accepts a request_id" do - expect(build_notice(request_id: 'abc').request_id).to eq 'abc' + expect(build_notice(request_id: "abc").request_id).to eq "abc" end it "sets the error class from an exception or hash" do @@ -126,7 +124,7 @@ def exception.detailed_message(**kwargs) MSG end - notice_from_exception = build_notice({ exception: exception }) + notice_from_exception = build_notice({exception: exception}) expect(notice_from_exception.send(:error_message)).to eq <<~EXPECTED NoMethodError: test.rb:1:in `
': undefined method `time' for 1:Integer @@ -137,25 +135,25 @@ def exception.detailed_message(**kwargs) end it "accepts parameters from a request or hash" do - params = {'one' => 'two'} + params = {"one" => "two"} notice_from_hash = build_notice(params: params) expect(notice_from_hash.params).to eq params end it "accepts session data from a session[:data] hash" do - data = {'one' => 'two'} + data = {"one" => "two"} notice = build_notice(session: {data: data}) expect(notice.session).to eq data end it "accepts session data from a session hash" do - data = {'one' => 'two'} + data = {"one" => "two"} notice = build_notice(session: data) expect(notice.session).to eq data end it "accepts CGI data from a hash" do - data = {'STRING' => 'value'} + data = {"STRING" => "value"} notice = build_notice(cgi_data: data) expect(notice.cgi_data).to eq data end @@ -164,21 +162,21 @@ def exception.detailed_message(**kwargs) backtrace = build_backtrace_array notice = build_notice(backtrace: backtrace) - expect(notice.error_message).to eq 'No message provided' + expect(notice.error_message).to eq "No message provided" assert_array_starts_with(backtrace, notice.backtrace) expect(notice.params).to be_empty expect(notice.session).to be_empty end - it 'includes details in payload' do + it "includes details in payload" do data = {"test" => {v1: 100}} notice = build_notice(details: data) expect(notice.details).to eq(data) - expect(JSON.parse(notice.to_json)['details']['test']['v1']).to eq(100) + expect(JSON.parse(notice.to_json)["details"]["test"]["v1"]).to eq(100) end it "uses the caller as the backtrace for an exception without a backtrace" do - notice = build_notice(exception: StandardError.new('error'), backtrace: nil) + notice = build_notice(exception: StandardError.new("error"), backtrace: nil) assert_array_starts_with caller, notice.backtrace end @@ -190,95 +188,95 @@ def exception.detailed_message(**kwargs) json = notice.to_json payload = JSON.parse(json) - expect(payload['request']['url']).to be_nil - expect(payload['request']['component']).to be_nil - expect(payload['request']['action']).to be_nil + expect(payload["request"]["url"]).to be_nil + expect(payload["request"]["component"]).to be_nil + expect(payload["request"]["action"]).to be_nil end it "does not filter the backtrace" do - notice = build_notice(:config => build_config(:'request.filter_keys' => ['number']), :backtrace => ['foo:1:in `bar\'']) + notice = build_notice(config: build_config("request.filter_keys": ["number"]), backtrace: ["foo:1:in `bar'"]) json = notice.to_json payload = JSON.parse(json) - expect(payload['error']['backtrace'][0]['number']).to eq '1' + expect(payload["error"]["backtrace"][0]["number"]).to eq "1" end - %w(params session cgi_data).each do |var| + %w[params session cgi_data].each do |var| it "does not filter top level #{var}" do - notice = build_notice(:config => build_config(:'request.filter_keys' => [var]), var.to_sym => {var => 'hello'}) + notice = build_notice(:config => build_config("request.filter_keys": [var]), var.to_sym => {var => "hello"}) json = notice.to_json payload = JSON.parse(json) - expect(payload['request'][var]).to eq({var => '[FILTERED]'}) + expect(payload["request"][var]).to eq({var => "[FILTERED]"}) end context "when #{var} is excluded" do it "sends default value" do - cfg = var == 'cgi_data' ? 'environment' : var - notice = build_notice(:config => build_config(:"request.disable_#{cfg}" => true), var.to_sym => {var => 'hello'}) + cfg = (var == "cgi_data") ? "environment" : var + notice = build_notice(:config => build_config("request.disable_#{cfg}": true), var.to_sym => {var => "hello"}) json = notice.to_json payload = JSON.parse(json) - expect(payload['request'][var]).to eq({}) + expect(payload["request"][var]).to eq({}) end end end - %w(url component action).each do |var| + %w[url component action].each do |var| it "does not filter top level #{var}" do - notice = build_notice(:config => build_config(:'request.filter_keys' => [var]), var.to_sym => 'hello') + notice = build_notice(:config => build_config("request.filter_keys": [var]), var.to_sym => "hello") json = notice.to_json payload = JSON.parse(json) - expect(payload['request'][var]).to eq 'hello' + expect(payload["request"][var]).to eq "hello" end end context "when url is excluded" do it "sends default value" do - notice = build_notice(:config => build_config(:'request.disable_url' => true), :url => 'hello') + notice = build_notice(config: build_config("request.disable_url": true), url: "hello") json = notice.to_json payload = JSON.parse(json) - expect(payload['request']['url']).to eq nil + expect(payload["request"]["url"]).to eq nil end end describe "#ignore?" do it "does not ignore an exception not matching ignore filters" do - config = build_config(:'exceptions.ignore' => ['Argument']) - config.exception_filter {|n| false } - notice = build_notice(error_class: 'ArgumentError', - config: config, - callbacks: config) + config = build_config("exceptions.ignore": ["Argument"]) + config.exception_filter { |n| false } + notice = build_notice(error_class: "ArgumentError", + config: config, + callbacks: config) expect(notice.ignore?).to eq false end it "ignores an exception with a matching error class" do - notice = build_notice(error_class: 'ArgumentError', - config: build_config(:'exceptions.ignore' => [ArgumentError])) + notice = build_notice(error_class: "ArgumentError", + config: build_config("exceptions.ignore": [ArgumentError])) expect(notice.ignore?).to eq true end it "ignores an exception with an equal error class name" do - notice = build_notice(error_class: 'ArgumentError', - config: build_config(:'exceptions.ignore' => ['ArgumentError'])) + notice = build_notice(error_class: "ArgumentError", + config: build_config("exceptions.ignore": ["ArgumentError"])) expect(notice.ignore?).to eq true # Expected ArgumentError to ignore ArgumentError end it "ignores an exception matching error class name" do - notice = build_notice(error_class: 'ArgumentError', - config: build_config(:'exceptions.ignore' => [/Error$/])) + notice = build_notice(error_class: "ArgumentError", + config: build_config("exceptions.ignore": [/Error$/])) expect(notice.ignore?).to eq true # Expected /Error$/ to ignore ArgumentError end it "ignores an exception that inherits from ignored error class" do - class ::FooError < ArgumentError ; end - notice = build_notice(exception: FooError.new('Oh noes!'), - config: build_config(:'exceptions.ignore' => [ArgumentError])) + class ::FooError < ArgumentError; end + notice = build_notice(exception: FooError.new("Oh noes!"), + config: build_config("exceptions.ignore": [ArgumentError])) expect(notice.ignore?).to eq true # Expected ArgumentError to ignore FooError end it "ignores an exception with a matching filter" do config = build_config - config.exception_filter {|n| n.error_class == 'ArgumentError' } - notice = build_notice(error_class: 'ArgumentError', - config: config) + config.exception_filter { |n| n.error_class == "ArgumentError" } + notice = build_notice(error_class: "ArgumentError", + config: config) expect(notice.ignore?).to eq true end @@ -293,14 +291,14 @@ class ::FooError < ArgumentError ; end expect { notice.ignore? }.not_to raise_error end - ignored_error_classes = %w( - ActiveRecord::RecordNotFound - AbstractController::ActionNotFound - ActionController::RoutingError - ActionController::InvalidAuthenticityToken - CGI::Session::CookieStore::TamperedWithCookie - ActionController::UnknownAction - ) + ignored_error_classes = %w[ + ActiveRecord::RecordNotFound + AbstractController::ActionNotFound + ActionController::RoutingError + ActionController::InvalidAuthenticityToken + CGI::Session::CookieStore::TamperedWithCookie + ActionController::UnknownAction + ] ignored_error_classes.each do |ignored_error_class| it "ignores #{ignored_error_class} error by default" do @@ -312,24 +310,24 @@ class ::FooError < ArgumentError ; end describe "#context" do it "merges local context" do - notice = build_notice(context: { local: 'local' }) - expect(notice.context).to eql({ local: 'local' }) + notice = build_notice(context: {local: "local"}) + expect(notice.context).to eql({local: "local"}) end it "merges global context" do - notice = build_notice(global_context: { global: 'global' }) - expect(notice.context).to eql({ global: 'global' }) + notice = build_notice(global_context: {global: "global"}) + expect(notice.context).to eql({global: "global"}) end it "merges exception context" do exception = Class.new(RuntimeError) do def to_honeybadger_context - { exception: 'exception' } + {exception: "exception"} end end notice = build_notice(exception: exception.new) - expect(notice.context).to eql({ exception: 'exception' }) + expect(notice.context).to eql({exception: "exception"}) end it "skips exception context when method isn't defined" do @@ -338,32 +336,32 @@ def to_honeybadger_context end it "merges context in order of precedence: local, exception, global" do - global_context = { global: 'global', local_override: 'global', exception_override: 'global' } + global_context = {global: "global", local_override: "global", exception_override: "global"} exception = Class.new(RuntimeError) do def to_honeybadger_context - { exception: 'exception', local_override: 'exception', exception_override: 'exception' } + {exception: "exception", local_override: "exception", exception_override: "exception"} end end - local_context = { local: 'local', local_override: 'local' } + local_context = {local: "local", local_override: "local"} notice = build_notice(exception: exception.new, global_context: global_context, context: local_context) expect(notice.context).to eq({ - global: 'global', - exception: 'exception', - local: 'local', - local_override: 'local', - exception_override: 'exception' + global: "global", + exception: "exception", + local: "local", + local_override: "local", + exception_override: "exception" }) end it "doesn't mutate global context" do - global_context = {'one' => 'two'} - expect { build_notice(global_context: global_context, context: {'foo' => 'bar'}) }.not_to change { Thread.current[:__honeybadger_context] } + global_context = {"one" => "two"} + expect { build_notice(global_context: global_context, context: {"foo" => "bar"}) }.not_to change { Thread.current[:__honeybadger_context] } end it "doesn't mutate local context" do - global_context = {'one' => 'two'} - hash = {'foo' => 'bar'} + global_context = {"one" => "two"} + hash = {"foo" => "bar"} expect { build_notice(global_context: global_context, context: hash) }.not_to change { hash } end @@ -373,22 +371,20 @@ def to_honeybadger_context end it "allows falsey values in context" do - global_context = {:debuga => true, :debugb => false} + global_context = {debuga: true, debugb: false} notice = build_notice(global_context: global_context) hash = JSON.parse(notice.to_json) - expect(hash['request']['context']).to eq({'debuga' => true, 'debugb' => false}) + expect(hash["request"]["context"]).to eq({"debuga" => true, "debugb" => false}) end - context 'with nested context' do + context "with nested context" do def build_instance_with_hb_context(value) Class.new do def initialize(value) @to_honeybadger_context = value end - def to_honeybadger_context - @to_honeybadger_context - end + attr_reader :to_honeybadger_context def to_json(_state) '"class with context"' @@ -399,18 +395,20 @@ def to_json(_state) let(:notice) { build_notice(global_context: global_context) } let(:global_context) do build_instance_with_hb_context( - { 'foo' => build_instance_with_hb_context( - { 'bar' => build_instance_with_hb_context({ 'baz' => 'qux' }) }) }) + {"foo" => build_instance_with_hb_context( + {"bar" => build_instance_with_hb_context({"baz" => "qux"})} + )} + ) end it "drills into the context values when they respond to to_honeybadger_context" do - expect(notice.context).to eq({ 'foo' => { 'bar' => { 'baz' => 'qux' }}}) + expect(notice.context).to eq({"foo" => {"bar" => {"baz" => "qux"}}}) end - context 'and a deeply nested context' do + context "and a deeply nested context" do let(:global_context) do (0..10).reduce({}) do |acc, depth| - build_instance_with_hb_context({ depth => acc }) + build_instance_with_hb_context({depth => acc}) end end @@ -418,27 +416,26 @@ def to_json(_state) # serialize/deserialize to simplify matching of the class at the end of the nesting ct = JSON.parse(notice.context.to_json) expect(ct).to eq({ - '10' => { '9' => { '8' => { '7' => { '6' => 'class with context' - }}}} + "10" => {"9" => {"8" => {"7" => {"6" => "class with context"}}}} }) end end - context 'and some non-nested contexts' do + context "and some non-nested contexts" do let(:global_context) do build_instance_with_hb_context( - { 'foo' => nil, - 'bar' => 'baz', - 'qux' => build_instance_with_hb_context({ 'fred' => 'thud' }), - 'array' => ['item'], - 'hash' => { 'key' => 'value' } - }) + {"foo" => nil, + "bar" => "baz", + "qux" => build_instance_with_hb_context({"fred" => "thud"}), + "array" => ["item"], + "hash" => {"key" => "value"}} + ) end it "drills in only where the object can drill" do expect(notice.context).to eq( - { 'foo' => nil, 'bar' => 'baz', 'qux' => { 'fred' => 'thud' }, - 'array' => ['item'], 'hash' => { 'key' => 'value' }} + {"foo" => nil, "bar" => "baz", "qux" => {"fred" => "thud"}, + "array" => ["item"], "hash" => {"key" => "value"}} ) end end @@ -449,77 +446,77 @@ def to_json(_state) context "with a rack environment hash" do it "extracts data from a rack environment hash" do url = "https://subdomain.happylane.com:100/test/file.rb?var=value&var2=value2" - params = {'var' => 'value', 'var2' => 'value2'} + params = {"var" => "value", "var2" => "value2"} env = Rack::MockRequest.env_for(url) notice = build_notice(rack_env: env) expect(notice.url).to eq url expect(notice.params).to eq params - expect(notice.cgi_data['REQUEST_METHOD']).to eq 'GET' + expect(notice.cgi_data["REQUEST_METHOD"]).to eq "GET" end it "prefers honeybadger.request.url to default PATH_INFO" do - url = 'https://subdomain.happylane.com:100/test/file.rb?var=value&var2=value2' + url = "https://subdomain.happylane.com:100/test/file.rb?var=value&var2=value2" env = Rack::MockRequest.env_for(url) - env['honeybadger.request.url'] = 'http://foo.com' + env["honeybadger.request.url"] = "http://foo.com" notice = build_notice(rack_env: env) - expect(notice.url).to eq 'http://foo.com' + expect(notice.url).to eq "http://foo.com" end context "with action_dispatch info" do - let(:params) { {'controller' => 'users', 'action' => 'index', 'id' => '7'} } + let(:params) { {"controller" => "users", "action" => "index", "id" => "7"} } it "extracts data from a rack environment hash " do - env = Rack::MockRequest.env_for('/', { 'action_dispatch.request.parameters' => params }) + env = Rack::MockRequest.env_for("/", {"action_dispatch.request.parameters" => params}) notice = build_notice(rack_env: env) expect(notice.params).to eq params - expect(notice.component).to eq params['controller'] - expect(notice.action).to eq params['action'] + expect(notice.component).to eq params["controller"] + expect(notice.action).to eq params["action"] end it "removes action_dispatch.request.parameters from cgi_data" do - env = Rack::MockRequest.env_for('/', { 'action_dispatch.request.parameters' => params }) + env = Rack::MockRequest.env_for("/", {"action_dispatch.request.parameters" => params}) notice = build_notice(rack_env: env) - expect(notice.cgi_data).not_to have_key 'action_dispatch.request.parameters' + expect(notice.cgi_data).not_to have_key "action_dispatch.request.parameters" end it "removes action_dispatch.request.request_parameters from cgi_data" do - env = Rack::MockRequest.env_for('/', { 'action_dispatch.request.request_parameters' => params }) + env = Rack::MockRequest.env_for("/", {"action_dispatch.request.request_parameters" => params}) notice = build_notice(rack_env: env) - expect(notice.cgi_data).not_to have_key 'action_dispatch.request.request_parameters' + expect(notice.cgi_data).not_to have_key "action_dispatch.request.request_parameters" end end it "extracts session data from a rack environment" do - session = { 'something' => 'some value' } - env = Rack::MockRequest.env_for('/', 'rack.session' => session) + session = {"something" => "some value"} + env = Rack::MockRequest.env_for("/", "rack.session" => session) notice = build_notice(rack_env: env) expect(notice.session).to eq session end it "prefers passed session data to rack session data" do - session = { 'something' => 'some value' } - env = Rack::MockRequest.env_for('/') + session = {"something" => "some value"} + env = Rack::MockRequest.env_for("/") notice = build_notice(rack_env: env, session: session) expect(notice.session).to eq session end - if defined?(::Rack) && Gem::Version.new(Rack.release) < Gem::Version.new('1.3') + if defined?(::Rack) && Gem::Version.new(Rack.release) < Gem::Version.new("1.3") it "parses params which are malformed in Rack >= 1.3" do - env = Rack::MockRequest.env_for('http://www.example.com/explode', :method => 'POST', :input => 'foo=bar&bar=baz%') + env = Rack::MockRequest.env_for("http://www.example.com/explode", method: "POST", input: "foo=bar&bar=baz%") expect { build_notice(rack_env: env) }.not_to raise_error end else it "fails gracefully when Rack params cannot be parsed" do - env = Rack::MockRequest.env_for('http://www.example.com/explode', :method => 'POST', :input => 'foo=bar&bar=baz%') + env = Rack::MockRequest.env_for("http://www.example.com/explode", method: "POST", input: "foo=bar&bar=baz%") notice = build_notice(rack_env: env) expect(notice.params.size).to eq 1 expect(notice.params[:error]).to match(/Failed to access params/) @@ -529,30 +526,30 @@ def to_json(_state) end it "prefers notice args to exception attributes" do - e = RuntimeError.new('Not very helpful') - notice = build_notice(exception: e, error_class: 'MyClass', error_message: 'Something very specific went wrong.') - expect(notice.error_class).to eq 'MyClass' - expect(notice.error_message).to eq 'Something very specific went wrong.' + e = RuntimeError.new("Not very helpful") + notice = build_notice(exception: e, error_class: "MyClass", error_message: "Something very specific went wrong.") + expect(notice.error_class).to eq "MyClass" + expect(notice.error_message).to eq "Something very specific went wrong." end describe "config[:'exceptions.unwrap']" do class TheCause < RuntimeError; end let(:notice) { build_notice(exception: exception, config: config) } - let(:exception) { RuntimeError.new('foo') } + let(:exception) { RuntimeError.new("foo") } context "when there isn't a cause" do context "and disabled (default)" do it "reports the exception" do - expect(notice.error_class).to eq 'RuntimeError' + expect(notice.error_class).to eq "RuntimeError" end end context "and enabled" do - let(:config) { build_config(:'exceptions.unwrap' => true) } + let(:config) { build_config("exceptions.unwrap": true) } it "reports the exception" do - expect(notice.error_class).to eq 'RuntimeError' + expect(notice.error_class).to eq "RuntimeError" end end end @@ -560,22 +557,22 @@ class TheCause < RuntimeError; end context "when there is a cause" do before do def exception.cause - TheCause.new(':trollface:') + TheCause.new(":trollface:") end end context "and disabled (default)" do it "reports the exception" do - expect(notice.error_class).to eq 'RuntimeError' + expect(notice.error_class).to eq "RuntimeError" end end context "and enabled" do - let(:config) { build_config(:'exceptions.unwrap' => true) } + let(:config) { build_config("exceptions.unwrap": true) } it "reports the cause" do - expect(notice.error_class).to eq 'TheCause' - expect(notice.error_message).to match /trollface/ + expect(notice.error_class).to eq "TheCause" + expect(notice.error_message).to match(/trollface/) end end end @@ -583,23 +580,23 @@ def exception.cause describe "#as_json" do it "sets the host name" do - notice = build_notice(config: build_config(hostname: 'foo')) - expect(notice.as_json[:server][:hostname]).to eq 'foo' + notice = build_notice(config: build_config(hostname: "foo")) + expect(notice.as_json[:server][:hostname]).to eq "foo" end it "sets the environment name" do - notice = build_notice(config: build_config(env: 'foo')) - expect(notice.as_json[:server][:environment_name]).to eq 'foo' + notice = build_notice(config: build_config(env: "foo")) + expect(notice.as_json[:server][:environment_name]).to eq "foo" end it "defaults api key to configuration" do notice = build_notice - expect(notice.as_json[:api_key]).to eq 'asdf' + expect(notice.as_json[:api_key]).to eq "asdf" end it "overrides the api key" do - notice = build_notice({api_key: 'zxcv'}) - expect(notice.as_json[:api_key]).to eq 'zxcv' + notice = build_notice({api_key: "zxcv"}) + expect(notice.as_json[:api_key]).to eq "zxcv" end it "sets the time in utc" do @@ -619,18 +616,18 @@ def exception.cause end it "trims error message to 64k" do - message = 'asdfghjkl'*12_000 + message = "asdfghjkl" * 12_000 e = StandardError.new(message) notice = build_notice(exception: e) expect(message.bytesize).to be > 65536 expect(65536...65556).to cover notice.as_json[:error][:message].bytesize end - it 'filters breadcrumb metadata' do - config[:'request.filter_keys'] = ['password'] - config[:'breadcrumbs.enabled'] = true + it "filters breadcrumb metadata" do + config[:"request.filter_keys"] = ["password"] + config[:"breadcrumbs.enabled"] = true coll = Honeybadger::Breadcrumbs::Collector.new(config) - bc = Honeybadger::Breadcrumbs::Breadcrumb.new(message: "test", metadata: { deep: {}, password: "my-password" }) + bc = Honeybadger::Breadcrumbs::Breadcrumb.new(message: "test", metadata: {deep: {}, password: "my-password"}) coll.add!(bc) notice = build_notice(breadcrumbs: coll) @@ -644,16 +641,16 @@ def exception.cause end end - describe 'public attributes' do - it 'assigns the same values from each opt and setter method' do + describe "public attributes" do + it "assigns the same values from each opt and setter method" do opts = { - api_key: 'custom api key', - error_message: 'badgers!', - error_class: 'MyError', + api_key: "custom api key", + error_message: "badgers!", + error_class: "MyError", backtrace: ["/path/to/file.rb:5 in `method'"], - fingerprint: 'some unique string', - tags: ['foo', 'bar'], - context: { user: 33 }, + fingerprint: "some unique string", + tags: ["foo", "bar"], + context: {user: 33} # TODO # controller: 'AuthController', # action: 'become_admin', @@ -679,29 +676,29 @@ def exception.cause end it "accepts fingerprint as string" do - notice = build_notice({fingerprint: 'foo' }) - expect(notice.fingerprint).to eq 'foo' - expect(notice.as_json[:error][:fingerprint]).to eq '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' + notice = build_notice({fingerprint: "foo"}) + expect(notice.fingerprint).to eq "foo" + expect(notice.as_json[:error][:fingerprint]).to eq "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" end it "accepts fingerprint responding to #call" do - notice = build_notice({fingerprint: double(call: 'foo')}) - expect(notice.fingerprint).to eq 'foo' - expect(notice.as_json[:error][:fingerprint]).to eq '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' + notice = build_notice({fingerprint: double(call: "foo")}) + expect(notice.fingerprint).to eq "foo" + expect(notice.as_json[:error][:fingerprint]).to eq "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" end it "accepts fingerprint using #to_s" do - object = double(to_s: 'foo') + object = double(to_s: "foo") notice = build_notice({fingerprint: object}) expect(notice.fingerprint).to eq object - expect(notice.as_json[:error][:fingerprint]).to eq '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' + expect(notice.as_json[:error][:fingerprint]).to eq "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" end context "fingerprint is a callback which accesses notice" do it "can access request information" do - notice = build_notice({params: { key: 'foo' }, fingerprint: lambda {|n| n.params[:key] }}) - expect(notice.fingerprint).to eq 'foo' - expect(notice.as_json[:error][:fingerprint]).to eq '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' + notice = build_notice({params: {key: "foo"}, fingerprint: lambda { |n| n.params[:key] }}) + expect(notice.fingerprint).to eq "foo" + expect(notice.as_json[:error][:fingerprint]).to eq "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" end end end @@ -720,25 +717,25 @@ def exception.cause RUBY @backtrace_array = ["my/file/backtrace:3", - "test/honeybadger/rack_test.rb:2:in `build_exception'", - "test/honeybadger/rack_test.rb:52:in `test_delivers_exception_from_rack'", - "foo/bar/baz.rb:28:in `run'"] + "test/honeybadger/rack_test.rb:2:in `build_exception'", + "test/honeybadger/rack_test.rb:52:in `test_delivers_exception_from_rack'", + "foo/bar/baz.rb:28:in `run'"] @exception = build_exception @exception.set_backtrace(@backtrace_array) end it "passes its backtrace filters for parsing" do - allow(config).to receive(:backtrace_filter).and_return('foo') - expect(Honeybadger::Backtrace).to receive(:parse).with(@backtrace_array, hash_including(filters: array_including('foo'))).and_return(double(to_a: [])) + allow(config).to receive(:backtrace_filter).and_return("foo") + expect(Honeybadger::Backtrace).to receive(:parse).with(@backtrace_array, hash_including(filters: array_including("foo"))).and_return(double(to_a: [])) build_notice({exception: @exception, config: config}).to_json end it "passes backtrace line filters for parsing" do - allow(config).to receive(:backtrace_filter).and_return('foo') + allow(config).to receive(:backtrace_filter).and_return("foo") @backtrace_array.each do |line| - expect(Honeybadger::Backtrace::Line).to receive(:parse).with(line, hash_including({filters: array_including('foo'), config: config})) + expect(Honeybadger::Backtrace::Line).to receive(:parse).with(line, hash_including({filters: array_including("foo"), config: config})) end build_notice({exception: @exception, callbacks: config, config: config}).to_json @@ -758,14 +755,14 @@ def exception.cause describe "#parsed_backtrace" do let(:backtrace) { ["my/file/backtrace.rb:3:in `magic'"] } - let(:exception) { build_exception({ backtrace: backtrace }) } + let(:exception) { build_exception({backtrace: backtrace}) } it "returns the parsed backtrace" do expect(Honeybadger::Backtrace).to receive(:parse).once.and_call_original - notice = build_notice({exception: exception, config: config}) - expect(notice.parsed_backtrace.first[:number]).to eq '3' - expect(notice.parsed_backtrace.first[:file]).to eq 'my/file/backtrace.rb' - expect(notice.parsed_backtrace.first[:method]).to eq 'magic' + notice = build_notice({exception: exception, config: config}) + expect(notice.parsed_backtrace.first[:number]).to eq "3" + expect(notice.parsed_backtrace.first[:file]).to eq "my/file/backtrace.rb" + expect(notice.parsed_backtrace.first[:method]).to eq "magic" end end @@ -773,22 +770,22 @@ def exception.cause context "when local variables are found" do it "sends local_variables in request payload" do notice = build_notice - hash = {'foo' => 'bar'} + hash = {"foo" => "bar"} allow(notice).to receive(:local_variables).and_return(hash) - expect(JSON.parse(notice.to_json)['request']['local_variables']).to eq(hash) + expect(JSON.parse(notice.to_json)["request"]["local_variables"]).to eq(hash) end end context "when local variables are not found" do it "doesn't send local_variables in request payload" do notice = build_notice - expect(JSON.parse(notice.to_json)['request']).not_to have_key 'local_variables' + expect(JSON.parse(notice.to_json)["request"]).not_to have_key "local_variables" end end context "when bad encodings exist in payload" do - let(:bad_string) { 'hello ümlaut'.force_encoding('BINARY') } - let(:invalid) { (100..1000).to_a.pack('c*').force_encoding('utf-8') } + let(:bad_string) { "hello ümlaut".force_encoding("BINARY") } + let(:invalid) { (100..1000).to_a.pack("c*").force_encoding("utf-8") } it "doesn't blow up with bad encoding" do notice = build_notice(error_message: bad_string) @@ -802,7 +799,7 @@ def exception.cause it "converts to utf-8" do notice = build_notice(error_message: bad_string) - expect(JSON.parse(notice.to_json)['error']['message']).to eq 'hello ??mlaut' + expect(JSON.parse(notice.to_json)["error"]["message"]).to eq "hello ??mlaut" end end @@ -810,8 +807,8 @@ def exception.cause notice = build_notice json = JSON.parse(notice.to_json) - json['error']['backtrace'].each do |line| - expect(line['source']).not_to be_empty + json["error"]["backtrace"].each do |line| + expect(line["source"]).not_to be_empty end end end @@ -819,12 +816,12 @@ def exception.cause describe "#local_variables", order: :defined do let(:notice) { build_notice(exception: exception, config: config) } let(:mock_binding) { @mock_binding } - let(:value) { double() } + let(:value) { double } let(:exception) do foo = value begin @mock_binding = binding - fail 'oops' + fail "oops" rescue $! end @@ -838,7 +835,7 @@ def exception.cause end context "when local variables are enabled" do - let(:config) { build_config(:'exceptions.local_variables' => true) } + let(:config) { build_config("exceptions.local_variables": true) } it "does not attempt to find them" do expect(notice.local_variables).to eq({}) @@ -868,7 +865,7 @@ def __honeybadger_bindings_stack=(val) end context "when local variables are enabled" do - let(:config) { build_config(:'exceptions.local_variables' => true) } + let(:config) { build_config("exceptions.local_variables": true) } it "finds the local variables from first frame of trace" do expect(notice.local_variables[:foo]).to eq(String(value)) @@ -876,14 +873,14 @@ def __honeybadger_bindings_stack=(val) context "when value responds to #to_honeybadger" do it "returns the #to_honeybadger value" do - allow(value).to receive(:to_honeybadger).and_return('baz') - expect(notice.local_variables[:foo]).to eq('baz') + allow(value).to receive(:to_honeybadger).and_return("baz") + expect(notice.local_variables[:foo]).to eq("baz") end end context "with an application trace" do before do - exception.__honeybadger_bindings_stack.unshift(double('Binding', :eval => nil, :source_location => [])) + exception.__honeybadger_bindings_stack.unshift(double("Binding", eval: nil, source_location: [])) config[:root] = File.dirname(__FILE__) end @@ -892,8 +889,8 @@ def __honeybadger_bindings_stack=(val) end it "filters local variable keys" do - config[:'request.filter_keys'] = ['foo'] - expect(notice.local_variables[:foo]).to eq '[FILTERED]' + config[:"request.filter_keys"] = ["foo"] + expect(notice.local_variables[:foo]).to eq "[FILTERED]" end context "and project_root is a Pathname" do @@ -923,31 +920,31 @@ def __honeybadger_bindings_stack=(val) context "adding tags" do context "directly" do it "converts String to tags Array" do - expect(build_notice(tags: ' foo , bar, , baz ').tags).to eq(%w(foo bar baz)) + expect(build_notice(tags: " foo , bar, , baz ").tags).to eq(%w[foo bar baz]) end it "accepts an Array" do - expect(build_notice(tags: [' foo ', ' bar', ' ', ' baz ']).tags).to eq(%w(foo bar baz)) + expect(build_notice(tags: [" foo ", " bar", " ", " baz "]).tags).to eq(%w[foo bar baz]) end it "accepts whitespace-delimited tags" do - expect(build_notice(tags: [' foo bar baz']).tags).to eq(%w(foo bar baz)) + expect(build_notice(tags: [" foo bar baz"]).tags).to eq(%w[foo bar baz]) end end context "from context" do it "converts String to tags Array" do - expect(build_notice(context: { tags: ' foo , , bar, baz ' }).tags).to eq(%w(foo bar baz)) + expect(build_notice(context: {tags: " foo , , bar, baz "}).tags).to eq(%w[foo bar baz]) end it "accepts an Array" do - expect(build_notice(tags: [' foo ', ' bar', ' ', ' baz ']).tags).to eq(%w(foo bar baz)) + expect(build_notice(tags: [" foo ", " bar", " ", " baz "]).tags).to eq(%w[foo bar baz]) end end context "from both" do it "merges tags" do - expect(build_notice(tags: 'foo , bar', context: { tags: ' foo , baz ' }).tags).to eq(%w(foo bar baz)) + expect(build_notice(tags: "foo , bar", context: {tags: " foo , baz "}).tags).to eq(%w[foo bar baz]) end end @@ -956,27 +953,31 @@ def __honeybadger_bindings_stack=(val) end it "allows non-word characters in tags while stripping whitespace" do - expect(build_notice(tags: 'word, with_underscore ,with space, with-dash,with$special*char').tags).to eq(%w(word with_underscore with space with-dash with$special*char)) + expect(build_notice(tags: "word, with_underscore ,with space, with-dash,with$special*char").tags).to eq(%w[word with_underscore with space with-dash with$special*char]) end end context "exception cause" do class CauseError < StandardError attr_reader :cause - def cause=(e); @cause = e; end + attr_writer :cause end class OriginalExceptionError < StandardError attr_reader :original_exception - def cause=(e); @original_exception = e; end + def cause=(e) + @original_exception = e + end end class ContinuedExceptionError < StandardError attr_reader :continued_exception - def cause=(e); @continued_exception = e; end + def cause=(e) + @continued_exception = e + end end - def build_cause(message: 'expected cause', backtrace: caller) + def build_cause(message: "expected cause", backtrace: caller) StandardError.new(message).tap do |cause| cause.set_backtrace(backtrace) end @@ -985,7 +986,7 @@ def build_cause(message: 'expected cause', backtrace: caller) [CauseError, OriginalExceptionError, ContinuedExceptionError].each do |error_class| context "when raising #{error_class} without a cause" do it "includes empty cause in payload" do - exception = error_class.new('badgers!') + exception = error_class.new("badgers!") causes = build_notice(exception: exception).as_json[:error][:causes] expect(causes.size).to eq 0 end @@ -993,20 +994,20 @@ def build_cause(message: 'expected cause', backtrace: caller) context "when raising #{error_class} with a cause" do it "includes the cause in the payload" do - exception = error_class.new('badgers!') + exception = error_class.new("badgers!") exception.cause = build_cause causes = build_notice(exception: exception).as_json[:error][:causes] expect(causes.size).to eq 1 - expect(causes[0][:class]).to eq 'StandardError' - expect(causes[0][:message]).to eq 'expected cause' + expect(causes[0][:class]).to eq "StandardError" + expect(causes[0][:message]).to eq "expected cause" expect(causes[0][:backtrace]).not_to be_empty end it "stops unwrapping at 5" do - exception = e = error_class.new('badgers!') + exception = e = error_class.new("badgers!") 0.upto(6) do - e.cause = c = error_class.new('expected cause') + e.cause = c = error_class.new("expected cause") e = c end @@ -1016,31 +1017,31 @@ def build_cause(message: 'expected cause', backtrace: caller) context "and the :cause option is also present" do it "prefers the option" do - exception = error_class.new('badgers!') + exception = error_class.new("badgers!") exception.cause = build_cause - causes = build_notice(exception: exception, cause: build_cause(message: 'this cause was passed explicitly')).as_json[:error][:causes] + causes = build_notice(exception: exception, cause: build_cause(message: "this cause was passed explicitly")).as_json[:error][:causes] expect(causes.size).to eq 1 - expect(causes[0][:class]).to eq 'StandardError' - expect(causes[0][:message]).to eq 'this cause was passed explicitly' + expect(causes[0][:class]).to eq "StandardError" + expect(causes[0][:message]).to eq "this cause was passed explicitly" expect(causes[0][:backtrace]).not_to be_empty end end context "and there is a current exception" do it "prefers the notice's exception's cause" do - exception = error_class.new('badgers!') + exception = error_class.new("badgers!") exception.cause = build_cause begin - raise StandardError.new('this should not be the cause') + raise StandardError.new("this should not be the cause") rescue causes = build_notice(exception: exception).as_json[:error][:causes] end expect(causes.size).to eq 1 - expect(causes[0][:class]).to eq 'StandardError' - expect(causes[0][:message]).to eq 'expected cause' + expect(causes[0][:class]).to eq "StandardError" + expect(causes[0][:message]).to eq "expected cause" expect(causes[0][:backtrace]).not_to be_empty end end @@ -1048,7 +1049,7 @@ def build_cause(message: 'expected cause', backtrace: caller) context "when raising #{error_class} with a non-exception cause" do it "includes empty cause in payload" do - exception = error_class.new('badgers!') + exception = error_class.new("badgers!") exception.cause = "Some reason you werent expecting" causes = build_notice(exception: exception).as_json[:error][:causes] expect(causes.size).to eq 0 @@ -1059,28 +1060,28 @@ def build_cause(message: 'expected cause', backtrace: caller) context "when there is a current global exception" do it "uses the global cause" do begin - raise StandardError.new('expected current cause') + raise StandardError.new("expected current cause") rescue causes = build_notice.as_json[:error][:causes] end expect(causes.size).to eq 1 - expect(causes[0][:class]).to eq 'StandardError' - expect(causes[0][:message]).to eq 'expected current cause' + expect(causes[0][:class]).to eq "StandardError" + expect(causes[0][:message]).to eq "expected current cause" expect(causes[0][:backtrace]).not_to be_empty end end context "when the cause has no backtrace" do it "includes cause with an empty backtrace in payload" do - exception = CauseError.new('error message') + exception = CauseError.new("error message") exception.cause = build_cause(backtrace: nil) causes = build_notice(exception: exception).as_json[:error][:causes] expect(causes.size).to eq(1) - expect(causes[0][:class]).to eq('StandardError') - expect(causes[0][:message]).to eq('expected cause') + expect(causes[0][:class]).to eq("StandardError") + expect(causes[0][:message]).to eq("expected cause") expect(causes[0][:backtrace]).to eq([]) end end @@ -1088,20 +1089,20 @@ def build_cause(message: 'expected cause', backtrace: caller) context "when the :cause option is present" do it "uses the cause option" do begin - raise StandardError.new('unexpected current cause') + raise StandardError.new("unexpected current cause") rescue causes = build_notice(cause: build_cause).as_json[:error][:causes] end expect(causes.size).to eq 1 - expect(causes[0][:class]).to eq 'StandardError' - expect(causes[0][:message]).to eq 'expected cause' + expect(causes[0][:class]).to eq "StandardError" + expect(causes[0][:message]).to eq "expected cause" expect(causes[0][:backtrace]).not_to be_empty end it "allows nil to disable cause" do begin - raise StandardError.new('unexpected current cause') + raise StandardError.new("unexpected current cause") rescue causes = build_notice(cause: nil).as_json[:error][:causes] end @@ -1113,25 +1114,25 @@ def build_cause(message: 'expected cause', backtrace: caller) describe "#cause=" do it "overrides the existing cause" do - notice = build_notice(cause: StandardError.new('unexpected cause')) - notice.cause = StandardError.new('expected cause') + notice = build_notice(cause: StandardError.new("unexpected cause")) + notice.cause = StandardError.new("expected cause") causes = notice.as_json[:error][:causes] expect(causes.size).to eq 1 - expect(causes[0][:message]).to eq 'expected cause' + expect(causes[0][:message]).to eq "expected cause" end it "removes cause when nil" do - notice = build_notice(cause: StandardError.new('unexpected cause')) + notice = build_notice(cause: StandardError.new("unexpected cause")) notice.cause = nil expect(notice.as_json[:error][:causes]).to eq([]) end it "changes the current cause" do - notice = build_notice(cause: StandardError.new('unexpected cause')) - cause = StandardError.new('expected cause') + notice = build_notice(cause: StandardError.new("unexpected cause")) + cause = StandardError.new("expected cause") notice.cause = cause @@ -1141,31 +1142,31 @@ def build_cause(message: 'expected cause', backtrace: caller) describe "#causes" do it "returns cause data" do - cause = StandardError.new('expected cause') + cause = StandardError.new("expected cause") cause.set_backtrace(caller) notice = build_notice(cause: cause) expect(notice.causes.size).to eq(1) - expect(notice.causes[0].error_message).to eq('expected cause') - expect(notice.causes[0].error_class).to eq('StandardError') + expect(notice.causes[0].error_message).to eq("expected cause") + expect(notice.causes[0].error_class).to eq("StandardError") expect(notice.causes[0].backtrace).to eq(caller) end it "allows override of cause data" do - notice = build_notice(cause: StandardError.new('unexpected cause')) + notice = build_notice(cause: StandardError.new("unexpected cause")) - notice.causes[0].error_message = 'expected cause' - notice.causes[0].error_class = 'expected class' + notice.causes[0].error_message = "expected cause" + notice.causes[0].error_class = "expected class" causes = notice.as_json[:error][:causes] - expect(causes[0][:message]).to eq 'expected cause' - expect(causes[0][:class]).to eq 'expected class' + expect(causes[0][:message]).to eq "expected cause" + expect(causes[0][:class]).to eq "expected class" end end context "when halted" do it ".halted? returns true" do - notice = build_notice(component: 'users_controller') + notice = build_notice(component: "users_controller") notice.halt! expect(notice.halted?).to eq(true) @@ -1174,7 +1175,7 @@ def build_cause(message: 'expected cause', backtrace: caller) context "when not halted" do it ".halted? returns false" do - notice = build_notice(component: 'users_controller') + notice = build_notice(component: "users_controller") expect(notice.halted?).to eq(false) end end diff --git a/spec/unit/honeybadger/notification_subscriber_spec.rb b/spec/unit/honeybadger/notification_subscriber_spec.rb index 09c9b5d78..2798766fc 100644 --- a/spec/unit/honeybadger/notification_subscriber_spec.rb +++ b/spec/unit/honeybadger/notification_subscriber_spec.rb @@ -1,6 +1,4 @@ -# encoding: utf-8 - -require 'honeybadger/notification_subscriber' +require "honeybadger/notification_subscriber" describe Honeybadger::ActiveSupportCacheMultiSubscriber do module ActiveSupport @@ -11,48 +9,48 @@ module Cache; end let(:payload) do obj = Object.new { - key: {'one' => 'data', 'object.cache_key' => obj }, - store: 'cache-store-name' + key: {"one" => "data", "object.cache_key" => obj}, + store: "cache-store-name" } end before do - allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key].keys[0]).and_return('one') - allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key].keys[1]).and_return('foo/bar') + allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key].keys[0]).and_return("one") + allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key].keys[1]).and_return("foo/bar") end subject { described_class.new.format_payload(payload) } it "returns a payload with all keys expanded and without cache values" do expect(subject).to be_a(Hash) - expect(subject[:key]).to eq(%w(one foo/bar)) - expect(subject[:store]).to eq('cache-store-name') + expect(subject[:key]).to eq(%w[one foo/bar]) + expect(subject[:store]).to eq("cache-store-name") end end context "with a cache_read_multi.active_support payload" do let(:payload) do { - key: ['one', Object.new], - hits: ['one'], - store: 'cache-store-name', + key: ["one", Object.new], + hits: ["one"], + store: "cache-store-name", super_operation: :fetch_multi } end before do - allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key][0]).and_return('one') - allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key][1]).and_return('foo/bar') - allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:hits][0]).and_return('one') + allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key][0]).and_return("one") + allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:key][1]).and_return("foo/bar") + allow(::ActiveSupport::Cache).to receive(:expand_cache_key).with(payload[:hits][0]).and_return("one") end subject { described_class.new.format_payload(payload) } it "returns a payload with all keys expanded" do expect(subject).to be_a(Hash) - expect(subject[:key]).to eq(%w(one foo/bar)) - expect(subject[:hits]).to eq(%w(one)) - expect(subject[:store]).to eq('cache-store-name') + expect(subject[:key]).to eq(%w[one foo/bar]) + expect(subject[:hits]).to eq(%w[one]) + expect(subject[:store]).to eq("cache-store-name") expect(subject[:super_operation]).to eq(:fetch_multi) end end diff --git a/spec/unit/honeybadger/plugin_spec.rb b/spec/unit/honeybadger/plugin_spec.rb index 8f1114e75..06889343f 100644 --- a/spec/unit/honeybadger/plugin_spec.rb +++ b/spec/unit/honeybadger/plugin_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugin' -require 'honeybadger/config' +require "honeybadger/plugin" +require "honeybadger/config" describe Honeybadger::Plugin::CALLER_FILE do it { should_not match "/foo/bar" } @@ -36,7 +36,7 @@ describe ".register" do it "returns a new plugin" do - instance = double() + instance = double allow(Honeybadger::Plugin).to receive(:new).and_return(instance) expect(Honeybadger::Plugin.register {}).to eq instance end @@ -44,37 +44,37 @@ it "registers a new plugin without a name" do expect(described_class.instances).to be_empty Honeybadger::Plugin.register {} - expect(described_class.instances[:'plugin_spec']).to be_a Honeybadger::Plugin + expect(described_class.instances[:plugin_spec]).to be_a Honeybadger::Plugin end it "registers a new plugin with a name" do expect(described_class.instances).to be_empty Honeybadger::Plugin.register(:foo) {} - expect(described_class.instances[:'foo']).to be_a Honeybadger::Plugin + expect(described_class.instances[:foo]).to be_a Honeybadger::Plugin end it "registers a new plugin with a String name" do expect(described_class.instances).to be_empty - Honeybadger::Plugin.register('foo') {} - expect(described_class.instances[:'foo']).to be_a Honeybadger::Plugin + Honeybadger::Plugin.register("foo") {} + expect(described_class.instances[:foo]).to be_a Honeybadger::Plugin end end describe ".load!" do it "loads all satisfied instances" do - Honeybadger::Plugin.instances.replace({:one => mock_plugin, :two => mock_plugin}) + Honeybadger::Plugin.instances.replace({one: mock_plugin, two: mock_plugin}) Honeybadger::Plugin.load!(config) end it "skips all unsatisfied instances" do - Honeybadger::Plugin.instances.replace({:one => mock_plugin(false), :two => mock_plugin(false)}) + Honeybadger::Plugin.instances.replace({one: mock_plugin(false), two: mock_plugin(false)}) Honeybadger::Plugin.load!(config) end context "when skipped by configuration" do before do - config[:plugins] = ['two', :three] - Honeybadger::Plugin.instances.replace({:one => mock_plugin(true, false), :two => mock_plugin(true), :three => mock_plugin(true)}) + config[:plugins] = ["two", :three] + Honeybadger::Plugin.instances.replace({one: mock_plugin(true, false), two: mock_plugin(true), three: mock_plugin(true)}) end it "skips instances" do @@ -90,7 +90,7 @@ end describe "#requirement" do - let(:block) { Proc.new {} } + let(:block) { proc {} } it "returns and Array of requirements" do expect(subject.requirement(&block)).to eq [block] @@ -102,7 +102,7 @@ end describe "#execution" do - let(:block) { Proc.new {} } + let(:block) { proc {} } it "returns an Array of executions" do expect(subject.execution(&block)).to eq [block] @@ -136,7 +136,7 @@ context "some requirements error" do before do plugin.requirement { true } - plugin.requirement { fail 'oops!' } + plugin.requirement { fail "oops!" } end it { should eq false } @@ -175,7 +175,7 @@ context "some executions fail" do before do - failing_execution = Proc.new { fail 'oh noes!' } + failing_execution = proc { fail "oh noes!" } plugin.executions.replace([mock_execution, failing_execution, mock_execution(false)]) end @@ -195,16 +195,16 @@ end def mock_plugin(ok = true, expected = ok) - plugin, expecting = Honeybadger::Plugin.new(:testing), double() + plugin, expecting = Honeybadger::Plugin.new(:testing), double expect(expecting).send(expected ? :to : :not_to, receive(:foo)) allow(plugin).to receive(:ok?).and_return(ok) - plugin.executions << Proc.new { expecting.foo } + plugin.executions << proc { expecting.foo } plugin end def mock_execution(positive = true) - expecting = double() + expecting = double expect(expecting).send(positive ? :to : :not_to, receive(:foo)) - Proc.new { expecting.foo } + proc { expecting.foo } end end diff --git a/spec/unit/honeybadger/plugins/breadcrumbs_spec.rb b/spec/unit/honeybadger/plugins/breadcrumbs_spec.rb index f23893ef3..b26c3c03d 100644 --- a/spec/unit/honeybadger/plugins/breadcrumbs_spec.rb +++ b/spec/unit/honeybadger/plugins/breadcrumbs_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/breadcrumbs' -require 'honeybadger/config' +require "honeybadger/plugins/breadcrumbs" +require "honeybadger/config" describe "Breadcrumbs Plugin" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } @@ -13,8 +13,8 @@ describe Honeybadger::Plugins::RailsBreadcrumbs do describe ".subscribe_to_notification" do let(:name) { "a.notification" } - let(:config) {{ foo: "bar" }} - let(:data) {{a: :b}} + let(:config) { {foo: "bar"} } + let(:data) { {a: :b} } it "registers with activesupport and delgates to send_breadcrumb_notification" do expect(described_class).to receive(:send_breadcrumb_notification).with(name, 10, config, data) @@ -56,7 +56,7 @@ describe ":message" do it "can allow a string" do - config = { message: "config message" } + config = {message: "config message"} expect(Honeybadger).to receive(:add_breadcrumb).with("config message", anything) described_class.send_breadcrumb_notification("noop", 100, config, {}) end @@ -95,7 +95,7 @@ end it "includes event if proc returns true" do - config = { exclude_when: ->(_){ false } } + config = {exclude_when: ->(_) { false }} expect(Honeybadger).to receive(:add_breadcrumb) described_class.send_breadcrumb_notification("name", 33, config, {}) end @@ -106,7 +106,7 @@ it "can filter metadata" do data = {a: :b, c: :d} removed_data = {c: :d} - config = { select_keys: [:a] } + config = {select_keys: [:a]} expect(Honeybadger).to receive(:add_breadcrumb).with(anything, hash_including(metadata: hash_not_including(removed_data))) described_class.send_breadcrumb_notification("_", 0, config, data) @@ -115,7 +115,7 @@ describe ":transform" do it "transforms data payload" do - data = {old: "data"} + data = {old: "data"} new_data = {new: "data"} config = { transform: lambda do |d| @@ -128,7 +128,6 @@ described_class.send_breadcrumb_notification("name", 33, config, data) end end - end end end diff --git a/spec/unit/honeybadger/plugins/delayed_job_spec.rb b/spec/unit/honeybadger/plugins/delayed_job_spec.rb index afcf3645b..7310543d1 100644 --- a/spec/unit/honeybadger/plugins/delayed_job_spec.rb +++ b/spec/unit/honeybadger/plugins/delayed_job_spec.rb @@ -1,15 +1,15 @@ -require 'honeybadger/config' -require 'honeybadger/agent' +require "honeybadger/config" +require "honeybadger/agent" begin - require 'delayed_job' - require 'honeybadger/plugins/delayed_job/plugin' + require "delayed_job" + require "honeybadger/plugins/delayed_job/plugin" describe "DelayedJob integration" do # Prepend the load path with delayed_job's spec directory so that we can take # advantage of their test backend: # https://github.com/collectiveidea/delayed_job/blob/master/spec/delayed/backend/test.rb - $:.unshift(File.join(Gem::Specification.find_by_name('delayed_job').full_gem_path, 'spec')) + $:.unshift(File.join(Gem::Specification.find_by_name("delayed_job").full_gem_path, "spec")) Delayed::Worker.backend = :test class ExceptionTester @@ -30,7 +30,7 @@ def will_raise @worker = Delayed::Worker.new end - after { Delayed::Job.delete_all } + after { Delayed::Job.delete_all } context "when a method is delayed" do let(:method_name) { :null_method } @@ -52,8 +52,8 @@ def will_raise context "and a threshold is set" do let(:method_name) { :will_raise } - before { ::Honeybadger.config[:'delayed_job.attempt_threshold'] = 2 } - after { ::Honeybadger.config[:'delayed_job.attempt_threshold'] = 0 } + before { ::Honeybadger.config[:"delayed_job.attempt_threshold"] = 2 } + after { ::Honeybadger.config[:"delayed_job.attempt_threshold"] = 0 } it "does not notify Honeybadger on first occurence" do expect(Honeybadger).not_to receive(:notify) diff --git a/spec/unit/honeybadger/plugins/faktory_spec.rb b/spec/unit/honeybadger/plugins/faktory_spec.rb index 920fab72d..f4803b637 100644 --- a/spec/unit/honeybadger/plugins/faktory_spec.rb +++ b/spec/unit/honeybadger/plugins/faktory_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/faktory' -require 'honeybadger/config' +require "honeybadger/plugins/faktory" +require "honeybadger/config" describe "Faktory Dependency" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } @@ -22,8 +22,8 @@ def self.configure_worker end end - let(:faktory_config) { double('config', :error_handlers => []) } - let(:chain) { double('chain', :prepend => true) } + let(:faktory_config) { double("config", error_handlers: []) } + let(:chain) { double("chain", prepend: true) } before do Object.const_set(:Faktory, shim) @@ -39,35 +39,37 @@ def self.configure_worker end describe "error handler" do - let(:exception) { RuntimeError.new('boom') } + let(:exception) { RuntimeError.new("boom") } before do Honeybadger::Plugin.instances[:faktory].load!(config) end context "not within job execution" do - let(:handler_context) { {context: 'Failed Hard', event: {} } } + let(:handler_context) { {context: "Failed Hard", event: {}} } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: handler_context }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: handler_context}).once faktory_config.error_handlers[0].call(exception, handler_context) end end context "within job execution" do - let(:handler_context) { {context: 'Job raised exception', job: job } } + let(:handler_context) { {context: "Job raised exception", job: job} } let(:job) { first_invocation } - let(:retried_invocation) { {'retry' => retry_limit, 'failure' => failure, 'jobtype' => 'JobType'} } - let(:first_invocation) { {'retry' => retry_limit, 'jobtype' => 'JobType'} } - let(:failure) { { 'retry_count' => attempt - 1 } } + let(:retried_invocation) { {"retry" => retry_limit, "failure" => failure, "jobtype" => "JobType"} } + let(:first_invocation) { {"retry" => retry_limit, "jobtype" => "JobType"} } + let(:failure) { {"retry_count" => attempt - 1} } let(:retry_limit) { 5 } let(:attempt) { 0 } - let(:error_payload) {{ - parameters: handler_context, - component: 'JobType', - action: 'perform' - }} + let(:error_payload) { + { + parameters: handler_context, + component: "JobType", + action: "perform" + } + } it "notifies Honeybadger" do expect(Honeybadger).to receive(:notify).with(exception, error_payload).once @@ -78,7 +80,7 @@ def self.configure_worker let(:job) { retried_invocation } let(:retry_limit) { 1 } let(:attempt) { 0 } - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'faktory.attempt_threshold' => 5) } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "faktory.attempt_threshold": 5) } it "doesn't notify Honeybadger" do expect(Honeybadger).not_to receive(:notify) diff --git a/spec/unit/honeybadger/plugins/karafka_spec.rb b/spec/unit/honeybadger/plugins/karafka_spec.rb index b85374713..5ff21879d 100644 --- a/spec/unit/honeybadger/plugins/karafka_spec.rb +++ b/spec/unit/honeybadger/plugins/karafka_spec.rb @@ -1,6 +1,6 @@ -require 'honeybadger/plugins/karafka' -require 'honeybadger/karafka' -require 'honeybadger/config' +require "honeybadger/plugins/karafka" +require "honeybadger/karafka" +require "honeybadger/config" describe "Karafka Dependency" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } @@ -22,9 +22,9 @@ def self.monitor end end end - let(:monitor) { double('monitor') } - let(:event) { double('event') } - let(:errors_listener) { double('errors listener') } + let(:monitor) { double("monitor") } + let(:event) { double("event") } + let(:errors_listener) { double("errors listener") } before do Object.const_set(:Karafka, shim) @@ -39,8 +39,8 @@ def self.monitor end context "when Insights instrumentation is enabled" do - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'insights.enabled' => true) } - let(:insights_listener) { double('insights listener') } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "insights.enabled": true) } + let(:insights_listener) { double("insights listener") } before do allow(::Honeybadger::Karafka::InsightsListener).to receive(:new).and_return(insights_listener) diff --git a/spec/unit/honeybadger/plugins/lambda_spec.rb b/spec/unit/honeybadger/plugins/lambda_spec.rb index ce074e9cb..e0cbedd18 100644 --- a/spec/unit/honeybadger/plugins/lambda_spec.rb +++ b/spec/unit/honeybadger/plugins/lambda_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/lambda' -require 'honeybadger/config' +require "honeybadger/plugins/lambda" +require "honeybadger/config" describe "Lambda Plugin" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, backend: :test, api_key: "noop") } @@ -13,14 +13,14 @@ Honeybadger::Backend::Test.notifications[:notices].clear end - it 'forces sync mode' do + it "forces sync mode" do expect(config[:sync]).to eq false Honeybadger::Plugin.instances[:lambda].load!(config) expect(config[:sync]).to eq true end describe "hb_wrap_handler decorator" do - it 'auto-captures errors from class methods when decorator is used' do + it "auto-captures errors from class methods when decorator is used" do expect(Honeybadger).to receive(:notify).with kind_of(RuntimeError) Honeybadger::Plugin.instances[:lambda].load!(config) @@ -36,7 +36,7 @@ def self.test_handler(event:, context:) expect { klass.test_handler(event: {}, context: {}) }.to raise_error(RuntimeError, "An exception") end - it 'auto-captures errors from main methods when decorator is used' do + it "auto-captures errors from main methods when decorator is used" do expect(Honeybadger).to receive(:notify).with kind_of(RuntimeError) Honeybadger::Plugin.instances[:lambda].load!(config) @@ -53,18 +53,20 @@ def test_handler(event:, context:) end describe "notice injection" do - let(:lambda_data) { { - "function" => "lambda_fn", - "handler" => "the.handler", - "memory" => 128 - } } + let(:lambda_data) { + { + "function" => "lambda_fn", + "handler" => "the.handler", + "memory" => 128 + } + } before do expect(Honeybadger::Util::Lambda).to receive(:trace_id).and_return("abc123") expect(Honeybadger::Util::Lambda).to receive(:normalized_data).and_return(lambda_data) end - it 'adds details to notice data and includes trace_id into context' do + it "adds details to notice data and includes trace_id into context" do agent = Honeybadger::Agent.new(config) Honeybadger::Plugin.instances[:lambda].load!(config) agent.notify("test") @@ -72,7 +74,7 @@ def test_handler(event:, context:) expect(notice.component).to eq "lambda_fn" expect(notice.action).to eq "the.handler" expect(notice.context[:lambda_trace_id]).to eq "abc123" - expect(notice.details).to eq({ "Lambda Details" => lambda_data }) + expect(notice.details).to eq({"Lambda Details" => lambda_data}) end end end diff --git a/spec/unit/honeybadger/plugins/local_variables_spec.rb b/spec/unit/honeybadger/plugins/local_variables_spec.rb index a93c0faf4..071baf7fa 100644 --- a/spec/unit/honeybadger/plugins/local_variables_spec.rb +++ b/spec/unit/honeybadger/plugins/local_variables_spec.rb @@ -1,17 +1,17 @@ -require 'honeybadger/plugins/local_variables' -require 'honeybadger/config' +require "honeybadger/plugins/local_variables" +require "honeybadger/config" describe "Local variables integration", order: :defined do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } before do Honeybadger::Plugin.instances[:local_variables].reset! - config[:'exceptions.local_variables'] = config_enabled + config[:"exceptions.local_variables"] = config_enabled end subject { Exception.new } - context "when binding_of_caller isn't installed", :unless => defined?(::BindingOfCaller) do + context "when binding_of_caller isn't installed", unless: defined?(::BindingOfCaller) do let(:config_enabled) { true } it "doesn't install extensions" do @@ -20,7 +20,7 @@ end end - context "when binding_of_caller is installed", :if => defined?(::BindingOfCaller) do + context "when binding_of_caller is installed", if: defined?(::BindingOfCaller) do context "and disabled by configuration" do let(:config_enabled) { false } @@ -48,7 +48,7 @@ end it "warns the logger" do - expect(config.logger).to receive(:warn).with /better_errors/ + expect(config.logger).to receive(:warn).with(/better_errors/) Honeybadger::Plugin.instances[:local_variables].load!(config) end end @@ -68,31 +68,31 @@ describe "#set_backtrace" do context "call stack does not match current file" do it "changes the bindings stack" do - expect { subject.set_backtrace(['foo.rb:1']) }.to change(subject, :__honeybadger_bindings_stack).from([]) + expect { subject.set_backtrace(["foo.rb:1"]) }.to change(subject, :__honeybadger_bindings_stack).from([]) end end context "call stack includes current file" do before do - allow(subject).to receive(:caller).and_return(["#{File.expand_path('../../../../../lib/honeybadger/plugins/local_variables.rb', __FILE__)}:1"]) + allow(subject).to receive(:caller).and_return(["#{File.expand_path("../../../../../lib/honeybadger/plugins/local_variables.rb", __FILE__)}:1"]) end it "does not change the bindings stack" do - expect { subject.set_backtrace(['foo.rb:1']) }.not_to change(subject, :__honeybadger_bindings_stack).from([]) + expect { subject.set_backtrace(["foo.rb:1"]) }.not_to change(subject, :__honeybadger_bindings_stack).from([]) end end context "call stack includes a non-matching line" do before do - allow(subject).to receive(:caller).and_return(['(foo)']) + allow(subject).to receive(:caller).and_return(["(foo)"]) end it "skips the non-matching line" do - expect { subject.set_backtrace(['foo.rb:1']) }.not_to raise_error + expect { subject.set_backtrace(["foo.rb:1"]) }.not_to raise_error end it "changes the bindings stack" do - expect { subject.set_backtrace(['foo.rb:1']) }.to change(subject, :__honeybadger_bindings_stack).from([]) + expect { subject.set_backtrace(["foo.rb:1"]) }.to change(subject, :__honeybadger_bindings_stack).from([]) end end end diff --git a/spec/unit/honeybadger/plugins/net_http_spec.rb b/spec/unit/honeybadger/plugins/net_http_spec.rb index 8fad12bf6..293f4e2ba 100644 --- a/spec/unit/honeybadger/plugins/net_http_spec.rb +++ b/spec/unit/honeybadger/plugins/net_http_spec.rb @@ -1,8 +1,8 @@ -require 'honeybadger/plugins/net_http' -require 'honeybadger/config' +require "honeybadger/plugins/net_http" +require "honeybadger/config" describe "Net::HTTP integration" do - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'insights.enabled' => true) } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "insights.enabled": true) } before do Honeybadger::Plugin.instances[:net_http].reset! @@ -18,38 +18,38 @@ context "report domain only" do it "contains a domain" do - expect(Honeybadger).to receive(:event).with('request.net_http', hash_including({method: "GET", status: 200, host: "example.com"})) - Net::HTTP.get(URI.parse('http://example.com')) + expect(Honeybadger).to receive(:event).with("request.net_http", hash_including({method: "GET", status: 200, host: "example.com"})) + Net::HTTP.get(URI.parse("http://example.com")) end end context "report domain and full url" do - before { config[:'net_http.insights.full_url'] = true } + before { config[:"net_http.insights.full_url"] = true } it "contains a domain and url" do - expect(Honeybadger).to receive(:event).with('request.net_http', hash_including({method: "GET", status: 200, url: "http://example.com", host: "example.com"})) - Net::HTTP.get(URI.parse('http://example.com')) + expect(Honeybadger).to receive(:event).with("request.net_http", hash_including({method: "GET", status: 200, url: "http://example.com", host: "example.com"})) + Net::HTTP.get(URI.parse("http://example.com")) end end context "metrics collection enabled" do - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'insights.enabled' => true, :'net_http.insights.metrics' => true) } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "insights.enabled": true, "net_http.insights.metrics": true) } context "report domain only" do it "contains a domain" do - expect(Honeybadger).to receive(:event).with('request.net_http', hash_including({method: "GET", status: 200, host: "example.com"})) - expect(Honeybadger).to receive(:gauge).with('duration.request', hash_including({method: "GET", status: 200, host: "example.com"})) - Net::HTTP.get(URI.parse('http://example.com')) + expect(Honeybadger).to receive(:event).with("request.net_http", hash_including({method: "GET", status: 200, host: "example.com"})) + expect(Honeybadger).to receive(:gauge).with("duration.request", hash_including({method: "GET", status: 200, host: "example.com"})) + Net::HTTP.get(URI.parse("http://example.com")) end end context "report domain and full url" do - before { config[:'net_http.insights.full_url'] = true } + before { config[:"net_http.insights.full_url"] = true } it "contains a domain and url" do - expect(Honeybadger).to receive(:event).with('request.net_http', hash_including({method: "GET", status: 200, url: "http://example.com", host: "example.com"})) - expect(Honeybadger).to receive(:gauge).with('duration.request', hash_including({method: "GET", status: 200, host: "example.com"})) - Net::HTTP.get(URI.parse('http://example.com')) + expect(Honeybadger).to receive(:event).with("request.net_http", hash_including({method: "GET", status: 200, url: "http://example.com", host: "example.com"})) + expect(Honeybadger).to receive(:gauge).with("duration.request", hash_including({method: "GET", status: 200, host: "example.com"})) + Net::HTTP.get(URI.parse("http://example.com")) end end end diff --git a/spec/unit/honeybadger/plugins/passenger_spec.rb b/spec/unit/honeybadger/plugins/passenger_spec.rb index e7743021d..1dd1d8410 100644 --- a/spec/unit/honeybadger/plugins/passenger_spec.rb +++ b/spec/unit/honeybadger/plugins/passenger_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/passenger' -require 'honeybadger/config' +require "honeybadger/plugins/passenger" +require "honeybadger/config" describe "Passenger integration" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } @@ -16,7 +16,7 @@ end context "when passenger is installed" do - let(:shim) { double('PhusionPassenger') } + let(:shim) { double("PhusionPassenger") } before do Object.const_set(:PhusionPassenger, shim) diff --git a/spec/unit/honeybadger/plugins/resque_spec.rb b/spec/unit/honeybadger/plugins/resque_spec.rb index 563adad10..950ac3df1 100644 --- a/spec/unit/honeybadger/plugins/resque_spec.rb +++ b/spec/unit/honeybadger/plugins/resque_spec.rb @@ -1,6 +1,6 @@ -require 'honeybadger/plugins/resque' -require 'honeybadger/config' -require 'honeybadger/agent' +require "honeybadger/plugins/resque" +require "honeybadger/config" +require "honeybadger/agent" class TestWorker extend Honeybadger::Plugins::Resque::Extension @@ -8,7 +8,7 @@ class TestWorker describe TestWorker do describe "::on_failure_with_honeybadger" do - let(:error) { RuntimeError.new('Failure in Honeybadger resque_spec') } + let(:error) { RuntimeError.new("Failure in Honeybadger resque_spec") } shared_examples_for "reports exceptions" do specify do @@ -22,7 +22,7 @@ class TestWorker expect(Honeybadger).not_to receive(:notify) expect { described_class.around_perform_with_honeybadger(1, 2, 3) do - fail 'foo' + fail "foo" end }.to raise_error(RuntimeError) end @@ -39,12 +39,12 @@ class TestWorker describe "with worker not extending Resque::Plugins::Retry" do context "when send exceptions on retry enabled" do - before { ::Honeybadger.config[:'resque.resque_retry.send_exceptions_when_retrying'] = true } + before { ::Honeybadger.config[:"resque.resque_retry.send_exceptions_when_retrying"] = true } it_behaves_like "reports exceptions" end context "when send exceptions on retry disabled" do - before { ::Honeybadger.config[:'resque.resque_retry.send_exceptions_when_retrying'] = false } + before { ::Honeybadger.config[:"resque.resque_retry.send_exceptions_when_retrying"] = false } it_behaves_like "reports exceptions" end end @@ -57,12 +57,12 @@ class TestWorker def self.retry_criteria_valid?(e) end end - allow(described_class).to receive(:retry_criteria_valid?). - and_return(retry_criteria_valid) + allow(described_class).to receive(:retry_criteria_valid?) + .and_return(retry_criteria_valid) end context "when send exceptions on retry enabled" do - before { ::Honeybadger.config[:'resque.resque_retry.send_exceptions_when_retrying'] = true } + before { ::Honeybadger.config[:"resque.resque_retry.send_exceptions_when_retrying"] = true } context "with retry criteria invalid" do it_behaves_like "reports exceptions" @@ -75,7 +75,7 @@ def self.retry_criteria_valid?(e) end context "when send exceptions on retry disabled" do - before { ::Honeybadger.config[:'resque.resque_retry.send_exceptions_when_retrying'] = false } + before { ::Honeybadger.config[:"resque.resque_retry.send_exceptions_when_retrying"] = false } context "with retry criteria invalid" do it_behaves_like "reports exceptions" @@ -88,13 +88,12 @@ def self.retry_criteria_valid?(e) context "and retry_criteria_valid? raises exception" do it "should report raised error to honeybadger" do - other_error = StandardError.new('stubbed Honeybadger error in retry_criteria_valid?') + other_error = StandardError.new("stubbed Honeybadger error in retry_criteria_valid?") allow(described_class).to receive(:retry_criteria_valid?).and_raise(other_error) expect(Honeybadger).to receive(:notify).with(other_error, hash_including(parameters: {job_arguments: [1, 2, 3]}, sync: true)) described_class.on_failure_with_honeybadger(error, 1, 2, 3) end end - end end end @@ -110,7 +109,7 @@ def self.retry_criteria_valid?(e) it "raises exceptions" do expect { described_class.around_perform_with_honeybadger do - fail 'foo' + fail "foo" end }.to raise_error(RuntimeError, /foo/) end diff --git a/spec/unit/honeybadger/plugins/shoryuken_spec.rb b/spec/unit/honeybadger/plugins/shoryuken_spec.rb index 137af40a5..ff08f8ef8 100644 --- a/spec/unit/honeybadger/plugins/shoryuken_spec.rb +++ b/spec/unit/honeybadger/plugins/shoryuken_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/shoryuken' -require 'honeybadger/config' +require "honeybadger/plugins/shoryuken" +require "honeybadger/config" RSpec.describe "Shoryuken Dependency" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } @@ -17,7 +17,8 @@ context "when shoryuken is installed" do let(:shim) do Class.new do - def self.configure_server; end + def self.configure_server + end end end @@ -44,16 +45,16 @@ class TestShoryukenWorker < Honeybadger::Plugins::Shoryuken::Middleware; end RSpec.describe TestShoryukenWorker do let(:sqs_msg) do double("SqsMsg", - queue_name: "queue", - attributes: { "ApproximateReceiveCount" => receive_count }, - data: double("SqsMsgData", message_id: rand.to_s)) + queue_name: "queue", + attributes: {"ApproximateReceiveCount" => receive_count}, + data: double("SqsMsgData", message_id: rand.to_s)) end - let(:body) { { "key" => "value" } } + let(:body) { {"key" => "value"} } shared_examples_for "notifies Honeybadger" do it do expect(Honeybadger).to receive(:notify).with(kind_of(RuntimeError), - hash_including(parameters: { body: { "key" => "value" } })) + hash_including(parameters: {body: {"key" => "value"}})) expect { job_execution }.to raise_error(RuntimeError) end @@ -62,13 +63,11 @@ class TestShoryukenWorker < Honeybadger::Plugins::Shoryuken::Middleware; end shared_examples_for "batch notifies Honeybadger" do it do expect(Honeybadger).to receive(:notify).with(kind_of(RuntimeError), - hash_including(parameters: - { batch: [ - { "key" => "value" }, - { "key" => "value" } - ] - } - )) + hash_including(parameters: + {batch: [ + {"key" => "value"}, + {"key" => "value"} + ]})) expect { job_execution }.to raise_error(RuntimeError) end @@ -95,8 +94,8 @@ class TestShoryukenWorker < Honeybadger::Plugins::Shoryuken::Middleware; end end context "when an attempt threshold is configured" do - before { ::Honeybadger.config[:'shoryuken.attempt_threshold'] = 2 } - after { ::Honeybadger.config[:'shoryuken.attempt_threshold'] = 0 } + before { ::Honeybadger.config[:"shoryuken.attempt_threshold"] = 2 } + after { ::Honeybadger.config[:"shoryuken.attempt_threshold"] = 0 } include_examples "doesn't notify Honeybadger" diff --git a/spec/unit/honeybadger/plugins/sidekiq_spec.rb b/spec/unit/honeybadger/plugins/sidekiq_spec.rb index f45fed486..6bef29736 100644 --- a/spec/unit/honeybadger/plugins/sidekiq_spec.rb +++ b/spec/unit/honeybadger/plugins/sidekiq_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/sidekiq' -require 'honeybadger/config' +require "honeybadger/plugins/sidekiq" +require "honeybadger/config" describe "Sidekiq Dependency" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } @@ -25,9 +25,9 @@ def self.default_configuration end end - let(:sidekiq_options) {{}} + let(:sidekiq_options) { {} } let(:sidekiq) { double(Sidekiq, error_handlers: [], options: sidekiq_options) } - let(:chain) { double('chain', :prepend => true) } + let(:chain) { double("chain", prepend: true) } before do Object.const_set(:Sidekiq, shim) @@ -39,7 +39,7 @@ def self.default_configuration context "when version is less than 3" do before do - ::Sidekiq.const_set(:VERSION, '2.17.7') + ::Sidekiq.const_set(:VERSION, "2.17.7") end it "adds the server middleware" do @@ -55,7 +55,7 @@ def self.default_configuration context "when version is 3 or greater" do before do - ::Sidekiq.const_set(:VERSION, '3.0.0') + ::Sidekiq.const_set(:VERSION, "3.0.0") end it "adds the error handler" do @@ -64,27 +64,27 @@ def self.default_configuration end describe "error handler" do - let(:exception) { RuntimeError.new('boom') } + let(:exception) { RuntimeError.new("boom") } let(:retry_config) { true } let(:attempt) { 1 } - let(:job) { { 'retry' => retry_config, 'retry_count' => attempt == 1 ? nil : attempt - 1} } + let(:job) { {"retry" => retry_config, "retry_count" => (attempt == 1) ? nil : attempt - 1} } before do Honeybadger::Plugin.instances[:sidekiq].load!(config) end - context 'Sidekiq 4.2.3 and later' do + context "Sidekiq 4.2.3 and later" do # The data we're interested in is inside the job subhash - let(:job_context) { {context: 'Job raised exception', job: job } } + let(:job_context) { {context: "Job raised exception", job: job} } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: nil }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: nil}).once sidekiq.error_handlers[0].call(exception, job_context) end context "when an attempt threshold is configured" do let(:attempt) { 1 } - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'sidekiq.attempt_threshold' => 3) } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "sidekiq.attempt_threshold": 3) } it "doesn't notify Honeybadger" do expect(Honeybadger).not_to receive(:notify) @@ -96,17 +96,17 @@ def self.default_configuration let(:attempt) { 2 } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: nil }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: nil}).once sidekiq.error_handlers[0].call(exception, job_context) end end context "and custom max_retries are exausted" do - let(:sidekiq_options) { { max_retries: 2 } } + let(:sidekiq_options) { {max_retries: 2} } let(:attempt) { 2 } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: nil }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: nil}).once sidekiq.error_handlers[0].call(exception, job_context) end end @@ -115,43 +115,43 @@ def self.default_configuration let(:attempt) { 3 } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: nil }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: nil}).once sidekiq.error_handlers[0].call(exception, job_context) end end end context "when the class info is present" do - let(:job) { { 'class' => 'HardWorker' } } + let(:job) { {"class" => "HardWorker"} } it "includes the class as a component" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: 'HardWorker', action: 'perform' }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: "HardWorker", action: "perform"}).once sidekiq.error_handlers[0].call(exception, job_context) end end context "when the worker is wrapped" do - let(:job) { { 'class' => 'HardWorker', 'wrapped' => 'WrappedWorker' } } + let(:job) { {"class" => "HardWorker", "wrapped" => "WrappedWorker"} } it "includes the class as a component" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: 'WrappedWorker', action: 'perform' }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: "WrappedWorker", action: "perform"}).once sidekiq.error_handlers[0].call(exception, job_context) end end end - context 'Sidekiq earlier than 4.2.3' do + context "Sidekiq earlier than 4.2.3" do # The data we're interested in is at the top level of the params let(:job_context) { job } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: nil }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: nil}).once sidekiq.error_handlers[0].call(exception, job_context) end context "when an attempt threshold is configured" do let(:attempt) { 1 } - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'sidekiq.attempt_threshold' => 3) } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "sidekiq.attempt_threshold": 3) } it "doesn't notify Honeybadger" do expect(Honeybadger).not_to receive(:notify) @@ -163,7 +163,7 @@ def self.default_configuration let(:retry_config) { 1 } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: nil }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: nil}).once sidekiq.error_handlers[0].call(exception, job_context) end end @@ -172,7 +172,7 @@ def self.default_configuration let(:attempt) { 3 } it "notifies Honeybadger" do - expect(Honeybadger).to receive(:notify).with(exception, { parameters: job_context, component: nil }).once + expect(Honeybadger).to receive(:notify).with(exception, {parameters: job_context, component: nil}).once sidekiq.error_handlers[0].call(exception, job_context) end end @@ -182,21 +182,37 @@ def self.default_configuration end describe "collectors" do - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, :'insights.enabled' => true, :'sidekiq.insights.cluster_collection' => true) } - let(:queues) { [double('queue', name: 'default', latency: 1, size: 10)] } - let(:workers) { [['pid', 'tid', double('work', payload: { queue: 'queue_name' })]] } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, "insights.enabled": true, "sidekiq.insights.cluster_collection": true) } + let(:queues) { [double("queue", name: "default", latency: 1, size: 10)] } + let(:workers) { [["pid", "tid", double("work", payload: {queue: "queue_name"})]] } let(:processes) { [{"concurrency" => 1, "busy" => 1}] } let(:stats_shim) do Class.new do - def workers_size; end - def processes_size; end - def processed; end - def failed; end - def scheduled_size; end - def enqueued; end - def dead_size; end - def retry_size; end + def workers_size + end + + def processes_size + end + + def processed + end + + def failed + end + + def scheduled_size + end + + def enqueued + end + + def dead_size + end + + def retry_size + end + def as_json {} end @@ -230,7 +246,7 @@ def as_json it "can execute collectors" do Honeybadger::Plugin.instances[:sidekiq].collectors.each do |options, collect_block| - Honeybadger::Plugin::CollectorExecution.new('sidekiq', config, options, &collect_block).call + Honeybadger::Plugin::CollectorExecution.new("sidekiq", config, options, &collect_block).call end end end diff --git a/spec/unit/honeybadger/plugins/sucker_punch_spec.rb b/spec/unit/honeybadger/plugins/sucker_punch_spec.rb index 6ae5f8c9e..f66555039 100644 --- a/spec/unit/honeybadger/plugins/sucker_punch_spec.rb +++ b/spec/unit/honeybadger/plugins/sucker_punch_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/sucker_punch' -require 'honeybadger/config' +require "honeybadger/plugins/sucker_punch" +require "honeybadger/config" describe "SuckerPunch Dependency" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } diff --git a/spec/unit/honeybadger/plugins/thor_spec.rb b/spec/unit/honeybadger/plugins/thor_spec.rb index bc8f6c688..af3c7c291 100644 --- a/spec/unit/honeybadger/plugins/thor_spec.rb +++ b/spec/unit/honeybadger/plugins/thor_spec.rb @@ -1,5 +1,5 @@ -require 'honeybadger/plugins/thor' -require 'honeybadger/config' +require "honeybadger/plugins/thor" +require "honeybadger/config" describe "Thor Dependency" do let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true) } diff --git a/spec/unit/honeybadger/rack/error_notifier_spec.rb b/spec/unit/honeybadger/rack/error_notifier_spec.rb index d4583de23..db2ad1870 100644 --- a/spec/unit/honeybadger/rack/error_notifier_spec.rb +++ b/spec/unit/honeybadger/rack/error_notifier_spec.rb @@ -1,10 +1,11 @@ -require 'honeybadger/rack/error_notifier' +require "honeybadger/rack/error_notifier" class BacktracedException < Exception attr_accessor :backtrace def initialize(opts) @backtrace = opts[:backtrace] end + def set_backtrace(bt) @backtrace = bt end @@ -12,9 +13,9 @@ def set_backtrace(bt) def build_exception(opts = {}) backtrace = ["test/honeybadger/rack_test.rb:15:in `build_exception'", - "test/honeybadger/rack_test.rb:52:in `test_delivers_exception_from_rack'", - "/Users/josh/Developer/.rvm/gems/ruby-1.9.3-p0/gems/mocha-0.10.5/lib/mocha/integration/mini_test/version_230_to_262.rb:28:in `run'"] - opts = { :backtrace => backtrace }.merge(opts) + "test/honeybadger/rack_test.rb:52:in `test_delivers_exception_from_rack'", + "/Users/josh/Developer/.rvm/gems/ruby-1.9.3-p0/gems/mocha-0.10.5/lib/mocha/integration/mini_test/version_230_to_262.rb:28:in `run'"] + opts = {backtrace: backtrace}.merge(opts) BacktracedException.new(opts) end @@ -23,20 +24,20 @@ def build_exception(opts = {}) let(:config) { agent.config } it "calls the upstream app with the environment" do - environment = { 'key' => 'value' } - app = lambda { |env| ['response', {}, env] } + environment = {"key" => "value"} + app = lambda { |env| ["response", {}, env] } stack = Honeybadger::Rack::ErrorNotifier.new(app, agent) response = stack.call(environment) - expect(response).to eq ['response', {}, environment] + expect(response).to eq ["response", {}, environment] end it "delivers an exception raised while calling an upstream app" do allow(agent).to receive(:notify) exception = build_exception - environment = { 'key' => 'value' } + environment = {"key" => "value"} app = lambda do |env| raise exception end @@ -56,11 +57,11 @@ def build_exception(opts = {}) it "delivers an exception in rack.exception" do allow(agent).to receive(:notify) exception = build_exception - environment = { 'key' => 'value' } + environment = {"key" => "value"} - response = [200, {}, ['okay']] + response = [200, {}, ["okay"]] app = lambda do |env| - env['rack.exception'] = exception + env["rack.exception"] = exception response end stack = Honeybadger::Rack::ErrorNotifier.new(app, agent) @@ -75,11 +76,11 @@ def build_exception(opts = {}) it "delivers an exception in sinatra.error" do allow(agent).to receive(:notify) exception = build_exception - environment = { 'key' => 'value' } + environment = {"key" => "value"} - response = [200, {}, ['okay']] + response = [200, {}, ["okay"]] app = lambda do |env| - env['sinatra.error'] = exception + env["sinatra.error"] = exception response end stack = Honeybadger::Rack::ErrorNotifier.new(app, agent) @@ -95,7 +96,7 @@ def build_exception(opts = {}) Honeybadger.context(foo: :bar) expect(Honeybadger.get_context).to eq({foo: :bar}) - app = lambda { |env| ['response', {}, env] } + app = lambda { |env| ["response", {}, env] } stack = Honeybadger::Rack::ErrorNotifier.new(app, agent) stack.call({}) diff --git a/spec/unit/honeybadger/rack/user_feedback_spec.rb b/spec/unit/honeybadger/rack/user_feedback_spec.rb index 788d752fc..3e1ebc55c 100644 --- a/spec/unit/honeybadger/rack/user_feedback_spec.rb +++ b/spec/unit/honeybadger/rack/user_feedback_spec.rb @@ -1,12 +1,12 @@ -require 'honeybadger/rack/user_feedback' -require 'honeybadger/config' +require "honeybadger/rack/user_feedback" +require "honeybadger/config" describe Honeybadger::Rack::UserFeedback do let(:agent) { Honeybadger::Agent.new } let(:config) { agent.config } let(:main_app) do lambda do |env| - env['honeybadger.error_id'] = honeybadger_id if defined?(honeybadger_id) + env["honeybadger.error_id"] = honeybadger_id if defined?(honeybadger_id) [200, {}, [""]] end end @@ -24,8 +24,8 @@ context "a project root is configured" do let(:tmp_dir) { TMP_DIR } - let(:template_dir) { File.join(tmp_dir, 'lib', 'honeybadger', 'templates') } - let(:template_file) { File.join(template_dir, 'feedback_form.erb') } + let(:template_dir) { File.join(tmp_dir, "lib", "honeybadger", "templates") } + let(:template_file) { File.join(template_dir, "feedback_form.erb") } before do FileUtils.mkdir_p(template_dir) @@ -35,7 +35,7 @@ context "custom template is implemented" do before do - File.open(template_file, 'w') { |f| f.write 'custom feedback form' } + File.write(template_file, "custom feedback form") end it "renders with custom template" do @@ -47,7 +47,7 @@ context "there is no honeybadger id" do it "does not modify the output" do - expect(result[2][0]).to eq '' + expect(result[2][0]).to eq "" end end end diff --git a/spec/unit/honeybadger/rack/user_informer_spec.rb b/spec/unit/honeybadger/rack/user_informer_spec.rb index 29d972b61..c3bb5c115 100644 --- a/spec/unit/honeybadger/rack/user_informer_spec.rb +++ b/spec/unit/honeybadger/rack/user_informer_spec.rb @@ -1,24 +1,24 @@ -require 'honeybadger/rack/user_informer' -require 'honeybadger/config' +require "honeybadger/rack/user_informer" +require "honeybadger/config" describe Honeybadger::Rack::UserInformer do let(:agent) { Honeybadger::Agent.new } let(:config) { agent.config } - it 'modifies output if there is a honeybadger id' do + it "modifies output if there is a honeybadger id" do main_app = lambda do |env| - env['honeybadger.error_id'] = 1 + env["honeybadger.error_id"] = 1 [200, {}, [""]] end informer_app = Honeybadger::Rack::UserInformer.new(main_app, agent) result = informer_app.call({}) - expect(result[2][0]).to eq 'Honeybadger Error 1' + expect(result[2][0]).to eq "Honeybadger Error 1" expect(result[1]["Content-Length"].to_i).to eq 19 end - it 'does not modify output if there is no honeybadger id' do + it "does not modify output if there is no honeybadger id" do main_app = lambda do |env| [200, {}, [""]] end @@ -26,7 +26,6 @@ result = informer_app.call({}) - expect(result[2][0]).to eq '' + expect(result[2][0]).to eq "" end end - diff --git a/spec/unit/honeybadger/timer_spec.rb b/spec/unit/honeybadger/timer_spec.rb index 23b5cadf4..73961bc2c 100644 --- a/spec/unit/honeybadger/timer_spec.rb +++ b/spec/unit/honeybadger/timer_spec.rb @@ -1,15 +1,13 @@ -# encoding: utf-8 - describe Honeybadger::Timer do describe "#payloads" do let(:metric) { described_class.new(name, attributes) } let(:name) { "perform" } - let(:attributes) { { foo: "bar" } } + let(:attributes) { {foo: "bar"} } subject { metric.payloads } before { metric.record(1) } - it { should eq [{ total: 1, avg: 1.0, latest: 1, max: 1, min: 1 }] } + it { should eq [{total: 1, avg: 1.0, latest: 1, max: 1, min: 1}] } end end diff --git a/spec/unit/honeybadger/util/http_spec.rb b/spec/unit/honeybadger/util/http_spec.rb index 93da9c7df..a2bab9d37 100644 --- a/spec/unit/honeybadger/util/http_spec.rb +++ b/spec/unit/honeybadger/util/http_spec.rb @@ -1,10 +1,10 @@ -require 'net/http' -require 'logger' -require 'honeybadger/util/http' -require 'honeybadger/config' +require "net/http" +require "logger" +require "honeybadger/util/http" +require "honeybadger/config" describe Honeybadger::Util::HTTP do - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, api_key: 'abc123') } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, api_key: "abc123") } let(:logger) { config.logger } subject { described_class.new(config) } @@ -14,40 +14,40 @@ it { should respond_to :get } it "sends a user agent with version number" do - http = stub_http - expect(http).to receive(:post).with(kind_of(String), kind_of(String), hash_including({'User-Agent' => "HB-Ruby #{Honeybadger::VERSION}; #{RUBY_VERSION}; #{RUBY_PLATFORM}"})) + http = stub_http + expect(http).to receive(:post).with(kind_of(String), kind_of(String), hash_including({"User-Agent" => "HB-Ruby #{Honeybadger::VERSION}; #{RUBY_VERSION}; #{RUBY_PLATFORM}"})) http_post end context "when proxy settings are configured" do let(:config) { Honeybadger::Config.new({ - :api_key => 'abc123', - :'connection.proxy_host' => 'some.host', - :'connection.proxy_port' => 88, - :'connection.proxy_user' => 'login', - :'connection.proxy_pass' => 'passwd' + api_key: "abc123", + "connection.proxy_host": "some.host", + "connection.proxy_port": 88, + "connection.proxy_user": "login", + "connection.proxy_pass": "passwd" }) } it "gets from Honeybadger when using an HTTP proxy" do - http = stub_http + http = stub_http proxy = double(new: http) allow(Net::HTTP).to receive(:Proxy).and_return(proxy) - expect(http).to receive(:get).with('/v1/foo') - expect(Net::HTTP).to receive(:Proxy).with('some.host', 88, 'login', 'passwd') + expect(http).to receive(:get).with("/v1/foo") + expect(Net::HTTP).to receive(:Proxy).with("some.host", 88, "login", "passwd") http_get end it "posts to Honeybadger when using an HTTP proxy" do - http = stub_http + http = stub_http proxy = double(new: http) allow(Net::HTTP).to receive(:Proxy).and_return(proxy) - expect(http).to receive(:post).with('/v1/foo', kind_of(String), Honeybadger::Util::HTTP::HEADERS.merge({ 'X-API-Key' => 'abc123'})) - expect(Net::HTTP).to receive(:Proxy).with('some.host', 88, 'login', 'passwd') + expect(http).to receive(:post).with("/v1/foo", kind_of(String), Honeybadger::Util::HTTP::HEADERS.merge({"X-API-Key" => "abc123"})) + expect(Net::HTTP).to receive(:Proxy).with("some.host", 88, "login", "passwd") http_post end @@ -90,7 +90,7 @@ context "non-success response from server" do it "logs failure" do - stub_http(response: Net::HTTPClientError.new('1.2', '429', 'Too Many Requests')) + stub_http(response: Net::HTTPClientError.new("1.2", "429", "Too Many Requests")) expect(logger).to receive(:debug).with(/code=429/) http_post end @@ -98,7 +98,7 @@ context "non-success response from server on #get" do it "logs failure" do - stub_http(response: Net::HTTPClientError.new('1.2', '429', 'Too Many Requests')) + stub_http(response: Net::HTTPClientError.new("1.2", "429", "Too Many Requests")) expect(logger).to receive(:debug).with(/code=429/) http_get end @@ -106,7 +106,7 @@ context "failure response from server" do it "logs failure" do - stub_http(response: Net::HTTPServerError.new('1.2', '500', 'Internal Error')) + stub_http(response: Net::HTTPServerError.new("1.2", "500", "Internal Error")) expect(logger).to receive(:debug).with(/code=500/) http_post end @@ -115,7 +115,7 @@ context "when encountering exceptions" do context "HTTP connection setup problems" do it "should not be rescued" do - proxy = double() + proxy = double allow(proxy).to receive(:new).and_raise(NoMemoryError) allow(Net::HTTP).to receive(:Proxy).and_return(proxy) expect { http_post }.to raise_error(NoMemoryError) @@ -144,17 +144,17 @@ context "SSL" do it "posts to the right url for non-ssl" do - config[:'connection.secure'] = false + config[:"connection.secure"] = false http = stub_http url = "http://api.honeybadger.io:80/v1/foo" uri = URI.parse(url) - expect(http).to receive(:post).with(uri.path, anything, Honeybadger::Util::HTTP::HEADERS.merge({ 'X-API-Key' => 'abc123'})) + expect(http).to receive(:post).with(uri.path, anything, Honeybadger::Util::HTTP::HEADERS.merge({"X-API-Key" => "abc123"})) http_post end it "post to the right path for ssl" do http = stub_http - expect(http).to receive(:post).with('/v1/foo', anything, Honeybadger::Util::HTTP::HEADERS.merge({ 'X-API-Key' => 'abc123'})) + expect(http).to receive(:post).with("/v1/foo", anything, Honeybadger::Util::HTTP::HEADERS.merge({"X-API-Key" => "abc123"})) http_post end @@ -163,7 +163,7 @@ uri = URI.parse(url) real_http = Net::HTTP.new(uri.host, uri.port) - allow(real_http).to receive(:post).and_return(double(code: '200')) + allow(real_http).to receive(:post).and_return(double(code: "200")) proxy = double(new: real_http) allow(Net::HTTP).to receive(:Proxy).and_return(proxy) @@ -178,7 +178,7 @@ it "uses the default DEFAULT_CERT_FILE if asked to" do expect(File).to receive(:exist?).with(OpenSSL::X509::DEFAULT_CERT_FILE).and_return(true) - config[:'connection.system_ssl_cert_chain'] = true + config[:"connection.system_ssl_cert_chain"] = true http = subject.send(:setup_http_connection) expect(http.ca_file).not_to eq config.local_cert_path @@ -186,11 +186,11 @@ end it "uses a custom ca bundle if asked to" do - config[:'connection.ssl_ca_bundle_path'] = '/test/blargh.crt' + config[:"connection.ssl_ca_bundle_path"] = "/test/blargh.crt" http = subject.send(:setup_http_connection) expect(http.ca_file).not_to eq config.local_cert_path - expect(http.ca_file).to eq '/test/blargh.crt' + expect(http.ca_file).to eq "/test/blargh.crt" end it "uses the default cert (OpenSSL::X509::DEFAULT_CERT_FILE) only if explicitly told to" do @@ -212,7 +212,7 @@ end it "does not use ssl if not secure" do - config[:'connection.secure'] = false + config[:"connection.secure"] = false http = subject.send(:setup_http_connection) expect(http.port).to eq 80 end @@ -232,14 +232,14 @@ end it "allow override of the open timeout" do - config[:'connection.http_open_timeout'] = 4 + config[:"connection.http_open_timeout"] = 4 http = stub_http expect(http).to receive(:open_timeout=).with(4) http_post end it "allow override of the read timeout" do - config[:'connection.http_read_timeout'] = 10 + config[:"connection.http_read_timeout"] = 10 http = stub_http expect(http).to receive(:read_timeout=).with(10) http_post @@ -255,22 +255,22 @@ parts = decompressed.split("\n").map { |part| JSON.parse(part) } expect(parts.length).to be(2) - Net::HTTPSuccess.new('1.2', '200', 'OK') + Net::HTTPSuccess.new("1.2", "200", "OK") end http_post_newline_delimited end end def http_post - subject.post('/v1/foo', double('Notice', to_json: '{}')) + subject.post("/v1/foo", double("Notice", to_json: "{}")) end def http_post_newline_delimited ts = DateTime.now.new_offset(0).rfc3339 - subject.post_newline_delimited('/v1/foo', [{ts: ts, event_type: "test"}, {ts: ts, event_type: "test2"}]) + subject.post_newline_delimited("/v1/foo", [{ts: ts, event_type: "test"}, {ts: ts, event_type: "test2"}]) end def http_get - subject.get('/v1/foo') + subject.get("/v1/foo") end end diff --git a/spec/unit/honeybadger/util/lambda_spec.rb b/spec/unit/honeybadger/util/lambda_spec.rb index 2a8a352d0..4c4ed2e7b 100644 --- a/spec/unit/honeybadger/util/lambda_spec.rb +++ b/spec/unit/honeybadger/util/lambda_spec.rb @@ -1,4 +1,4 @@ -require 'honeybadger/util/lambda' +require "honeybadger/util/lambda" describe Honeybadger::Util::Lambda do subject { described_class } diff --git a/spec/unit/honeybadger/util/request_hash_spec.rb b/spec/unit/honeybadger/util/request_hash_spec.rb index ae3668c65..238b058ff 100644 --- a/spec/unit/honeybadger/util/request_hash_spec.rb +++ b/spec/unit/honeybadger/util/request_hash_spec.rb @@ -1,33 +1,33 @@ -require 'honeybadger/util/request_hash' +require "honeybadger/util/request_hash" describe Honeybadger::Util::RequestHash, if: defined?(Rack) do - let(:rack_env) { Rack::MockRequest.env_for('/') } + let(:rack_env) { Rack::MockRequest.env_for("/") } subject { described_class.from_env(rack_env) } describe "cgi_data" do it "includes all HTTP headers" do - rack_env['HTTP_SOME_RANDOM_HEADER'] = 'foo' - expect(subject[:cgi_data]['HTTP_SOME_RANDOM_HEADER']).to eq 'foo' + rack_env["HTTP_SOME_RANDOM_HEADER"] = "foo" + expect(subject[:cgi_data]["HTTP_SOME_RANDOM_HEADER"]).to eq "foo" end it "includes approved CGI variables" do - rack_env['REMOTE_ADDR'] = '127.0.0.1' - expect(subject[:cgi_data]['REMOTE_ADDR']).to eq '127.0.0.1' + rack_env["REMOTE_ADDR"] = "127.0.0.1" + expect(subject[:cgi_data]["REMOTE_ADDR"]).to eq "127.0.0.1" end it "excludes RAW_POST_DATA" do - rack_env['RAW_POST_DATA'] = 'foo' - expect(subject[:cgi_data]).not_to have_key 'RAW_POST_DATA' + rack_env["RAW_POST_DATA"] = "foo" + expect(subject[:cgi_data]).not_to have_key "RAW_POST_DATA" end it "excludes QUERY_STRING" do - rack_env['QUERY_STRING'] = 'foo' - expect(subject[:cgi_data]).not_to have_key 'QUERY_STRING' + rack_env["QUERY_STRING"] = "foo" + expect(subject[:cgi_data]).not_to have_key "QUERY_STRING" end it "excludes symbols" do - rack_env[:foo] = 'foo' + rack_env[:foo] = "foo" expect(subject[:cgi_data]).not_to have_key :foo end end diff --git a/spec/unit/honeybadger/util/request_payload_spec.rb b/spec/unit/honeybadger/util/request_payload_spec.rb index 991d7fcbe..0cbbe0c23 100644 --- a/spec/unit/honeybadger/util/request_payload_spec.rb +++ b/spec/unit/honeybadger/util/request_payload_spec.rb @@ -1,4 +1,4 @@ -require 'honeybadger/util/request_payload' +require "honeybadger/util/request_payload" class TestSanitizer def sanitize(data) @@ -21,14 +21,14 @@ def filter_url(string) subject { described_class.build } Honeybadger::Util::RequestPayload::DEFAULTS.each_pair do |key, value| - it "defaults #{ key } to default value" do + it "defaults #{key} to default value" do expect(subject[key]).to eq value end end it "can be intiailized with a Hash" do - subject = described_class.build({ component: 'foo' }) - expect(subject[:component]).to eq 'foo' + subject = described_class.build({component: "foo"}) + expect(subject[:component]).to eq "foo" end it "returns a Hash" do @@ -36,28 +36,28 @@ def filter_url(string) end it "rejects invalid keys" do - subject = described_class.build({ foo: 'foo' }) + subject = described_class.build({foo: "foo"}) expect(subject).not_to have_key(:foo) end it "defaults nil keys" do - subject = described_class.build({ params: nil }) + subject = described_class.build({params: nil}) expect(subject[:params]).to eq({}) end it "sanitizes payload with injected sanitizer" do - expect(sanitizer).to receive(:sanitize).with('foo') - described_class.build({ sanitizer: sanitizer, component: 'foo' }) + expect(sanitizer).to receive(:sanitize).with("foo") + described_class.build({sanitizer: sanitizer, component: "foo"}) end it "sanitizes the url key" do - expect(sanitizer).to receive(:filter_url).with('foo/bar') - described_class.build({ sanitizer: sanitizer, url: 'foo/bar' }) + expect(sanitizer).to receive(:filter_url).with("foo/bar") + described_class.build({sanitizer: sanitizer, url: "foo/bar"}) end it "sanitizes the request cookies" do - expect(sanitizer).to receive(:filter_cookies).with('abc=hello') - described_class.build({ sanitizer: sanitizer, cgi_data: { "HTTP_COOKIE" => "abc=hello" } }) + expect(sanitizer).to receive(:filter_cookies).with("abc=hello") + described_class.build({sanitizer: sanitizer, cgi_data: {"HTTP_COOKIE" => "abc=hello"}}) end it "converts Hash to JSON" do @@ -65,7 +65,7 @@ def filter_url(string) result = JSON.parse(subject.to_json) expect(result.size).to eq original.size - subject.each_pair do |k,v| + subject.each_pair do |k, v| expect(result[k.to_s]).to eq v end end diff --git a/spec/unit/honeybadger/util/revision_spec.rb b/spec/unit/honeybadger/util/revision_spec.rb index 8f63fb4c4..7023c0886 100644 --- a/spec/unit/honeybadger/util/revision_spec.rb +++ b/spec/unit/honeybadger/util/revision_spec.rb @@ -1,13 +1,13 @@ -require 'honeybadger/util/revision' +require "honeybadger/util/revision" describe Honeybadger::Util::Revision do after do - ENV.delete('HEROKU_SLUG_COMMIT') + ENV.delete("HEROKU_SLUG_COMMIT") end it "detects capistrano revision" do root = FIXTURES_PATH.to_s - expect(Honeybadger::Util::Revision.detect(root)).to eq('rspec testing') + expect(Honeybadger::Util::Revision.detect(root)).to eq("rspec testing") end it "detects git revision" do @@ -15,8 +15,8 @@ end it "detects heroku revision" do - ENV['HEROKU_SLUG_COMMIT'] = 'heroku revision' - expect(Honeybadger::Util::Revision.detect).to eq('heroku revision') + ENV["HEROKU_SLUG_COMMIT"] = "heroku revision" + expect(Honeybadger::Util::Revision.detect).to eq("heroku revision") end it "returns nil when detected value is a blank string" do diff --git a/spec/unit/honeybadger/util/sanitizer_spec.rb b/spec/unit/honeybadger/util/sanitizer_spec.rb index d9e6ed253..3684add0b 100644 --- a/spec/unit/honeybadger/util/sanitizer_spec.rb +++ b/spec/unit/honeybadger/util/sanitizer_spec.rb @@ -1,22 +1,20 @@ -# encoding: utf-8 - -require 'honeybadger/util/sanitizer' +require "honeybadger/util/sanitizer" describe Honeybadger::Util::Sanitizer do its(:max_depth) { should eq 20 } describe "#sanitize" do - let(:deep_hash) { {}.tap {|h| 30.times.each {|i| h = h[i.to_s] = {:string => 'string'} }} } - let(:expected_hash) { {}.tap {|h| max_depth.times.each {|i| h = h[i.to_s] = (i < max_depth-1 ? {:string => 'string'} : '[DEPTH]') }} } + let(:deep_hash) { {}.tap { |h| 30.times.each { |i| h = h[i.to_s] = {string: "string"} } } } + let(:expected_hash) { {}.tap { |h| max_depth.times.each { |i| h = h[i.to_s] = ((i < max_depth - 1) ? {string: "string"} : "[DEPTH]") } } } let(:sanitized_hash) { described_class.new(max_depth: max_depth).sanitize(deep_hash) } let(:max_depth) { 10 } it "truncates nested hashes to max_depth" do - expect(sanitized_hash['0']).to eq(expected_hash['0']) + expect(sanitized_hash["0"]).to eq(expected_hash["0"]) end it "does not allow infinite recursion" do - hash = {:a => :a} + hash = {a: :a} hash[:hash] = hash payload = described_class.new.sanitize(request: {params: hash}) expect(payload[:request][:params][:hash]).to eq "[RECURSION]" @@ -30,35 +28,35 @@ end it "converts string-like objects to strings" do - object = double(to_s: 'expected value') - expect(described_class.new.sanitize(object)).to eq('expected value') + object = double(to_s: "expected value") + expect(described_class.new.sanitize(object)).to eq("expected value") end it "indicates raised when the object can't be converted to string" do object = double allow(object).to receive(:to_s).and_raise("error while converting to string") - expect(described_class.new.sanitize(object)).to eq('[RAISED]') + expect(described_class.new.sanitize(object)).to eq("[RAISED]") end it "identifies basic objects which would otherwise cause errors" do - expect(described_class.new.sanitize(BasicObject.new)).to eq('#') + expect(described_class.new.sanitize(BasicObject.new)).to eq("#") end it "converts objects with #to_honeybadger before sanitizing" do - object = double(to_honeybadger: { string: double(to_honeybadger: 'expected value') }) - expect(described_class.new.sanitize(object)).to eq({ string: 'expected value' }) + object = double(to_honeybadger: {string: double(to_honeybadger: "expected value")}) + expect(described_class.new.sanitize(object)).to eq({string: "expected value"}) end it "indicates raised when #to_honeybadger raises an exception" do object = double allow(object).to receive(:to_honeybadger).and_raise("error in #to_honeybadger") - expect(described_class.new.sanitize(object)).to eq('[RAISED]') + expect(described_class.new.sanitize(object)).to eq("[RAISED]") end it "halts infinite recursion of #to_honeybadger" do object = double allow(object).to receive(:to_honeybadger).and_return(object) - expect(described_class.new.sanitize(object)).to eq('[RECURSION]') + expect(described_class.new.sanitize(object)).to eq("[RECURSION]") end it "halts infinite recursion of different objects responding to #to_honeybadger" do @@ -68,20 +66,20 @@ object } object = to_honeybadger.call - expect(described_class.new.sanitize(object)).to eq('[DEPTH]') + expect(described_class.new.sanitize(object)).to eq("[DEPTH]") end it "ensures #to_hash is called on objects that support it" do - expect { described_class.new.sanitize(:session => { :object => double(:to_hash => {}) }) }.not_to raise_error + expect { described_class.new.sanitize(session: {object: double(to_hash: {})}) }.not_to raise_error end it "ensures #to_ary is called on objects that support it" do - expect { described_class.new.sanitize(:session => { :object => double(:to_ary => {}) }) }.not_to raise_error + expect { described_class.new.sanitize(session: {object: double(to_ary: {})}) }.not_to raise_error end it "allocates under 1/2 objects vs. the original hash.", if: defined?(AllocationStats) do o = AllocationStats.trace { deep_hash } - expect { sanitized_hash }.to allocate_under((o.new_allocations.size/2)).objects + expect { sanitized_hash }.to allocate_under((o.new_allocations.size / 2)).objects end it "includes nils in arrays" do @@ -91,7 +89,7 @@ it "sanitizes objects which return #inspect output from #to_s" do object = double(to_s: '#') - expect(described_class.new.sanitize(object)).to eq('#') + expect(described_class.new.sanitize(object)).to eq("#") end it "doesn't sanitize #inspect output when passed explicitly as a String" do @@ -100,66 +98,66 @@ end context "with bad encodings" do - let(:string) { 'hello ümlaut' } + let(:string) { "hello ümlaut" } let(:binary) { string.dup.force_encoding(Encoding::BINARY) } let(:windows) { string.dup.force_encoding(Encoding::Windows_31J) } - let(:invalid) { (100..1000).to_a.pack('c*').force_encoding('utf-8') } + let(:invalid) { (100..1000).to_a.pack("c*").force_encoding("utf-8") } it "generates JSON with incompatible encodings" do - expect { described_class.new.sanitize('string' => binary).to_json }.not_to raise_error + expect { described_class.new.sanitize("string" => binary).to_json }.not_to raise_error end it "generates JSON with bad encodings" do - expect { described_class.new.sanitize('string' => invalid).to_json }.not_to raise_error + expect { described_class.new.sanitize("string" => invalid).to_json }.not_to raise_error end it "converts to utf-8 when invalid" do - expect(described_class.new.sanitize('string' => invalid)['string'].encoding).to eq Encoding::UTF_8 + expect(described_class.new.sanitize("string" => invalid)["string"].encoding).to eq Encoding::UTF_8 end it "converts to utf-8 when binary" do - expect(described_class.new.sanitize('string' => binary)['string']).to eq 'hello ??mlaut' + expect(described_class.new.sanitize("string" => binary)["string"]).to eq "hello ??mlaut" end it "converts to UTF-8 when otherwise valid" do - expect(described_class.new.sanitize('string' => windows)['string']).to eq windows.encode!(Encoding::UTF_8) + expect(described_class.new.sanitize("string" => windows)["string"]).to eq windows.encode!(Encoding::UTF_8) end end context "with filters" do subject { described_class.new(filters: filters).sanitize(original) } - let!(:filters) { ["abc", :def, /private/, /^foo_.*$/, 'nested.string', /nested\.regexp$/, ->(k,v) { v.replace('block filter') if k == 'block' }] } + let!(:filters) { ["abc", :def, /private/, /^foo_.*$/, "nested.string", /nested\.regexp$/, ->(k, v) { v.replace("block filter") if k == "block" }] } let!(:original) do { - 'abc' => "123", 'def' => "456", 'ghi' => "789", 'nested' => { 'abc' => '100' }, - 'something_with_abc' => 'match the entire string', 'private_param' => 'prra', - 'foo_param' => 'bar', 'not_foo_param' => 'baz', 'nested_foo' => { 'foo_nested' => 'bla'}, - 'deeply' => { 'nested' => { 'string' => 'nested', 'regexp' => 'nested' } }, - 'nested.string' => 'value', - 'nested.regexp' => 'value', - 'block' => 'value', - 12345 => 'password' + "abc" => "123", "def" => "456", "ghi" => "789", "nested" => {"abc" => "100"}, + "something_with_abc" => "match the entire string", "private_param" => "prra", + "foo_param" => "bar", "not_foo_param" => "baz", "nested_foo" => {"foo_nested" => "bla"}, + "deeply" => {"nested" => {"string" => "nested", "regexp" => "nested"}}, + "nested.string" => "value", + "nested.regexp" => "value", + "block" => "value", + 12345 => "password" } end let!(:filtered) do { - 'abc' => '[FILTERED]', - 'def' => '[FILTERED]', - 'something_with_abc' => '[FILTERED]', - 'ghi' => '789', - 'nested' => { 'abc' => '[FILTERED]' }, - 'private_param' => '[FILTERED]', - 'foo_param' => '[FILTERED]', - 'not_foo_param' => 'baz', - 'nested_foo' => { 'foo_nested' => '[FILTERED]'}, - 'deeply' => { 'nested' => { 'string' => '[FILTERED]', 'regexp' => '[FILTERED]' } }, - 'nested.string' => '[FILTERED]', - 'nested.regexp' => '[FILTERED]', - 'block' => 'block filter', - 12345 => 'password' + "abc" => "[FILTERED]", + "def" => "[FILTERED]", + "something_with_abc" => "[FILTERED]", + "ghi" => "789", + "nested" => {"abc" => "[FILTERED]"}, + "private_param" => "[FILTERED]", + "foo_param" => "[FILTERED]", + "not_foo_param" => "baz", + "nested_foo" => {"foo_nested" => "[FILTERED]"}, + "deeply" => {"nested" => {"string" => "[FILTERED]", "regexp" => "[FILTERED]"}}, + "nested.string" => "[FILTERED]", + "nested.regexp" => "[FILTERED]", + "block" => "block filter", + 12345 => "password" } end @@ -169,7 +167,7 @@ it "allocates approximately same number of objects as without filters.", if: defined?(AllocationStats) do o = AllocationStats.trace { described_class.new.sanitize(original) } - expect { subject }.to allocate_under(o.new_allocations.size+8).objects + expect { subject }.to allocate_under(o.new_allocations.size + 8).objects end end end @@ -178,23 +176,23 @@ subject { described_class.new.filter_url(url) } context "malformed query" do - let(:url) { 'https://www.honeybadger.io/?foobar12' } + let(:url) { "https://www.honeybadger.io/?foobar12" } it { should eq url } end context "no query" do - let(:url) { 'https://www.honeybadger.io' } + let(:url) { "https://www.honeybadger.io" } it { should eq url } end context "malformed url" do - let(:url) { 'http s ! honeybadger' } + let(:url) { "http s ! honeybadger" } before { expect { URI.parse(url) }.to raise_error(URI::InvalidURIError) } it { should eq url } end context "complex url" do - let(:url) { 'https://foo:bar@www.honeybadger.io:123/asdf/?foo=1&bar=2&baz=3' } + let(:url) { "https://foo:bar@www.honeybadger.io:123/asdf/?foo=1&bar=2&baz=3" } it { should eq url } end end @@ -202,29 +200,29 @@ describe "#filter_cookies" do let!(:filters) { ["abc", :def, /private/] } - let!(:cookies) {"abc=123; def=456; ghi=789; private_param=prra"} - let(:filtered_cookies) {"abc=[FILTERED]; def=[FILTERED]; ghi=789; private_param=[FILTERED]"} + let!(:cookies) { "abc=123; def=456; ghi=789; private_param=prra" } + let(:filtered_cookies) { "abc=[FILTERED]; def=[FILTERED]; ghi=789; private_param=[FILTERED]" } subject { described_class.new(filters: filters).filter_cookies(cookies) } it { should eq filtered_cookies } end def assert_serializes(*keys) - [File.open(__FILE__), Proc.new { puts "boo!" }, Module.new].each do |object| + [File.open(__FILE__), proc { puts "boo!" }, Module.new].each do |object| hash = { - :strange_object => object, - :sub_hash => { - :sub_object => object + strange_object: object, + sub_hash: { + sub_object: object }, - :array => [object] + array: [object] } payload_keys = keys.dup last_key = payload_keys.pop - payload = described_class.new.sanitize(payload_keys.reverse.reduce({last_key => hash}) { |a,k| {k => a} }) + payload = described_class.new.sanitize(payload_keys.reverse.reduce({last_key => hash}) { |a, k| {k => a} }) first_key = keys.shift - hash = keys.reduce(payload[first_key]) {|a,k| a[k] } + hash = keys.reduce(payload[first_key]) { |a, k| a[k] } expect(hash[:strange_object]).to eq "#<#{object.class.name}>" # objects should be serialized expect(hash[:sub_hash]).to be_a Hash # subhashes should be kept diff --git a/spec/unit/honeybadger/util/stats_spec.rb b/spec/unit/honeybadger/util/stats_spec.rb index e21c47449..35b5b23b6 100644 --- a/spec/unit/honeybadger/util/stats_spec.rb +++ b/spec/unit/honeybadger/util/stats_spec.rb @@ -1,15 +1,15 @@ -require 'honeybadger/util/stats' +require "honeybadger/util/stats" describe Honeybadger::Util::Stats do - describe '.memory' do + describe ".memory" do subject { Honeybadger::Util::Stats.memory } before do - stub_const('Honeybadger::Util::Stats::HAS_MEM', true) - allow(IO).to receive(:readlines).with('/proc/meminfo').and_return(["MemTotal: 35125476 kB\n", "MemFree: 1671436 kB\n", "Buffers: 2242812 kB\n", "Cached: 11791596 kB\n", "SwapCached: 164256 kB\n", "Active: 15891800 kB\n", "Inactive: 13593872 kB\n"]) + stub_const("Honeybadger::Util::Stats::HAS_MEM", true) + allow(IO).to receive(:readlines).with("/proc/meminfo").and_return(["MemTotal: 35125476 kB\n", "MemFree: 1671436 kB\n", "Buffers: 2242812 kB\n", "Cached: 11791596 kB\n", "SwapCached: 164256 kB\n", "Active: 15891800 kB\n", "Inactive: 13593872 kB\n"]) end - describe '.keys' do + describe ".keys" do subject { Honeybadger::Util::Stats.memory.keys } its(:length) { should eq 5 } end @@ -22,21 +22,21 @@ it { should be_empty } end - it 'converts KB to MB' do + it "converts KB to MB" do expect(Honeybadger::Util::Stats.memory[:total]).to eq 34302.22265625 expect(Honeybadger::Util::Stats.memory[:free]).to eq 1632.26171875 expect(Honeybadger::Util::Stats.memory[:buffers]).to eq 2190.24609375 expect(Honeybadger::Util::Stats.memory[:cached]).to eq 11515.23046875 end - it 'sums non-totals for free_total' do + it "sums non-totals for free_total" do expect(Honeybadger::Util::Stats.memory[:free_total]).to eq 15337.73828125 end - context 'when mathn is required' do - before(:all) { require 'mathn' } + context "when mathn is required" do + before(:all) { require "mathn" } - it 'converts Rational to Float', if: RUBY_VERSION < '2.5.0' do + it "converts Rational to Float", if: RUBY_VERSION < "2.5.0" do expect(Honeybadger::Util::Stats.memory[:total]).to be_a Float expect(Honeybadger::Util::Stats.memory[:free]).to be_a Float expect(Honeybadger::Util::Stats.memory[:buffers]).to be_a Float @@ -45,15 +45,15 @@ end end - describe '.load' do + describe ".load" do subject { Honeybadger::Util::Stats.load } before do - stub_const('Honeybadger::Util::Stats::HAS_LOAD', true) - allow(IO).to receive(:read).with('/proc/loadavg').and_return('22.58 19.66 15.96 20/2019 2') + stub_const("Honeybadger::Util::Stats::HAS_LOAD", true) + allow(IO).to receive(:read).with("/proc/loadavg").and_return("22.58 19.66 15.96 20/2019 2") end - describe '.keys' do + describe ".keys" do subject { Honeybadger::Util::Stats.load.keys } its(:length) { should eq 3 } end diff --git a/spec/unit/honeybadger/worker_spec.rb b/spec/unit/honeybadger/worker_spec.rb index 6e650494f..7d5aa9d39 100644 --- a/spec/unit/honeybadger/worker_spec.rb +++ b/spec/unit/honeybadger/worker_spec.rb @@ -1,28 +1,28 @@ -require 'timecop' -require 'thread' +require "timecop" +require "thread" -require 'honeybadger/worker' -require 'honeybadger/config' -require 'honeybadger/backend' -require 'honeybadger/notice' +require "honeybadger/worker" +require "honeybadger/config" +require "honeybadger/backend" +require "honeybadger/notice" describe Honeybadger::Worker do let!(:instance) { described_class.new(config) } - let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, backend: 'null') } - let(:obj) { double('Badger', id: :foo, to_json: '{}') } + let(:config) { Honeybadger::Config.new(logger: NULL_LOGGER, debug: true, backend: "null") } + let(:obj) { double("Badger", id: :foo, to_json: "{}") } subject { instance } after do Thread.list.each do |thread| - next unless thread.kind_of?(Honeybadger::Worker::Thread) + next unless thread.is_a?(Honeybadger::Worker::Thread) Thread.kill(thread) end end context "when an exception happens in the worker loop" do before do - allow(instance.send(:queue)).to receive(:pop).and_raise('fail') + allow(instance.send(:queue)).to receive(:pop).and_raise("fail") end it "does not raise when shutting down" do @@ -51,7 +51,7 @@ context "when an exception happens during processing" do before do allow(instance).to receive(:sleep) - allow(instance).to receive(:handle_response).and_raise('fail') + allow(instance).to receive(:handle_response).and_raise("fail") end def flush @@ -221,7 +221,7 @@ def flush context "when throttled during shutdown" do before do - allow(subject.send(:backend)).to receive(:notify).with(:notices, obj).and_return(Honeybadger::Backend::Response.new(429) ) + allow(subject.send(:backend)).to receive(:notify).with(:notices, obj).and_return(Honeybadger::Backend::Response.new(429)) end it "shuts down immediately" do @@ -346,7 +346,7 @@ def handle_response end context "when error" do - let(:response) { Honeybadger::Backend::Response.new(:error, nil, 'test error message') } + let(:response) { Honeybadger::Backend::Response.new(:error, nil, "test error message") } it "warns the logger" do expect(config.logger).to receive(:warn).with(/test error message/) diff --git a/spec/unit/honeybadger_spec.rb b/spec/unit/honeybadger_spec.rb index 1c6bedf26..019890abd 100644 --- a/spec/unit/honeybadger_spec.rb +++ b/spec/unit/honeybadger_spec.rb @@ -1,4 +1,4 @@ -require 'honeybadger/ruby' +require "honeybadger/ruby" RSpec::Matchers.define :define do |expected| match do |actual| @@ -39,7 +39,7 @@ it "delegates ::flush to agent instance" do expect(Honeybadger::Agent.instance).to receive(:flush) Honeybadger.flush - end + end it "delegates ::event to agent instance" do expect(Honeybadger::Agent.instance).to receive(:event) @@ -69,53 +69,53 @@ expect { described_class.context.clear! }.to change { described_class.get_context }.from(c).to(nil) end - context 'with local context' do - it 'merges local context' do + context "with local context" do + it "merges local context" do allow(described_class).to receive(:get_context).and_call_original - described_class.context({ bar: :baz }) do - described_class.context({ bar: :qux }) do - expect(described_class.get_context).to eq({ foo: :bar, bar: :qux }) + described_class.context({bar: :baz}) do + described_class.context({bar: :qux}) do + expect(described_class.get_context).to eq({foo: :bar, bar: :qux}) end - expect(described_class.get_context).to eq({ foo: :bar, bar: :baz }) + expect(described_class.get_context).to eq({foo: :bar, bar: :baz}) end expect(described_class).to have_received(:get_context).at_least(:twice) end - it 'clears local context' do + it "clears local context" do allow(described_class).to receive(:get_context).and_call_original - described_class.context({ bar: :baz }) do - expect(described_class.get_context).to eq({ foo: :bar, bar: :baz }) + described_class.context({bar: :baz}) do + expect(described_class.get_context).to eq({foo: :bar, bar: :baz}) end - expect(described_class.get_context).to eq({ foo: :bar }) + expect(described_class.get_context).to eq({foo: :bar}) expect(described_class).to have_received(:get_context).at_least(:twice) end - it 'tracks local context correctly' do + it "tracks local context correctly" do allow(described_class).to receive(:get_context).and_call_original begin - described_class.context({ bar: :qux }) do - described_class.context({ baz: :qux }) + described_class.context({bar: :qux}) do + described_class.context({baz: :qux}) - raise 'exception' + raise "exception" end - rescue StandardError + rescue # noop end - expect(described_class.get_context).to eq({ foo: :bar, baz: :qux }) + expect(described_class.get_context).to eq({foo: :bar, baz: :qux}) end end end describe "#notify" do - let(:config) { Honeybadger::Config.new(api_key:'fake api key', logger: NULL_LOGGER) } + let(:config) { Honeybadger::Config.new(api_key: "fake api key", logger: NULL_LOGGER) } let(:instance) { Honeybadger::Agent.new(config) } - let(:worker) { double('Honeybadger::Worker') } + let(:worker) { double("Honeybadger::Worker") } before do allow(Honeybadger::Agent).to receive(:instance).and_return(instance) @@ -133,13 +133,13 @@ end it "creates and send a notice for a hash" do - exception = build_exception + build_exception notice = stub_notice!(config) - expect(Honeybadger::Notice).to receive(:new).with(config, hash_including(error_message: 'uh oh')).and_return(notice) + expect(Honeybadger::Notice).to receive(:new).with(config, hash_including(error_message: "uh oh")).and_return(notice) expect(worker).to receive(:push).with(notice) - Honeybadger.notify(error_message: 'uh oh') + Honeybadger.notify(error_message: "uh oh") end it "does not pass the hash as an exception when sending a notice for it" do @@ -148,13 +148,13 @@ expect(Honeybadger::Notice).to receive(:new).with(anything, hash_excluding(:exception)) expect(worker).to receive(:push).with(notice) - Honeybadger.notify(error_message: 'uh oh') + Honeybadger.notify(error_message: "uh oh") end it "creates and sends a notice for an exception and hash" do exception = build_exception notice = stub_notice!(config) - notice_args = { error_message: 'uh oh' } + notice_args = {error_message: "uh oh"} expect(Honeybadger::Notice).to receive(:new).with(config, hash_including(notice_args.merge(exception: exception))).and_return(notice) expect(worker).to receive(:push).with(notice) @@ -165,27 +165,27 @@ it "sends a notice with a string" do notice = stub_notice!(config) - expect(Honeybadger::Notice).to receive(:new).with(config, hash_including(error_message: 'the test message')).and_return(notice) + expect(Honeybadger::Notice).to receive(:new).with(config, hash_including(error_message: "the test message")).and_return(notice) expect(worker).to receive(:push).with(notice) - Honeybadger.notify('the test message') + Honeybadger.notify("the test message") end it "sends a notice with any arbitrary object" do notice = stub_notice!(config) - expect(Honeybadger::Notice).to receive(:new).with(config, hash_including(error_message: 'the test message')).and_return(notice) + expect(Honeybadger::Notice).to receive(:new).with(config, hash_including(error_message: "the test message")).and_return(notice) expect(worker).to receive(:push).with(notice) - Honeybadger.notify(double(to_s: 'the test message')) + Honeybadger.notify(double(to_s: "the test message")) end it "generates a backtrace excluding the singleton" do expect(instance.worker).to receive(:push) do |notice| - expect(notice.backtrace.to_a[0]).to match('lib/honeybadger/agent.rb') + expect(notice.backtrace.to_a[0]).to match("lib/honeybadger/agent.rb") end - Honeybadger.notify(error_message: 'testing backtrace generation') + Honeybadger.notify(error_message: "testing backtrace generation") end it "does not deliver an ignored exception when notifying implicitly" do @@ -230,7 +230,6 @@ it "passes config to created notices" do exception = build_exception - config_opts = { 'one' => 'two', 'three' => 'four' } notice = stub_notice(config) @@ -263,15 +262,15 @@ describe "#configure" do before do Honeybadger.config.set(:api_key, nil) - Honeybadger.config.set(:'user_informer.enabled', true) + Honeybadger.config.set(:"user_informer.enabled", true) end it "configures the singleton" do expect { Honeybadger.configure do |config| - config.api_key = 'test api key' + config.api_key = "test api key" end - }.to change { Honeybadger.config.get(:api_key) }.from(nil).to('test api key') + }.to change { Honeybadger.config.get(:api_key) }.from(nil).to("test api key") end it "yields a Ruby config object" do diff --git a/tools/allocation_stats.rb b/tools/allocation_stats.rb index 1ed6a4729..75084ac75 100644 --- a/tools/allocation_stats.rb +++ b/tools/allocation_stats.rb @@ -1,22 +1,22 @@ -require 'allocation_stats' -require 'honeybadger' -require 'benchmark' +require "allocation_stats" +require "honeybadger" +require "benchmark" -group_by = if ENV['GROUP'] - ENV['GROUP'].split(',').lazy.map(&:strip).map(&:to_sym).freeze - else - [:sourcefile, :sourceline, :class].freeze - end +group_by = if ENV["GROUP"] + ENV["GROUP"].split(",").lazy.map(&:strip).map(&:to_sym).freeze +else + [:sourcefile, :sourceline, :class].freeze +end puts Benchmark.measure { stats = AllocationStats.trace do Honeybadger.configure do |config| - config.api_key = 'badgers' - config.backend = 'null' + config.api_key = "badgers" + config.backend = "null" end 1000.times do - Honeybadger.notify(error_class: 'RubyProf', error_message: 'Profiling Honeybadger -- this should never actually be reported.') + Honeybadger.notify(error_class: "RubyProf", error_message: "Profiling Honeybadger -- this should never actually be reported.") end end diff --git a/tools/benchmark.rb b/tools/benchmark.rb index bb4ee1cd7..412b81e29 100644 --- a/tools/benchmark.rb +++ b/tools/benchmark.rb @@ -6,13 +6,13 @@ # # bundle exec jruby -J-Xrunhprof spec/benchmark.rb -require 'honeybadger' -require 'benchmark' +require "honeybadger" +require "benchmark" benchmark = Benchmark.measure do - if Honeybadger.start({:api_key => 'badgers', :backend => 'null'}) + if Honeybadger.start({api_key: "badgers", backend: "null"}) 1000.times do - Honeybadger.notify(error_class: 'RubyProf', error_message: 'Profiling Honeybadger -- this should never actually be reported.') + Honeybadger.notify(error_class: "RubyProf", error_message: "Profiling Honeybadger -- this should never actually be reported.") end end end diff --git a/tools/isolation.rb b/tools/isolation.rb index 77c6b27e9..0fc42f039 100644 --- a/tools/isolation.rb +++ b/tools/isolation.rb @@ -1,7 +1,7 @@ -require 'bundler' +require "bundler" catch :failure do - Dir['spec/unit/**/*_spec.rb'].each do |s| + Dir["spec/unit/**/*_spec.rb"].each do |s| Bundler.with_unbundled_env { puts `bundle exec rspec --pattern #{s}` } throw :failure unless $?.exitstatus == 0 end diff --git a/tools/profile.rb b/tools/profile.rb index f863f5807..6701c3992 100644 --- a/tools/profile.rb +++ b/tools/profile.rb @@ -1,7 +1,7 @@ -require 'ruby-prof' -require 'honeybadger' +require "ruby-prof" +require "honeybadger" -if Honeybadger.start({:api_key => 'badgers', :debug => true, :backend => 'null'}) +if Honeybadger.start({api_key: "badgers", debug: true, backend: "null"}) RubyProf.start and Honeybadger::Agent.at_exit do result = RubyProf.stop printer = RubyProf::FlatPrinter.new(result) @@ -9,6 +9,6 @@ end 1000.times do - Honeybadger.notify(error_class: 'RubyProf', error_message: 'Profiling Honeybadger -- this should never actually be reported.') + Honeybadger.notify(error_class: "RubyProf", error_message: "Profiling Honeybadger -- this should never actually be reported.") end end diff --git a/tools/release.rb b/tools/release.rb index 77cb96381..bea36cf17 100644 --- a/tools/release.rb +++ b/tools/release.rb @@ -1,11 +1,11 @@ -require 'rubygems' -require 'bundler/setup' -require 'honeybadger/version' +require "rubygems" +require "bundler/setup" +require "honeybadger/version" module Release - CHANGELOG_FILE = 'CHANGELOG.md'.freeze - CHANGELOG_HEADING = '## [Unreleased]' - EXIT_CMD = 'bundle update honeybadger && git add -p' + CHANGELOG_FILE = "CHANGELOG.md".freeze + CHANGELOG_HEADING = "## [Unreleased]" + EXIT_CMD = "bundle update honeybadger && git add -p" def self.run_before(version) bump_changelog(version) @@ -18,7 +18,7 @@ def self.run_after(version) def self.bump_changelog(version) contents = File.read(CHANGELOG_FILE) if contents =~ Regexp.new(Regexp.escape("## [#{version}]")) - puts "ERROR: #{ version } already exists in CHANGELOG.md" + puts "ERROR: #{version} already exists in CHANGELOG.md" exit 1 end diff --git a/tools/sinatra.rb b/tools/sinatra.rb index 18ecb00e0..fe5f77d84 100644 --- a/tools/sinatra.rb +++ b/tools/sinatra.rb @@ -1,16 +1,16 @@ -require 'sinatra' -require 'honeybadger' +require "sinatra" +require "honeybadger" GC::Profiler.enable # class Badgers < Sinatra::Application -get '/' do - 'Hello world!' +get "/" do + "Hello world!" end -get '/test/failure' do - fail 'Sinatra has left the building' +get "/test/failure" do + fail "Sinatra has left the building" end # end From 7b22a5e55ef5bc804abcc086e069132ad498d27f Mon Sep 17 00:00:00 2001 From: Mike Perham Date: Mon, 20 Jan 2025 10:27:02 -0800 Subject: [PATCH 02/13] Add standard 'unsafe' fixes --- lib/honeybadger/backtrace.rb | 2 +- lib/honeybadger/breadcrumbs/active_support.rb | 2 +- lib/honeybadger/cli/heroku.rb | 6 +++--- lib/honeybadger/cli/test.rb | 4 ++-- lib/honeybadger/config.rb | 1 - lib/honeybadger/config/defaults.rb | 4 ++-- lib/honeybadger/config/env.rb | 2 +- lib/honeybadger/config/ruby.rb | 2 +- lib/honeybadger/events_worker.rb | 2 +- lib/honeybadger/instrumentation.rb | 4 ++-- lib/honeybadger/logging.rb | 6 +++--- lib/honeybadger/metrics_worker.rb | 2 +- lib/honeybadger/notice.rb | 11 +++++------ lib/honeybadger/plugins/breadcrumbs.rb | 2 +- lib/honeybadger/plugins/delayed_job/plugin.rb | 2 +- lib/honeybadger/plugins/sidekiq.rb | 3 ++- lib/honeybadger/singleton.rb | 2 +- lib/honeybadger/util/http.rb | 2 +- lib/honeybadger/util/sanitizer.rb | 2 +- lib/honeybadger/worker.rb | 2 +- spec/fixtures/Rakefile | 4 ++-- spec/fixtures/ruby_custom.rb | 2 +- spec/spec_helper.rb | 2 +- spec/support/backtraced_exception.rb | 2 +- spec/unit/honeybadger/events_worker_spec.rb | 1 - spec/unit/honeybadger/logging_spec.rb | 4 ++-- spec/unit/honeybadger/metrics_worker_spec.rb | 1 - spec/unit/honeybadger/plugins/local_variables_spec.rb | 2 +- spec/unit/honeybadger/rack/error_notifier_spec.rb | 2 +- spec/unit/honeybadger/worker_spec.rb | 1 - tools/profile.rb | 2 +- 31 files changed, 41 insertions(+), 45 deletions(-) diff --git a/lib/honeybadger/backtrace.rb b/lib/honeybadger/backtrace.rb index 4318d043b..43cab31f4 100644 --- a/lib/honeybadger/backtrace.rb +++ b/lib/honeybadger/backtrace.rb @@ -104,7 +104,7 @@ def get_source(file, number, radius = 2) f.gets l += 1 } - return Hash[duration.times.map { (line = f.gets) ? [(l += 1), line] : nil }.compact] + return duration.times.map { (line = f.gets) ? [(l += 1), line] : nil }.compact.to_h end else {} diff --git a/lib/honeybadger/breadcrumbs/active_support.rb b/lib/honeybadger/breadcrumbs/active_support.rb index 09ce90767..09893c601 100644 --- a/lib/honeybadger/breadcrumbs/active_support.rb +++ b/lib/honeybadger/breadcrumbs/active_support.rb @@ -19,7 +19,7 @@ def self.default_notifications transform: lambda do |data| if data[:sql] connection = data.delete(:connection) - adapter = (connection && connection.adapter_name.downcase) || active_record_connection_db_config[:adapter] + adapter = connection&.adapter_name&.downcase || active_record_connection_db_config[:adapter] data[:sql] = Util::SQL.obfuscate(data[:sql], adapter) end data diff --git a/lib/honeybadger/cli/heroku.rb b/lib/honeybadger/cli/heroku.rb index ed350fa9b..3d76f1c0a 100644 --- a/lib/honeybadger/cli/heroku.rb +++ b/lib/honeybadger/cli/heroku.rb @@ -78,7 +78,7 @@ def detect_heroku_app(prompt_on_default = true) apps.values.first else say "We detected a Heroku app named #{apps.values.first}. Do you want to load the config? (y/yes or n/no)" - if STDIN.gets.chomp =~ /(y|yes)/i + if $stdin.gets.chomp =~ /(y|yes)/i apps.values.first end end @@ -87,7 +87,7 @@ def detect_heroku_app(prompt_on_default = true) apps.each_with_index { |a, i| say "\s\s#{i + 1}. #{a[1]}" } say "\s\s#{apps.size + 1}. Use default" say "Please select an option (1-#{apps.size + 1}):" - apps.values[STDIN.gets.chomp.to_i - 1] + apps.values[$stdin.gets.chomp.to_i - 1] end end end @@ -107,7 +107,7 @@ def read_heroku_env(app = nil) cmd << "--app #{app}" if app output = run(cmd.join("\s")) return false unless $?.to_i == 0 - Hash[output.scan(/(HONEYBADGER_[^:]+):\s*(\S.*)\s*$/)] + output.scan(/(HONEYBADGER_[^:]+):\s*(\S.*)\s*$/).to_h end def set_env_from_heroku(app = nil) diff --git a/lib/honeybadger/cli/test.rb b/lib/honeybadger/cli/test.rb index 1b673acca..f34f73825 100644 --- a/lib/honeybadger/cli/test.rb +++ b/lib/honeybadger/cli/test.rb @@ -12,7 +12,7 @@ class Test exception_name = ENV["EXCEPTION"] || "HoneybadgerTestingException" Object.const_get(exception_name) rescue - Object.const_set(exception_name, Class.new(Exception)) + Object.const_set(exception_name, Class.new(RuntimeError)) end.new('Testing honeybadger via "honeybadger test". If you can see this, it works.') class TestBackend @@ -90,7 +90,7 @@ def test_exception_class exception_name = ENV["EXCEPTION"] || "HoneybadgerTestingException" Object.const_get(exception_name) rescue - Object.const_set(exception_name, Class.new(Exception)) + Object.const_set(exception_name, Class.new(RuntimeError)) end def run_standalone_test diff --git a/lib/honeybadger/config.rb b/lib/honeybadger/config.rb index a05189b8d..f4ee78735 100644 --- a/lib/honeybadger/config.rb +++ b/lib/honeybadger/config.rb @@ -10,7 +10,6 @@ require "honeybadger/config/defaults" require "honeybadger/util/http" require "honeybadger/util/revision" -require "honeybadger/logging" module Honeybadger # @api private diff --git a/lib/honeybadger/config/defaults.rb b/lib/honeybadger/config/defaults.rb index eac3d0656..9c5ad7e4a 100644 --- a/lib/honeybadger/config/defaults.rb +++ b/lib/honeybadger/config/defaults.rb @@ -291,7 +291,7 @@ class Boolean; end }, "exceptions.rescue_rake": { description: "Enable reporting exceptions in rake tasks.", - default: !STDOUT.tty?, + default: !$stdout.tty?, type: Boolean }, "exceptions.notify_at_exit": { @@ -519,6 +519,6 @@ class Boolean; end } }.freeze - DEFAULTS = Hash[OPTIONS.map { |k, v| [k, v[:default]] }].freeze + DEFAULTS = OPTIONS.map { |k, v| [k, v[:default]] }.to_h.freeze end end diff --git a/lib/honeybadger/config/env.rb b/lib/honeybadger/config/env.rb index d69258400..4398e889f 100644 --- a/lib/honeybadger/config/env.rb +++ b/lib/honeybadger/config/env.rb @@ -4,7 +4,7 @@ module Honeybadger class Config module Env CONFIG_KEY = /\AHONEYBADGER_(.+)\Z/.freeze - CONFIG_MAPPING = Hash[DEFAULTS.keys.map { |k| [k.to_s.upcase.gsub(KEY_REPLACEMENT, "_"), k] }].freeze + CONFIG_MAPPING = DEFAULTS.keys.map { |k| [k.to_s.upcase.gsub(KEY_REPLACEMENT, "_"), k] }.to_h.freeze ARRAY_VALUES = Regexp.new('\s*,\s*').freeze IGNORED_TYPES = Set[Hash] diff --git a/lib/honeybadger/config/ruby.rb b/lib/honeybadger/config/ruby.rb index 6e2dc3a74..14bf331c0 100644 --- a/lib/honeybadger/config/ruby.rb +++ b/lib/honeybadger/config/ruby.rb @@ -46,7 +46,7 @@ def mash?(method) end def setter?(method_name) - return false unless method_name.to_s =~ /=\z/ + return false unless method_name.to_s.end_with?("=") key = key(method_name) KEYS.any? { |k| k == key } end diff --git a/lib/honeybadger/events_worker.rb b/lib/honeybadger/events_worker.rb index bf1068e5f..54ac12027 100644 --- a/lib/honeybadger/events_worker.rb +++ b/lib/honeybadger/events_worker.rb @@ -84,7 +84,7 @@ def shutdown(force = false) # Blocks until queue is processed up to this point in time. def flush mutex.synchronize do - if thread && thread.alive? + if thread&.alive? queue.push(FLUSH) queue.push(marker) marker.wait(mutex) diff --git a/lib/honeybadger/instrumentation.rb b/lib/honeybadger/instrumentation.rb index d843a602d..d684f86b1 100644 --- a/lib/honeybadger/instrumentation.rb +++ b/lib/honeybadger/instrumentation.rb @@ -143,12 +143,12 @@ def gauge(name, *args) # @api private def extract_attributes(args) - args.select { |a| a.is_a?(Hash) }.first || {} + args.find { |a| a.is_a?(Hash) } || {} end # @api private def extract_callable(args) - args.select { |a| a.respond_to?(:call) }.first + args.find { |a| a.respond_to?(:call) } end end end diff --git a/lib/honeybadger/logging.rb b/lib/honeybadger/logging.rb index b60aae875..4e9441e89 100644 --- a/lib/honeybadger/logging.rb +++ b/lib/honeybadger/logging.rb @@ -116,7 +116,7 @@ def format_message(msg) end class ConfigLogger < StandardLogger - LOCATE_CALLER_LOCATION = Regexp.new("#{Regexp.escape(__FILE__)}").freeze + LOCATE_CALLER_LOCATION = Regexp.new(Regexp.escape(__FILE__).to_s).freeze CALLER_LOCATION = Regexp.new("#{Regexp.escape(File.expand_path("../../../", __FILE__))}/(.*)").freeze INFO_SUPPLEMENT = " level=%s pid=%s".freeze @@ -124,7 +124,7 @@ class ConfigLogger < StandardLogger def initialize(config, logger = Logger.new(nil)) @config = config - @tty = STDOUT.tty? + @tty = $stdout.tty? @tty_level = @config.log_level(:"logging.tty_level") super(logger) end @@ -169,7 +169,7 @@ def supplement(msg, severity) end def caller_location - if caller && caller.find { |l| l !~ LOCATE_CALLER_LOCATION && l =~ CALLER_LOCATION } + if caller&.find { |l| l !~ LOCATE_CALLER_LOCATION && l =~ CALLER_LOCATION } Regexp.last_match(1) end end diff --git a/lib/honeybadger/metrics_worker.rb b/lib/honeybadger/metrics_worker.rb index 1948b3a23..92021f39b 100644 --- a/lib/honeybadger/metrics_worker.rb +++ b/lib/honeybadger/metrics_worker.rb @@ -59,7 +59,7 @@ def shutdown(force = false) # Blocks until queue is processed up to this point in time. def flush mutex.synchronize do - if thread && thread.alive? + if thread&.alive? queue.push(marker) marker.wait(mutex) end diff --git a/lib/honeybadger/notice.rb b/lib/honeybadger/notice.rb index 79250066d..5ea64832d 100644 --- a/lib/honeybadger/notice.rb +++ b/lib/honeybadger/notice.rb @@ -310,8 +310,7 @@ def ignore_by_origin? end def ignore_by_callbacks? - config.exception_filter && - config.exception_filter.call(self) + config.exception_filter&.call(self) end # Gets a property named "attribute" of an exception, either from @@ -489,7 +488,7 @@ def local_variables_from_exception(exception, config) end } - result_hash = Hash[results] + result_hash = results.to_h request_sanitizer.sanitize(result_hash) end @@ -532,11 +531,11 @@ def unwrap_exception(exception) # Returns the Exception cause. def exception_cause(exception) e = exception - if e.respond_to?(:cause) && e.cause && e.cause.is_a?(Exception) + if e.respond_to?(:cause) && e.cause&.is_a?(Exception) e.cause - elsif e.respond_to?(:original_exception) && e.original_exception && e.original_exception.is_a?(Exception) + elsif e.respond_to?(:original_exception) && e.original_exception&.is_a?(Exception) e.original_exception - elsif e.respond_to?(:continued_exception) && e.continued_exception && e.continued_exception.is_a?(Exception) + elsif e.respond_to?(:continued_exception) && e.continued_exception&.is_a?(Exception) e.continued_exception end end diff --git a/lib/honeybadger/plugins/breadcrumbs.rb b/lib/honeybadger/plugins/breadcrumbs.rb index 10d2d4604..4825de5bb 100644 --- a/lib/honeybadger/plugins/breadcrumbs.rb +++ b/lib/honeybadger/plugins/breadcrumbs.rb @@ -73,7 +73,7 @@ class RailsBreadcrumbs # @option notification_config [Proc] :transform A proc that accepts the data payload. The return value will replace the current data hash (optional) # def self.send_breadcrumb_notification(name, duration, notification_config, data = {}) - return if notification_config[:exclude_when] && notification_config[:exclude_when].call(data) + return if notification_config[:exclude_when]&.call(data) message = case (m = notification_config[:message]) diff --git a/lib/honeybadger/plugins/delayed_job/plugin.rb b/lib/honeybadger/plugins/delayed_job/plugin.rb index 6869c7cc8..76f21388b 100644 --- a/lib/honeybadger/plugins/delayed_job/plugin.rb +++ b/lib/honeybadger/plugins/delayed_job/plugin.rb @@ -9,7 +9,7 @@ class Plugin < ::Delayed::Plugin lifecycle.around(:invoke_job) do |job, &block| begin begin - if job.payload_object.class.name == "ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper" + if job.payload_object.instance_of?(::ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper) # buildin support for Rails 4.2 ActiveJob component = job.payload_object.job_data["job_class"] action = "perform" diff --git a/lib/honeybadger/plugins/sidekiq.rb b/lib/honeybadger/plugins/sidekiq.rb index 6d3eb28a0..a2a7f614e 100644 --- a/lib/honeybadger/plugins/sidekiq.rb +++ b/lib/honeybadger/plugins/sidekiq.rb @@ -37,7 +37,8 @@ def call(worker, msg, queue, &block) status = "failure" raise ensure - context.merge!(duration: duration, status: status) + context[:duration] = duration + context[:status] = status if Honeybadger.config.load_plugin_insights_events?(:sidekiq) Honeybadger.event("perform.sidekiq", context) end diff --git a/lib/honeybadger/singleton.rb b/lib/honeybadger/singleton.rb index 4df73f782..64ec4b414 100644 --- a/lib/honeybadger/singleton.rb +++ b/lib/honeybadger/singleton.rb @@ -68,7 +68,7 @@ def notify(exception_or_opts = nil, opts = {}, **kwargs) # @api private def load_plugins! - Dir[File.expand_path("../plugins/*.rb", __FILE__)].each do |plugin| + Dir[File.expand_path("../plugins/*.rb", __FILE__)].sort.each do |plugin| require plugin end Plugin.load!(config) diff --git a/lib/honeybadger/util/http.rb b/lib/honeybadger/util/http.rb index a3a0d340b..74403e32f 100644 --- a/lib/honeybadger/util/http.rb +++ b/lib/honeybadger/util/http.rb @@ -66,7 +66,7 @@ def http_connection def http_headers(headers = nil) {}.tap do |hash| hash.merge!(HEADERS) - hash.merge!({"X-API-Key" => config[:api_key].to_s}) + hash["X-API-Key"] = config[:api_key].to_s hash.merge!(headers) if headers end end diff --git a/lib/honeybadger/util/sanitizer.rb b/lib/honeybadger/util/sanitizer.rb index b572bfed2..f618d8561 100644 --- a/lib/honeybadger/util/sanitizer.rb +++ b/lib/honeybadger/util/sanitizer.rb @@ -59,7 +59,7 @@ def sanitize(data, depth = 0, stack = nil, parents = []) return BASIC_OBJECT if basic_object?(data) if recursive?(data) - return RECURSION if stack && stack.include?(data.object_id) + return RECURSION if stack&.include?(data.object_id) stack = stack ? stack.dup : Set.new stack << data.object_id diff --git a/lib/honeybadger/worker.rb b/lib/honeybadger/worker.rb index c0d9f8d37..82190d44d 100644 --- a/lib/honeybadger/worker.rb +++ b/lib/honeybadger/worker.rb @@ -76,7 +76,7 @@ def shutdown(force = false) # Blocks until queue is processed up to this point in time. def flush mutex.synchronize do - if thread && thread.alive? + if thread&.alive? queue.push(marker) marker.wait(mutex) end diff --git a/spec/fixtures/Rakefile b/spec/fixtures/Rakefile index 54757ce20..dc4451a4a 100644 --- a/spec/fixtures/Rakefile +++ b/spec/fixtures/Rakefile @@ -19,11 +19,11 @@ end def stub_tty_output(value) if value - def STDOUT.tty? + def $stdout.tty? true end else - def STDOUT.tty? + def $stdout.tty? false end end diff --git a/spec/fixtures/ruby_custom.rb b/spec/fixtures/ruby_custom.rb index 98bc9d40c..07768c8b5 100644 --- a/spec/fixtures/ruby_custom.rb +++ b/spec/fixtures/ruby_custom.rb @@ -4,7 +4,7 @@ api_key: "asdf", backend: "debug", debug: true, - logger: Logger.new(STDOUT) + logger: Logger.new($stdout) }) agent.notify(error_class: "CustomHoneybadgerException", error_message: "Test message") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e1e53c704..503f7650b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -19,7 +19,7 @@ nil end -Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f } +Dir[File.expand_path("../support/**/*.rb", __FILE__)].sort.each { |f| require f } TMP_DIR = Pathname.new(File.expand_path("../../tmp", __FILE__)) FIXTURES_PATH = Pathname.new(File.expand_path("../fixtures/", __FILE__)) diff --git a/spec/support/backtraced_exception.rb b/spec/support/backtraced_exception.rb index ea4bd6685..5932908ba 100644 --- a/spec/support/backtraced_exception.rb +++ b/spec/support/backtraced_exception.rb @@ -1,4 +1,4 @@ -class BacktracedException < Exception +class BacktracedException < RuntimeError attr_accessor :backtrace def initialize(opts) @backtrace = opts[:backtrace] diff --git a/spec/unit/honeybadger/events_worker_spec.rb b/spec/unit/honeybadger/events_worker_spec.rb index 43127da02..35a07883c 100644 --- a/spec/unit/honeybadger/events_worker_spec.rb +++ b/spec/unit/honeybadger/events_worker_spec.rb @@ -1,5 +1,4 @@ require "timecop" -require "thread" require "honeybadger/events_worker" require "honeybadger/config" diff --git a/spec/unit/honeybadger/logging_spec.rb b/spec/unit/honeybadger/logging_spec.rb index 683921ee9..711663615 100644 --- a/spec/unit/honeybadger/logging_spec.rb +++ b/spec/unit/honeybadger/logging_spec.rb @@ -63,7 +63,7 @@ it { should respond_to severity } end - context "when not attached to terminal", unless: STDOUT.tty? do + context "when not attached to terminal", unless: $stdout.tty? do LOG_SEVERITIES.each do |severity| it "delegates ##{severity} to configured logger" do # Debug is logged at the info level. @@ -74,7 +74,7 @@ end end - context "when attached to terminal", if: STDOUT.tty? do + context "when attached to terminal", if: $stdout.tty? do [:debug, :info, :warn].each do |severity| it "suppresses ##{severity} from configured logger" do expect(logger).not_to receive(:add) diff --git a/spec/unit/honeybadger/metrics_worker_spec.rb b/spec/unit/honeybadger/metrics_worker_spec.rb index ba468b831..7ed5e22f5 100644 --- a/spec/unit/honeybadger/metrics_worker_spec.rb +++ b/spec/unit/honeybadger/metrics_worker_spec.rb @@ -1,5 +1,4 @@ require "timecop" -require "thread" require "honeybadger/metrics_worker" require "honeybadger/config" diff --git a/spec/unit/honeybadger/plugins/local_variables_spec.rb b/spec/unit/honeybadger/plugins/local_variables_spec.rb index 071baf7fa..681b7c0ca 100644 --- a/spec/unit/honeybadger/plugins/local_variables_spec.rb +++ b/spec/unit/honeybadger/plugins/local_variables_spec.rb @@ -56,7 +56,7 @@ describe Honeybadger::Plugins::LocalVariables::ExceptionExtension do subject do # Test in isolation rather than installing the plugin globally. - Class.new(Exception) do |klass| + Class.new(RuntimeError) do |klass| klass.send(:include, Honeybadger::Plugins::LocalVariables::ExceptionExtension) end.new end diff --git a/spec/unit/honeybadger/rack/error_notifier_spec.rb b/spec/unit/honeybadger/rack/error_notifier_spec.rb index db2ad1870..575706118 100644 --- a/spec/unit/honeybadger/rack/error_notifier_spec.rb +++ b/spec/unit/honeybadger/rack/error_notifier_spec.rb @@ -1,6 +1,6 @@ require "honeybadger/rack/error_notifier" -class BacktracedException < Exception +class BacktracedException < RuntimeError attr_accessor :backtrace def initialize(opts) @backtrace = opts[:backtrace] diff --git a/spec/unit/honeybadger/worker_spec.rb b/spec/unit/honeybadger/worker_spec.rb index 7d5aa9d39..a464de459 100644 --- a/spec/unit/honeybadger/worker_spec.rb +++ b/spec/unit/honeybadger/worker_spec.rb @@ -1,5 +1,4 @@ require "timecop" -require "thread" require "honeybadger/worker" require "honeybadger/config" diff --git a/tools/profile.rb b/tools/profile.rb index 6701c3992..4da8d2a19 100644 --- a/tools/profile.rb +++ b/tools/profile.rb @@ -5,7 +5,7 @@ RubyProf.start and Honeybadger::Agent.at_exit do result = RubyProf.stop printer = RubyProf::FlatPrinter.new(result) - printer.print(STDOUT, {}) + printer.print($stdout, {}) end 1000.times do From c31bac45795bb87d4bb2f7e353c34f3506277b6e Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Mon, 20 Jan 2025 13:14:05 -0800 Subject: [PATCH 03/13] Remove standard from default rake task This way it won't get run for every appraisal. We'll run it separately via Lefthook in dev and a separate workflow in CI. --- Rakefile | 3 +-- lefthook.yml | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 lefthook.yml diff --git a/Rakefile b/Rakefile index 2d7dd8db0..560885e9e 100644 --- a/Rakefile +++ b/Rakefile @@ -44,8 +44,7 @@ namespace :spec do task all: [:units, :integrations, :features] end -require "standard/rake" desc "Alias for spec:all (default task)" task spec: :"spec:all" task test: :spec -task default: [:standard, :spec] +task default: :spec diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 000000000..5815cbefa --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,8 @@ +# https://github.com/evilmartians/lefthook/blob/master/docs/configuration.md +pre-commit: + parallel: true + commands: + standard: + tags: backend style + glob: "*.rb" + run: bundle exec standardrb {staged_files} From 31816282160597edcc5e10bcdb7afb4758da7c69 Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Mon, 20 Jan 2025 13:15:12 -0800 Subject: [PATCH 04/13] Run standard on PRs --- .github/workflows/standard.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/standard.yml diff --git a/.github/workflows/standard.yml b/.github/workflows/standard.yml new file mode 100644 index 000000000..1ac32d368 --- /dev/null +++ b/.github/workflows/standard.yml @@ -0,0 +1,23 @@ +name: Standard + +on: + pull_request: + branches: + - 'master' + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Run standard + run: | + bundle exec standardrb . \ No newline at end of file From b9e698d9955c7760e7bc13a4fd340cd9f3c5dd95 Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Mon, 20 Jan 2025 13:26:50 -0800 Subject: [PATCH 05/13] Fix Lint/IneffectiveAccessModifier --- lib/honeybadger/backtrace.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/honeybadger/backtrace.rb b/lib/honeybadger/backtrace.rb index 43cab31f4..d555455df 100644 --- a/lib/honeybadger/backtrace.rb +++ b/lib/honeybadger/backtrace.rb @@ -172,11 +172,15 @@ def ==(other) attr_writer :lines, :application_lines - def self.split_multiline_backtrace(backtrace) - if backtrace.size == 1 - backtrace.first.to_s.split(/\n\s*/) - else - backtrace + class << self + private + + def split_multiline_backtrace(backtrace) + if backtrace.size == 1 + backtrace.first.to_s.split(/\n\s*/) + else + backtrace + end end end end From df81fa37d753f1259dcd8f3d937c83e241ee07fa Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Mon, 20 Jan 2025 13:29:13 -0800 Subject: [PATCH 06/13] Fix deprecation warning Rakefile:15: warning: rdoc/task was loaded from the standard library, but is not part of the default gems starting from Ruby 3.5.0. --- honeybadger.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/honeybadger.gemspec b/honeybadger.gemspec index c911f9aab..7afe120c9 100644 --- a/honeybadger.gemspec +++ b/honeybadger.gemspec @@ -35,6 +35,7 @@ Gem::Specification.new do |s| s.executables << "honeybadger" + s.add_development_dependency "rdoc" s.add_dependency "logger" s.add_dependency "ostruct" end From 7edaa5310da409cdcd600843f23a0bddfc0dd6bc Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Mon, 20 Jan 2025 13:38:33 -0800 Subject: [PATCH 07/13] Revert "Fix deprecation warning" This reverts commit df81fa37d753f1259dcd8f3d937c83e241ee07fa. --- honeybadger.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/honeybadger.gemspec b/honeybadger.gemspec index 7afe120c9..c911f9aab 100644 --- a/honeybadger.gemspec +++ b/honeybadger.gemspec @@ -35,7 +35,6 @@ Gem::Specification.new do |s| s.executables << "honeybadger" - s.add_development_dependency "rdoc" s.add_dependency "logger" s.add_dependency "ostruct" end From 8e27331bf4e09facf75851f49fc6c32a4630d738 Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Thu, 23 Jan 2025 09:13:31 -0800 Subject: [PATCH 08/13] Bump minimum Ruby version to 3.0 --- honeybadger.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/honeybadger.gemspec b/honeybadger.gemspec index c911f9aab..bba538126 100644 --- a/honeybadger.gemspec +++ b/honeybadger.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| "source_code_uri" => "https://github.com/honeybadger-io/honeybadger-ruby" } - s.required_ruby_version = ">= 2.3.0" + s.required_ruby_version = ">= 3.0" s.rdoc_options << "--markup=tomdoc" s.rdoc_options << "--main=README.md" From 5af9805c67010372c7ff3b05fe524b3df083d5cf Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Thu, 23 Jan 2025 09:20:23 -0800 Subject: [PATCH 09/13] Update the jruby test matrix --- .github/workflows/ruby.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 329de1f91..c6d5fa863 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -68,11 +68,13 @@ jobs: strategy: matrix: ruby: - - 'jruby-9.2.14.0' + - 'jruby-9.4.10.0' gemfile: - rails6.1.gemfile - # TODO - # - rails7.0.gemfile + - rails7.0.gemfile + - rails7.1.gemfile + - rails7.2.gemfile + - rails8.gemfile # Has to be top level to cache properly env: From 2cff1699b772dfeba917338970c642e5be81f8c1 Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Thu, 23 Jan 2025 09:24:11 -0800 Subject: [PATCH 10/13] Try a later ubuntu version --- .github/workflows/ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index c6d5fa863..0b0fbdd2f 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -63,7 +63,7 @@ jobs: bundle exec rake jruby: - runs-on: ubuntu-20.04 # ubuntu-latest is currently 22.04, which doesn't have a supported JRuby 9 build yet + runs-on: ubuntu-22.04 timeout-minutes: 10 strategy: matrix: From 7b95e629e4e6eae4bb77f2cc226b59afcc3152c6 Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Thu, 23 Jan 2025 09:28:54 -0800 Subject: [PATCH 11/13] Try a not-so-recent jruby version --- .github/workflows/ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 0b0fbdd2f..f7e55884f 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -68,7 +68,7 @@ jobs: strategy: matrix: ruby: - - 'jruby-9.4.10.0' + - 'jruby-9.4.9.0' gemfile: - rails6.1.gemfile - rails7.0.gemfile From 570c2102c69f2466918e599dabf98184e6c92390 Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Thu, 23 Jan 2025 09:32:36 -0800 Subject: [PATCH 12/13] JRuby 9.4.9.0 isn't ready for Rails 8 --- .github/workflows/ruby.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index f7e55884f..1d9403838 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -74,7 +74,6 @@ jobs: - rails7.0.gemfile - rails7.1.gemfile - rails7.2.gemfile - - rails8.gemfile # Has to be top level to cache properly env: From 801c88f4dcce3166e2ceaf32a51f8a52c7b0ac6a Mon Sep 17 00:00:00 2001 From: Benjamin Curtis Date: Thu, 23 Jan 2025 09:35:25 -0800 Subject: [PATCH 13/13] Try to fix ruby-head problem --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index ad57ccb94..f12ba2545 100644 --- a/Gemfile +++ b/Gemfile @@ -13,6 +13,7 @@ gem "webmock" gem "bigdecimal" gem "base64" gem "mutex_m" +gem "rdoc" # Used in Rakefile, removed from default gems in Ruby 3.5.0 # Required by feature specs. gem "capistrano" @@ -30,6 +31,5 @@ group :development do gem "guard-rspec" gem "pry" gem "pry-byebug", platforms: :mri - gem "rdoc" gem "standard" end