Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 6.16.0 #624

Merged
merged 24 commits into from
Aug 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
a530de7
Supress frozen middleware errors in Railtie
imjoehaines Jul 23, 2020
a91776e
Set consistent context in delayed_job integration
mike-stewart Nov 26, 2018
a798bed
Changelog entry for bugsnag/bugsnag-ruby#499
mike-stewart Nov 27, 2018
80e0c80
Add maze runner test for report context class name
imjoehaines Jul 27, 2020
1d5e201
Merge pull request #611 from bugsnag/supress-frozen-middleware-error
imjoehaines Jul 27, 2020
4d10fc1
Merge pull request #615 from bugsnag/delayed-job-context
imjoehaines Jul 28, 2020
c3b1c78
Use BUGSNAG_RELEASE_STAGE by default
imjoehaines Jul 23, 2020
a626e1c
We no longer need to set the release stage env var
imjoehaines Jul 23, 2020
7850434
Add #613 to changelog
imjoehaines Jul 27, 2020
7ac8bb3
Merge pull request #613 from bugsnag/release-stage-environment-variable
imjoehaines Jul 28, 2020
bd03d1d
Fix order app_type is resolved
imjoehaines Jul 30, 2020
717ec5d
Merge pull request #619 from bugsnag/fix-automatic-app-type-detection
imjoehaines Jul 31, 2020
40c13ff
Report runtime versions where they were missing
imjoehaines Jul 31, 2020
b85f5e3
Update changelog
imjoehaines Jul 31, 2020
fb4adbd
Merge pull request #620 from bugsnag/more-runtime-versions
imjoehaines Aug 3, 2020
6be1f85
Remove spec files from bundled gem
t-richards Oct 22, 2019
303791d
Include gemspec and VERSION files
imjoehaines Aug 3, 2020
45b1df6
Add changelog entry
imjoehaines Aug 3, 2020
8182fa5
Merge pull request #621 from bugsnag/reduce-gem-size
imjoehaines Aug 5, 2020
b32525d
Delay serialization until delivery in thread queue
imjoehaines Aug 4, 2020
0b3ecf6
Merge pull request #623 from bugsnag/delay-serialization-until-delivery
imjoehaines Aug 5, 2020
ceb8564
Pin Rubocop version more strictly
imjoehaines Aug 7, 2020
24ed9f6
Merge pull request #625 from bugsnag/pin-rubocop-version
imjoehaines Aug 7, 2020
819b0a3
Bump version to 6.16.0
imjoehaines Aug 7, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ Metrics/BlockNesting:
# Offense count: 4
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 174
Max: 184

# Offense count: 15
# Configuration parameters: IgnoredMethods.
Expand Down
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
Changelog
=========

## 6.16.0 (12 August 2020)

### Enhancements

* Set default Delayed Job error context to job class
| [#499](https://github.com/bugsnag/bugsnag-ruby/pull/499)
| [Mike Stewart](https://github.com/mike-stewart)

* The `BUGSNAG_RELEASE_STAGE` environment variable can now be used to set the release stage. Previously this was only used in Rails applications
| [#613](https://github.com/bugsnag/bugsnag-ruby/pull/613)

* Add support for runtime versions to Delayed Job, Mailman and Shoryuken integrations
| [#620](https://github.com/bugsnag/bugsnag-ruby/pull/620)

* Reduce the size of the bundled gem
| [#571](https://github.com/bugsnag/bugsnag-ruby/pull/571)
| [t-richards](https://github.com/t-richards)

* Move serialization of Reports onto the background thread when using the thread_queue delivery method
| [#623](https://github.com/bugsnag/bugsnag-ruby/pull/623)

## Fixes

* The `app_type` configuration option should no longer be overwritten by Bugsnag and integrations should set this more consistently
| [#619](https://github.com/bugsnag/bugsnag-ruby/pull/619)

## 6.15.0 (27 July 2020)

### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ group :coverage, optional: true do
end

group :rubocop, optional: true do
gem 'rubocop', '~> 0.83'
gem 'rubocop', '~> 0.88.0'
end

group :sidekiq, optional: true do
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.15.0
6.16.0
2 changes: 1 addition & 1 deletion bugsnag.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Gem::Specification.new do |s|
s.homepage = "https://github.com/bugsnag/bugsnag-ruby"
s.licenses = ["MIT"]

s.files = `git ls-files`.split("\n").reject {|file| file.start_with? "example/"}
s.files = `git ls-files -z lib bugsnag.gemspec VERSION`.split("\x0")
s.extra_rdoc_files = [
"LICENSE.txt",
"README.md",
Expand Down
20 changes: 20 additions & 0 deletions features/delayed_job.feature
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Scenario: An unhandled RuntimeError sends a report with arguments
And the event "metaData.job.payload.display_name" equals "TestModel.fail_with_args"
And the event "metaData.job.payload.method_name" equals "fail_with_args"
And the payload field "events.0.metaData.job.payload.args.0" equals "Test"
And the event "device.runtimeVersions.delayed_job" equals "4.1.8"

Scenario: A handled exception sends a report
Given I run the service "delayed_job" with the command "bundle exec rake delayed_job_tests:notify_with_args"
Expand All @@ -34,3 +35,22 @@ Scenario: A handled exception sends a report
And the event "metaData.job.payload.display_name" equals "TestModel.notify_with_args"
And the event "metaData.job.payload.method_name" equals "notify_with_args"
And the payload field "events.0.metaData.job.payload.args.0" equals "Test"
And the event "device.runtimeVersions.delayed_job" equals "4.1.8"

Scenario: The report context uses the class name if no display name is available
Given I run the service "delayed_job" with the command "bundle exec rake delayed_job_tests:report_context"
And I wait to receive a request
Then the request is valid for the error reporting API version "4.0" for the "Ruby Bugsnag Notifier"
And the event "unhandled" is true
And the event "severity" equals "error"
And the event "context" equals "TestReportContextJob"
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
And the event "severityReason.attributes.framework" equals "DelayedJob"
And the exception "errorClass" equals "RuntimeError"
And the event "metaData.job.class" equals "Delayed::Backend::ActiveRecord::Job"
And the event "metaData.job.id" is not null
And the event "metaData.job.attempt" equals 1
And the event "metaData.job.max_attempts" equals 1
And the event "metaData.job.payload.display_name" is null
And the event "metaData.job.payload.method_name" is null
And the event "device.runtimeVersions.delayed_job" equals "4.1.8"
6 changes: 5 additions & 1 deletion features/fixtures/delayed_job/app/Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ namespace :delayed_job_tests do
task :notify_with_args do
run_delayed_job_test('"TestModel.delay.notify_with_args(\"Test\")"')
end

task :report_context do
run_delayed_job_test('"Delayed::Job.enqueue TestReportContextJob.new"')
end
end

def run_delayed_job_test(command)
Expand All @@ -21,4 +25,4 @@ def run_delayed_job_test(command)
end
system("rails runner #{command}")
Process.wait
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class TestReportContextJob < ApplicationJob
queue_as :default

def perform(*)
raise "oh dear"
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
config.project_root = ENV["BUGSNAG_PROJECT_ROOT"] if ENV.include? "BUGSNAG_PROJECT_ROOT"
config.ignore_classes << lambda { |ex| ex.class.to_s == ENV["BUGSNAG_IGNORE_CLASS"] } if ENV.include? "BUGSNAG_IGNORE_CLASS"
config.auto_capture_sessions = ENV["BUGSNAG_AUTO_CAPTURE_SESSIONS"] == "true"
config.release_stage = ENV["BUGSNAG_RELEASE_STAGE"] if ENV.include? "BUGSNAG_RELEASE_STAGE"
config.send_code = ENV["BUGSNAG_SEND_CODE"] != "false"
config.send_environment = ENV["BUGSNAG_SEND_ENVIRONMENT"] == "true"
end
3 changes: 1 addition & 2 deletions features/fixtures/plain/app/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def configure_using_environment
conf.proxy_password = ENV["BUGSNAG_PROXY_PASSWORD"] if ENV.include? "BUGSNAG_PROXY_PASSWORD"
conf.proxy_port = ENV["BUGSNAG_PROXY_PORT"] if ENV.include? "BUGSNAG_PROXY_PORT"
conf.proxy_user = ENV["BUGSNAG_PROXY_USER"] if ENV.include? "BUGSNAG_PROXY_USER"
conf.release_stage = ENV["BUGSNAG_RELEASE_STAGE"] if ENV.include? "BUGSNAG_RELEASE_STAGE"
conf.send_environment = ENV["BUGSNAG_SEND_ENVIRONMENT"] != "false"
conf.send_code = ENV["BUGSNAG_SEND_CODE"] != "false"
conf.timeout = ENV["BUGSNAG_TIMEOUT"] if ENV.include? "BUGSNAG_TIMEOUT"
Expand All @@ -35,4 +34,4 @@ def add_at_exit
Bugsnag.notify($!, true)
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
config.project_root = ENV["BUGSNAG_PROJECT_ROOT"] if ENV.include? "BUGSNAG_PROJECT_ROOT"
config.ignore_classes << lambda { |ex| ex.class.to_s == ENV["BUGSNAG_IGNORE_CLASS"] } if ENV.include? "BUGSNAG_IGNORE_CLASS"
config.auto_capture_sessions = ENV["BUGSNAG_AUTO_CAPTURE_SESSIONS"] == "true" unless ENV["USE_DEFAULT_AUTO_CAPTURE_SESSIONS"] == "true"
config.release_stage = ENV["BUGSNAG_RELEASE_STAGE"] if ENV.include? "BUGSNAG_RELEASE_STAGE"
config.send_code = ENV["BUGSNAG_SEND_CODE"] != "false"
config.send_environment = ENV["BUGSNAG_SEND_ENVIRONMENT"] == "true"
config.meta_data_filters << 'filtered_parameter'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
config.project_root = ENV["BUGSNAG_PROJECT_ROOT"] if ENV.include? "BUGSNAG_PROJECT_ROOT"
config.ignore_classes << lambda { |ex| ex.class.to_s == ENV["BUGSNAG_IGNORE_CLASS"] } if ENV.include? "BUGSNAG_IGNORE_CLASS"
config.auto_capture_sessions = ENV["BUGSNAG_AUTO_CAPTURE_SESSIONS"] == "true" unless ENV["USE_DEFAULT_AUTO_CAPTURE_SESSIONS"] == "true"
config.release_stage = ENV["BUGSNAG_RELEASE_STAGE"] if ENV.include? "BUGSNAG_RELEASE_STAGE"
config.send_code = ENV["BUGSNAG_SEND_CODE"] != "false"
config.send_environment = ENV["BUGSNAG_SEND_ENVIRONMENT"] == "true"
config.meta_data_filters << 'filtered_parameter'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
config.project_root = ENV["BUGSNAG_PROJECT_ROOT"] if ENV.include? "BUGSNAG_PROJECT_ROOT"
config.ignore_classes << lambda { |ex| ex.class.to_s == ENV["BUGSNAG_IGNORE_CLASS"] } if ENV.include? "BUGSNAG_IGNORE_CLASS"
config.auto_capture_sessions = ENV["BUGSNAG_AUTO_CAPTURE_SESSIONS"] == "true" unless ENV["USE_DEFAULT_AUTO_CAPTURE_SESSIONS"] == "true"
config.release_stage = ENV["BUGSNAG_RELEASE_STAGE"] if ENV.include? "BUGSNAG_RELEASE_STAGE"
config.send_code = ENV["BUGSNAG_SEND_CODE"] != "false"
config.send_environment = ENV["BUGSNAG_SEND_ENVIRONMENT"] == "true"
config.meta_data_filters << 'filtered_parameter'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
config.project_root = ENV["BUGSNAG_PROJECT_ROOT"] if ENV.include? "BUGSNAG_PROJECT_ROOT"
config.ignore_classes << lambda { |ex| ex.class.to_s == ENV["BUGSNAG_IGNORE_CLASS"] } if ENV.include? "BUGSNAG_IGNORE_CLASS"
config.auto_capture_sessions = ENV["BUGSNAG_AUTO_CAPTURE_SESSIONS"] == "true" unless ENV["USE_DEFAULT_AUTO_CAPTURE_SESSIONS"] == "true"
config.release_stage = ENV["BUGSNAG_RELEASE_STAGE"] if ENV.include? "BUGSNAG_RELEASE_STAGE"
config.send_code = ENV["BUGSNAG_SEND_CODE"] != "false"
config.send_environment = ENV["BUGSNAG_SEND_ENVIRONMENT"] == "true"
config.meta_data_filters << 'filtered_parameter'
Expand Down
30 changes: 20 additions & 10 deletions lib/bugsnag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -303,15 +303,25 @@ def abort_reason(exception, auto_notify)
def deliver_notification(report)
configuration.info("Notifying #{configuration.notify_endpoint} of #{report.exceptions.last[:errorClass]}")

payload = report_to_json(report)
options = {:headers => report.headers}

Bugsnag::Delivery[configuration.delivery_method].deliver(
configuration.notify_endpoint,
payload,
configuration,
options
)
options = { headers: report.headers }

delivery_method = Bugsnag::Delivery[configuration.delivery_method]

if delivery_method.respond_to?(:serialize_and_deliver)
delivery_method.serialize_and_deliver(
configuration.notify_endpoint,
proc { report_to_json(report) },
configuration,
options
)
else
delivery_method.deliver(
configuration.notify_endpoint,
report_to_json(report),
configuration,
options
)
end

leave_breadcrumb(
report.summary[:error_class],
Expand Down Expand Up @@ -353,7 +363,7 @@ def check_endpoint_setup
# encoding errors and redacting metadata according to "meta_data_filters"
#
# @param report [Report]
# @return string
# @return [String]
def report_to_json(report)
cleaned = cleaner.clean_object(report.as_json)
trimmed = Bugsnag::Helpers.trim_if_needed(cleaned)
Expand Down
50 changes: 49 additions & 1 deletion lib/bugsnag/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class Configuration
attr_accessor :send_code
attr_accessor :project_root
attr_accessor :app_version
attr_accessor :app_type
attr_accessor :meta_data_filters
attr_accessor :logger
attr_accessor :middleware
Expand Down Expand Up @@ -116,6 +115,7 @@ def initialize
self.runtime_versions["ruby"] = RUBY_VERSION
self.runtime_versions["jruby"] = JRUBY_VERSION if defined?(JRUBY_VERSION)
self.timeout = 15
self.release_stage = ENV['BUGSNAG_RELEASE_STAGE']
self.notify_release_stages = nil
self.auto_capture_sessions = true

Expand Down Expand Up @@ -197,6 +197,54 @@ def default_delivery_method=(delivery_method)
@default_delivery_method = delivery_method
end

##
# Get the type of application executing the current code
#
# This is usually used to represent if you are running in a Rails server,
# Sidekiq job, Rake task etc... Bugsnag will automatically detect most
# application types for you
#
# @return [String, nil]
def app_type
@app_type || @detected_app_type
end

##
# Set the type of application executing the current code
#
# If an app_type is set, this will be used instead of the automatically
# detected app_type that Bugsnag would otherwise use
#
# @param app_type [String]
# @return [void]
def app_type=(app_type)
@app_type = app_type
end

##
# Get the detected app_type, which is used when one isn't set explicitly
#
# @api private
#
# @return [String, nil]
def detected_app_type
@detected_app_type
end

##
# Set the detected app_type, which is used when one isn't set explicitly
#
# This allows Bugsnag's integrations to say 'this is a Rails app' while
# allowing the user to overwrite this if they wish
#
# @api private
#
# @param app_type [String]
# @return [void]
def detected_app_type=(app_type)
@detected_app_type = app_type
end

##
# Indicates whether the notifier should send a notification based on the
# configured release stage.
Expand Down
21 changes: 18 additions & 3 deletions lib/bugsnag/delivery/thread_queue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ class ThreadQueue < Synchronous

class << self
##
# Queues a given payload to be delivered asynchronously.
def deliver(url, body, configuration, options={})
# Queues a given payload to be delivered asynchronously
#
# @param url [String]
# @param get_payload [Proc] A Proc that will return the payload.
# @param configuration [Bugsnag::Configuration]
# @param options [Hash]
# @return [void]
def serialize_and_deliver(url, get_payload, configuration, options={})
@configuration = configuration

start_once!
Expand All @@ -21,7 +27,16 @@ def deliver(url, body, configuration, options={})
end

# Add delivery to the worker thread
@queue.push proc { super(url, body, configuration, options) }
@queue.push(proc do
begin
payload = get_payload.call
rescue StandardError => e
configuration.warn("Notification to #{url} failed, #{e.inspect}")
configuration.warn(e.backtrace)
end

Synchronous.deliver(url, payload, configuration, options) unless payload.nil?
end)
end

private
Expand Down
14 changes: 13 additions & 1 deletion lib/bugsnag/integrations/delayed_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,23 @@
module Delayed
module Plugins
class Bugsnag < ::Delayed::Plugin
##
# DelayedJob doesn't have an easy way to fetch its version, but we can use
# Gem.loaded_specs to get the version instead
def self.delayed_job_version
::Gem.loaded_specs['delayed_job'].version.to_s
rescue StandardError
# Explicitly return nil to prevent Rubocop complaining of a suppressed exception
nil
end

callbacks do |lifecycle|
lifecycle.around(:invoke_job) do |job, *args, &block|
begin
::Bugsnag.configuration.app_type = 'delayed_job'
::Bugsnag.configuration.detected_app_type = 'delayed_job'
::Bugsnag.configuration.runtime_versions['delayed_job'] = delayed_job_version if defined?(::Gem)
::Bugsnag.configuration.set_request_data(:delayed_job, job)

block.call(job, *args)
rescue Exception => exception
::Bugsnag.notify(exception, true) do |report|
Expand Down
3 changes: 2 additions & 1 deletion lib/bugsnag/integrations/mailman.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ class Mailman

def initialize
Bugsnag.configuration.internal_middleware.use(Bugsnag::Middleware::Mailman)
Bugsnag.configuration.app_type = "mailman"
Bugsnag.configuration.detected_app_type = "mailman"
Bugsnag.configuration.runtime_versions["mailman"] = ::Mailman::VERSION
end

##
Expand Down
3 changes: 2 additions & 1 deletion lib/bugsnag/integrations/que.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
end
end

Bugsnag.configuration.app_type ||= "que"
Bugsnag.configuration.detected_app_type = "que"

if defined?(::Que::Version)
Bugsnag.configuration.runtime_versions["que"] = ::Que::Version
elsif defined?(::Que::VERSION)
Expand Down
4 changes: 3 additions & 1 deletion lib/bugsnag/integrations/rack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def initialize(app)
config.middleware.insert_before(Bugsnag::Middleware::Callbacks, Bugsnag::Middleware::ClearanceUser) if defined?(Clearance)

# Set environment data for payload
config.app_type ||= "rack"
# Note we only set the detected app_type if it's not already set. This
# ensures we don't overwrite the value set by the Railtie
config.detected_app_type ||= "rack"
config.runtime_versions["rack"] = ::Rack.release if defined?(::Rack)
config.runtime_versions["sinatra"] = ::Sinatra::VERSION if defined?(::Sinatra)
end
Expand Down
Loading