rollbar 2.12.0 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -6
- data/README.md +58 -8
- data/docs/configuration.md +12 -0
- data/gemfiles/rails30.gemfile +1 -0
- data/gemfiles/rails31.gemfile +1 -0
- data/gemfiles/rails32.gemfile +1 -0
- data/gemfiles/rails40.gemfile +3 -0
- data/gemfiles/rails41.gemfile +1 -0
- data/gemfiles/rails42.gemfile +7 -1
- data/gemfiles/rails50.gemfile +2 -1
- data/gemfiles/ruby_1_8_and_1_9_2.gemfile +3 -1
- data/lib/rollbar.rb +70 -654
- data/lib/rollbar/configuration.rb +32 -0
- data/lib/rollbar/item.rb +16 -6
- data/lib/rollbar/item/backtrace.rb +26 -17
- data/lib/rollbar/item/frame.rb +112 -0
- data/lib/rollbar/middleware/js.rb +39 -35
- data/lib/rollbar/middleware/rails/rollbar.rb +3 -3
- data/lib/rollbar/notifier.rb +645 -0
- data/lib/rollbar/plugins/delayed_job/job_data.rb +40 -21
- data/lib/rollbar/plugins/rails.rb +2 -2
- data/lib/rollbar/plugins/rake.rb +32 -6
- data/lib/rollbar/plugins/resque.rb +11 -0
- data/lib/rollbar/plugins/resque/failure.rb +39 -0
- data/lib/rollbar/plugins/validations.rb +10 -0
- data/lib/rollbar/request_data_extractor.rb +36 -18
- data/lib/rollbar/scrubbers/params.rb +2 -1
- data/lib/rollbar/truncation.rb +1 -1
- data/lib/rollbar/truncation/frames_strategy.rb +2 -1
- data/lib/rollbar/truncation/min_body_strategy.rb +2 -1
- data/lib/rollbar/truncation/strings_strategy.rb +1 -1
- data/lib/rollbar/version.rb +1 -1
- data/spec/controllers/home_controller_spec.rb +13 -24
- data/spec/delayed/backend/test.rb +1 -0
- data/spec/requests/home_spec.rb +1 -1
- data/spec/rollbar/configuration_spec.rb +22 -0
- data/spec/rollbar/item/backtrace_spec.rb +26 -0
- data/spec/rollbar/item/frame_spec.rb +267 -0
- data/spec/rollbar/item_spec.rb +27 -2
- data/spec/rollbar/middleware/js_spec.rb +23 -0
- data/spec/rollbar/middleware/sinatra_spec.rb +7 -7
- data/spec/rollbar/notifier_spec.rb +43 -0
- data/spec/rollbar/plugins/delayed_job/{job_data.rb → job_data_spec.rb} +15 -2
- data/spec/rollbar/plugins/rack_spec.rb +7 -7
- data/spec/rollbar/plugins/rake_spec.rb +1 -2
- data/spec/rollbar/plugins/resque/failure_spec.rb +36 -0
- data/spec/rollbar/request_data_extractor_spec.rb +103 -1
- data/spec/rollbar/truncation/min_body_strategy_spec.rb +1 -1
- data/spec/rollbar/truncation/strings_strategy_spec.rb +2 -2
- data/spec/rollbar_bc_spec.rb +4 -4
- data/spec/rollbar_spec.rb +99 -37
- data/spec/spec_helper.rb +2 -2
- data/spec/support/notifier_helpers.rb +2 -0
- metadata +16 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d7a60c8f3a1929550de7236c1f2cad3f06d686ef
         | 
| 4 | 
            +
              data.tar.gz: 7c91ff957d85efa7387384948174d1ea6f745b00
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a53c437380edf552740dec8ece8c8bf90f774b5c1ba420ac8526f8a11eaf8bd502ec6798f70da4ce056cbadae215ebef4629cd75e81742164cc78838fc89a0ba
         | 
| 7 | 
            +
              data.tar.gz: f5bda5da6010fa1a5d6d4d1571c5973e78d42fba2523731be1f5c38295cf808c7f2e9bfdb9035da143963fdb65dc8c586b739e91b4200a2a70f4f7fbafc5eea9
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,32 @@ | |
| 1 1 | 
             
            # Change Log
         | 
| 2 2 |  | 
| 3 | 
            +
            ## 2.13.0
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Features:
         | 
| 6 | 
            +
            - Allow to override config. See [#519](https://github.com/rollbar/rollbar-gem/pull/519).
         | 
| 7 | 
            +
            - Send code and context frame data. See [#523](https://github.com/rollbar/rollbar-gem/pull/523).
         | 
| 8 | 
            +
            - Send GET, POST and raw body in their correct place. See [#522](https://github.com/rollbar/rollbar-gem/pull/522).
         | 
| 9 | 
            +
            - Increase max payload from 128kb to 512kb. See [#521](https://github.com/rollbar/rollbar-gem/pull/521).
         | 
| 10 | 
            +
            - Add resque-rollbar functionality to the gem. See [#516](https://github.com/rollbar/rollbar-gem/pull/516).
         | 
| 11 | 
            +
            - Send custom.orig_host and custom.orig_uuid on too large payloads. See [#518](https://github.com/rollbar/rollbar-gem/pull/518).
         | 
| 12 | 
            +
            - Add Content-Length and Content-Type headers to the reports. See [#513](https://github.com/rollbar/rollbar-gem/pull/513).
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            Bug fixes:
         | 
| 15 | 
            +
            - SecureHeaders fixes. See [#478](https://github.com/rollbar/rollbar-gem/pull/478).
         | 
| 16 | 
            +
            - Include validations plugin in activerecord base. See [#503](https://github.com/rollbar/rollbar-gem/pull/503).
         | 
| 17 | 
            +
            - Require tempfile and use ::Tempfile. See [#514](https://github.com/rollbar/rollbar-gem/pull/514).
         | 
| 18 | 
            +
            - Extract correct client IP from X-Forwarded-For header. See [#515](https://github.com/rollbar/rollbar-gem/pull/515).
         | 
| 19 | 
            +
            - Delayed job fix on job serialization. See [#512](https://github.com/rollbar/rollbar-gem/pull/512).
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            Others:
         | 
| 22 | 
            +
            - Fix tests on rails40 and ruby 1.8.7. See [#485](https://github.com/rollbar/rollbar-gem/pull/485).
         | 
| 23 | 
            +
            - Move log methods to public section. See [#498](https://github.com/rollbar/rollbar-gem/pull/498).
         | 
| 24 | 
            +
            - Change rails50.gemfile to use Rails 5.0.0. See [#495](https://github.com/rollbar/rollbar-gem/pull/495).
         | 
| 25 | 
            +
            - Update CHANGELOG.md to fix incorrect links. See [#502](https://github.com/rollbar/rollbar-gem/pull/502).
         | 
| 26 | 
            +
            - Improve Rake support to avoid conflicts with other services. See [#517](https://github.com/rollbar/rollbar-gem/pull/517).
         | 
| 27 | 
            +
            - Make Codeclimate happier with Rollbar::Middlware::Js. See [#520](https://github.com/rollbar/rollbar-gem/pull/520).
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             | 
| 3 30 | 
             
            ## 2.12.0
         | 
| 4 31 |  | 
| 5 32 | 
             
            Features:
         | 
| @@ -13,7 +40,7 @@ Others: | |
| 13 40 |  | 
| 14 41 | 
             
            ## 2.11.5
         | 
| 15 42 |  | 
| 16 | 
            -
             | 
| 43 | 
            +
            Bugf ixes:
         | 
| 17 44 |  | 
| 18 45 | 
             
            - Use require_dependency for rake and sidekiq plugins. See [#485](https://github.com/rollbar/rollbar-gem/pull/485).
         | 
| 19 46 | 
             
            - Add immediate ActiveModel::Validations monkey patch. See [#484](https://github.com/rollbar/rollbar-gem/pull/484).
         | 
| @@ -53,7 +80,7 @@ Bug fixes: | |
| 53 80 |  | 
| 54 81 | 
             
            New features:
         | 
| 55 82 |  | 
| 56 | 
            -
            - Rollbar.js support  | 
| 83 | 
            +
            - Rollbar.js support with SecureHeaders 2.0. See [#448](https://github.com/rollbar/rollbar-gem/pull/448).
         | 
| 57 84 | 
             
            - Inject extensions in ActiveModel::Validations instead of ActiveRecord::Base. See [#445](https://github.com/rollbar/rollbar-gem/pull/445).
         | 
| 58 85 |  | 
| 59 86 | 
             
            Bug fixes:
         | 
| @@ -64,7 +91,7 @@ Bug fixes: | |
| 64 91 |  | 
| 65 92 | 
             
            Refactors and others:
         | 
| 66 93 |  | 
| 67 | 
            -
            - Refactor Item payload building. See [#452](https://github.com/rollbar/rollbar-gem/pull/ | 
| 94 | 
            +
            - Refactor Item payload building. See [#452](https://github.com/rollbar/rollbar-gem/pull/452).
         | 
| 68 95 | 
             
            - Mock the requests to Rollbar API. See [#450](https://github.com/rollbar/rollbar-gem/pull/450).
         | 
| 69 96 | 
             
            - Add plugins architecture. See [#438](https://github.com/rollbar/rollbar-gem/pull/438).
         | 
| 70 97 | 
             
            - Add TOC for README.md. See [#444](https://github.com/rollbar/rollbar-gem/pull/444).
         | 
| @@ -199,8 +226,8 @@ Features | |
| 199 226 |  | 
| 200 227 | 
             
            Bug fixes:
         | 
| 201 228 |  | 
| 202 | 
            -
            - Use ACCEPT header to check json requests. See [# | 
| 203 | 
            -
            - Fix URL scrubbing when using a malformed URL. See [# | 
| 229 | 
            +
            - Use ACCEPT header to check json requests. See [#333](https://github.com/rollbar/rollbar-gem/pull/333)
         | 
| 230 | 
            +
            - Fix URL scrubbing when using a malformed URL. See [#332](https://github.com/rollbar/rollbar-gem/pull/332)
         | 
| 204 231 |  | 
| 205 232 | 
             
            ## 2.5.1
         | 
| 206 233 |  | 
| @@ -237,7 +264,7 @@ Documentation: | |
| 237 264 |  | 
| 238 265 | 
             
            Bug fixes:
         | 
| 239 266 |  | 
| 240 | 
            -
            - Remove better errors hook. This was causing to report twice the errors. See [#313](https://github.com/rollbar/rollbar-gem/pull/ | 
| 267 | 
            +
            - Remove better errors hook. This was causing to report twice the errors. See [#313](https://github.com/rollbar/rollbar-gem/pull/313)
         | 
| 241 268 |  | 
| 242 269 |  | 
| 243 270 | 
             
            ## 2.3.0
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,10 +1,4 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
            layout: page
         | 
| 3 | 
            -
            sidebar: rollbar_sidebar
         | 
| 4 | 
            -
            permalink: /notifiers/rollbar-gem/
         | 
| 5 | 
            -
            toc: false
         | 
| 6 | 
            -
            ---
         | 
| 7 | 
            -
            # Rollbar [](https://travis-ci.org/rollbar/rollbar-gem/branches)
         | 
| 1 | 
            +
            # Rollbar [](https://travis-ci.org/rollbar/rollbar-gem/branches)
         | 
| 8 2 |  | 
| 9 3 | 
             
            <!-- RemoveNext -->
         | 
| 10 4 | 
             
            [Rollbar](https://rollbar.com) is an error tracking service for Ruby and other languages. The Rollbar service will alert you of problems with your code and help you understand them in a ways never possible before. We love it and we hope you will too.
         | 
| @@ -36,6 +30,8 @@ This is the Ruby library for Rollbar. It will instrument many kinds of Ruby appl | |
| 36 30 | 
             
            - [Before process hook](#before-process-hook)
         | 
| 37 31 | 
             
            - [Transform hook](#transform-hook)
         | 
| 38 32 | 
             
            - [The Scope](#the-scope)
         | 
| 33 | 
            +
            - [Override configuration](#override-configuration)
         | 
| 34 | 
            +
            - [Code and context](#code-and-context)
         | 
| 39 35 | 
             
            - [Silencing exceptions at runtime](#silencing-exceptions-at-runtime)
         | 
| 40 36 | 
             
            - [Sending backtrace without rescued exceptions](#sending-backtrace-without-rescued-exceptions)
         | 
| 41 37 | 
             
            - [ActiveJob integration](#activejob-integration)
         | 
| @@ -613,6 +609,49 @@ your_handler = proc do |options| | |
| 613 609 | 
             
            end
         | 
| 614 610 | 
             
            ```
         | 
| 615 611 |  | 
| 612 | 
            +
            ## Override configuration
         | 
| 613 | 
            +
             | 
| 614 | 
            +
            There are some cases where you would need to change the Rollbar configuration for a specific block of code so a new configuration is used on the reported errors in that block. You can use `Rollbar.with_config` to do this. It receives a `Hash` object with the configuration overrides you want to use for the given block. The configuration options to use can be read at [Configuration](https://rollbar.com/docs/notifier/rollbar-gem/configuration/). So the `Hash` passed to `with_config` can be like `{environment: 'specific-environment'}`. Example:
         | 
| 615 | 
            +
             | 
| 616 | 
            +
            ```ruby
         | 
| 617 | 
            +
            Rollbar.with_config(use_async: false) do
         | 
| 618 | 
            +
              begin
         | 
| 619 | 
            +
                # do work that may crash
         | 
| 620 | 
            +
              rescue => e
         | 
| 621 | 
            +
                Rollbar.error(e)
         | 
| 622 | 
            +
              end
         | 
| 623 | 
            +
            end
         | 
| 624 | 
            +
            ```
         | 
| 625 | 
            +
             | 
| 626 | 
            +
            This method looks similar to `Rollbar.scoped` and internally `Rollbar.with_config` uses it. Now `Rollbar.scoped` can receive a second argument with the config overrides for the given block of code. So if you need to set a new payload scope and new config for a code block, you can:
         | 
| 627 | 
            +
             | 
| 628 | 
            +
            ```ruby
         | 
| 629 | 
            +
            scope = {context: 'foo'}
         | 
| 630 | 
            +
            new_config = {framework: 'Sinatra'}
         | 
| 631 | 
            +
             | 
| 632 | 
            +
            Rollbar.scoped(scope, new_config) do
         | 
| 633 | 
            +
              begin
         | 
| 634 | 
            +
                # do work that may crash
         | 
| 635 | 
            +
              rescue => e
         | 
| 636 | 
            +
                Rollbar.error(e)
         | 
| 637 | 
            +
              end
         | 
| 638 | 
            +
            end
         | 
| 639 | 
            +
            ```
         | 
| 640 | 
            +
             | 
| 641 | 
            +
            In the example from above we are defining a new payload scope and overriding the `framework` configuration for the reported errors inside the given block.
         | 
| 642 | 
            +
             | 
| 643 | 
            +
            ## Code and context
         | 
| 644 | 
            +
             | 
| 645 | 
            +
            By default we send the following values for each backtrace frame: `filename`, `lineno` and `method`. You can configure Rollbar to additionally send `code` (the actual line of code) and `context` (lines before and after) for each frame.
         | 
| 646 | 
            +
             | 
| 647 | 
            +
            Since the backtrace can be very long, you can configure to send this data for all the frames or only your in-project frames. There are three levels: `:none` (default), `:app` (only your project files) and `:all`. Example:
         | 
| 648 | 
            +
             | 
| 649 | 
            +
            ```ruby
         | 
| 650 | 
            +
            Rollbar.configure do |config|
         | 
| 651 | 
            +
               config.send_extra_frame_data = :app
         | 
| 652 | 
            +
            end
         | 
| 653 | 
            +
            ```
         | 
| 654 | 
            +
             | 
| 616 655 | 
             
            ## Silencing exceptions at runtime
         | 
| 617 656 |  | 
| 618 657 | 
             
            If you just want to disable exception reporting for a single block, use ```Rollbar.silenced```:
         | 
| @@ -937,7 +976,18 @@ If you're using [Goalie](https://github.com/obvio171/goalie) for custom error pa | |
| 937 976 |  | 
| 938 977 | 
             
            ## Resque
         | 
| 939 978 |  | 
| 940 | 
            -
             | 
| 979 | 
            +
            From a time ago, Resque errors reporting was supported by the gem [resque-rollbar](https://github.com/dimko/resque-rollbar). Now that functionality is built-in in the own gem. All you need to do is use `Resque::Failure::Rollbar` as the failure backend for Resque.
         | 
| 980 | 
            +
             | 
| 981 | 
            +
            In your resque configuration add next lines:
         | 
| 982 | 
            +
             | 
| 983 | 
            +
            ```ruby
         | 
| 984 | 
            +
            require 'resque/failure/multiple'
         | 
| 985 | 
            +
            require 'resque/failure/redis'
         | 
| 986 | 
            +
            require 'rollbar'
         | 
| 987 | 
            +
             | 
| 988 | 
            +
            Resque::Failure::Multiple.classes = [ Resque::Failure::Redis, Resque::Failure::Rollbar ]
         | 
| 989 | 
            +
            Resque::Failure.backend = Resque::Failure::Multiple
         | 
| 990 | 
            +
            ```
         | 
| 941 991 |  | 
| 942 992 | 
             
            ## SSL
         | 
| 943 993 |  | 
    
        data/docs/configuration.md
    CHANGED
    
    | @@ -102,6 +102,18 @@ Rollbar notifier. | |
| 102 102 |  | 
| 103 103 | 
             
            The number of job failures before reporting the failure to Rollbar.
         | 
| 104 104 |  | 
| 105 | 
            +
            ### enabled
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            **Default** `true`
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            Set to false to turn Rollbar off and stop reporting errors.
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            ### environment
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            **Default** unspecified
         | 
| 114 | 
            +
             | 
| 115 | 
            +
            The environment that your code is running in.
         | 
| 116 | 
            +
             | 
| 105 117 | 
             
            ### failover_handlers
         | 
| 106 118 |  | 
| 107 119 | 
             
            An array of backup handlers if the async handlers fails. Each should respond to
         | 
    
        data/gemfiles/rails30.gemfile
    CHANGED
    
    
    
        data/gemfiles/rails31.gemfile
    CHANGED
    
    
    
        data/gemfiles/rails32.gemfile
    CHANGED
    
    
    
        data/gemfiles/rails40.gemfile
    CHANGED
    
    | @@ -23,8 +23,10 @@ gem 'sidekiq', '>= 2.13.0' if RUBY_VERSION != '1.8.7' | |
| 23 23 |  | 
| 24 24 | 
             
            if RUBY_VERSION.start_with?('1.9')
         | 
| 25 25 | 
             
              gem 'sucker_punch', '~> 1.0'
         | 
| 26 | 
            +
              gem 'json', '~> 1.8'
         | 
| 26 27 | 
             
            elsif RUBY_VERSION.start_with?('2')
         | 
| 27 28 | 
             
              gem 'sucker_punch', '~> 2.0'
         | 
| 29 | 
            +
              gem 'json', '~> 2.0'
         | 
| 28 30 | 
             
            end
         | 
| 29 31 |  | 
| 30 32 | 
             
            gem 'sinatra'
         | 
| @@ -41,5 +43,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') | |
| 41 43 | 
             
            end
         | 
| 42 44 |  | 
| 43 45 | 
             
            gem 'webmock', :require => false
         | 
| 46 | 
            +
            gem 'resque'
         | 
| 44 47 |  | 
| 45 48 | 
             
            gemspec :path => "../"
         | 
    
        data/gemfiles/rails41.gemfile
    CHANGED
    
    
    
        data/gemfiles/rails42.gemfile
    CHANGED
    
    | @@ -16,7 +16,6 @@ gem "rails", "4.2.3" | |
| 16 16 | 
             
            gem 'rspec-rails', '~> 3.4'
         | 
| 17 17 | 
             
            gem 'rake'
         | 
| 18 18 |  | 
| 19 | 
            -
            gem 'oj', '~> 2.12.14' unless is_jruby
         | 
| 20 19 | 
             
            gem 'sidekiq', '>= 2.13.0' if RUBY_VERSION != '1.8.7'
         | 
| 21 20 |  | 
| 22 21 | 
             
            if RUBY_VERSION.start_with?('1.9')
         | 
| @@ -25,6 +24,12 @@ elsif RUBY_VERSION.start_with?('2') | |
| 25 24 | 
             
              gem 'sucker_punch', '~> 2.0'
         | 
| 26 25 | 
             
            end
         | 
| 27 26 |  | 
| 27 | 
            +
            if RUBY_VERSION.start_with?('2.4')
         | 
| 28 | 
            +
              gem 'oj', '~> 2.16.0' unless is_jruby
         | 
| 29 | 
            +
            else
         | 
| 30 | 
            +
              gem 'oj', '~> 2.12.14' unless is_jruby
         | 
| 31 | 
            +
            end
         | 
| 32 | 
            +
             | 
| 28 33 | 
             
            gem 'sinatra'
         | 
| 29 34 | 
             
            gem 'resque'
         | 
| 30 35 | 
             
            gem 'delayed_job', :require => false
         | 
| @@ -39,5 +44,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') | |
| 39 44 | 
             
            end
         | 
| 40 45 |  | 
| 41 46 | 
             
            gem 'webmock', :require => false
         | 
| 47 | 
            +
            gem 'resque'
         | 
| 42 48 |  | 
| 43 49 | 
             
            gemspec :path => "../"
         | 
    
        data/gemfiles/rails50.gemfile
    CHANGED
    
    | @@ -12,7 +12,7 @@ gem 'rubysl', '~> 2.0', :platform => :rbx | |
| 12 12 | 
             
            gem 'racc', :platform => :rbx
         | 
| 13 13 | 
             
            gem 'minitest', :platform => :rbx
         | 
| 14 14 | 
             
            gem 'rubinius-developer_tools', :platform => :rbx
         | 
| 15 | 
            -
            gem 'rails', '~> 5.0.0 | 
| 15 | 
            +
            gem 'rails', '~> 5.0.0'
         | 
| 16 16 |  | 
| 17 17 | 
             
            gem 'rspec-core', '~> 3.5.0.beta3'
         | 
| 18 18 | 
             
            gem 'rspec-rails', '~> 3.5.0.beta3'
         | 
| @@ -45,5 +45,6 @@ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0') | |
| 45 45 | 
             
            end
         | 
| 46 46 |  | 
| 47 47 | 
             
            gem 'webmock', :require => false
         | 
| 48 | 
            +
            gem 'resque'
         | 
| 48 49 |  | 
| 49 50 | 
             
            gemspec :path => '../'
         | 
| @@ -33,11 +33,13 @@ gem 'resque' | |
| 33 33 | 
             
            gem 'delayed_job', :require => false
         | 
| 34 34 | 
             
            gem 'redis'
         | 
| 35 35 | 
             
            gem 'database_cleaner', '~> 1.0.0'
         | 
| 36 | 
            -
            gem 'genspec', ' | 
| 36 | 
            +
            gem 'genspec', '= 0.2.8'
         | 
| 37 37 | 
             
            gem 'girl_friday', '>= 0.11.1'
         | 
| 38 38 |  | 
| 39 39 | 
             
            if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.0')
         | 
| 40 40 | 
             
              gem 'mime-types', '< 3.0'
         | 
| 41 41 | 
             
            end
         | 
| 42 42 |  | 
| 43 | 
            +
            gem 'resque'
         | 
| 44 | 
            +
             | 
| 43 45 | 
             
            gemspec :path => '../'
         | 
    
        data/lib/rollbar.rb
    CHANGED
    
    | @@ -12,633 +12,19 @@ end | |
| 12 12 |  | 
| 13 13 | 
             
            require 'rollbar/version'
         | 
| 14 14 | 
             
            require 'rollbar/plugins'
         | 
| 15 | 
            -
            require 'rollbar/json'
         | 
| 16 | 
            -
            require 'rollbar/js'
         | 
| 17 15 | 
             
            require 'rollbar/configuration'
         | 
| 18 | 
            -
            require 'rollbar/item'
         | 
| 19 | 
            -
            require 'rollbar/encoding'
         | 
| 20 16 | 
             
            require 'rollbar/logger_proxy'
         | 
| 21 | 
            -
            require 'rollbar/exception_reporter'
         | 
| 22 | 
            -
            require 'rollbar/util'
         | 
| 23 | 
            -
            require 'rollbar/delay/girl_friday' if defined?(GirlFriday)
         | 
| 24 | 
            -
            require 'rollbar/delay/thread'
         | 
| 25 | 
            -
            require 'rollbar/truncation'
         | 
| 26 17 | 
             
            require 'rollbar/exceptions'
         | 
| 27 18 | 
             
            require 'rollbar/lazy_store'
         | 
| 28 | 
            -
            require 'rollbar/ | 
| 19 | 
            +
            require 'rollbar/notifier'
         | 
| 29 20 |  | 
| 21 | 
            +
            # The Rollbar module. It stores a Rollbar::Notifier per thread and
         | 
| 22 | 
            +
            # provides some module methods in order to use the current thread notifier.
         | 
| 30 23 | 
             
            module Rollbar
         | 
| 31 24 | 
             
              PUBLIC_NOTIFIER_METHODS = %w(debug info warn warning error critical log logger
         | 
| 32 | 
            -
                                           process_item process_from_async_handler scope | 
| 33 | 
            -
                                            | 
| 34 | 
            -
             | 
| 35 | 
            -
              class Notifier
         | 
| 36 | 
            -
                attr_accessor :configuration
         | 
| 37 | 
            -
                attr_accessor :last_report
         | 
| 38 | 
            -
                attr_reader :scope_object
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                @file_semaphore = Mutex.new
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                def initialize(parent_notifier = nil, payload_options = nil, scope = nil)
         | 
| 43 | 
            -
                  if parent_notifier
         | 
| 44 | 
            -
                    @configuration = parent_notifier.configuration.clone
         | 
| 45 | 
            -
                    @scope_object = parent_notifier.scope_object.clone
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                    Rollbar::Util.deep_merge(@configuration.payload_options, payload_options) if payload_options
         | 
| 48 | 
            -
                    Rollbar::Util.deep_merge(@scope_object, scope) if scope
         | 
| 49 | 
            -
                  else
         | 
| 50 | 
            -
                    @configuration = ::Rollbar::Configuration.new
         | 
| 51 | 
            -
                    @scope_object = ::Rollbar::LazyStore.new(scope)
         | 
| 52 | 
            -
                  end
         | 
| 53 | 
            -
                end
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                # Similar to configure below, but used only internally within the gem
         | 
| 56 | 
            -
                # to configure it without initializing any of the third party hooks
         | 
| 57 | 
            -
                def preconfigure
         | 
| 58 | 
            -
                  yield(configuration)
         | 
| 59 | 
            -
                end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                # Configures the notifier instance
         | 
| 62 | 
            -
                def configure
         | 
| 63 | 
            -
                  configuration.enabled = true if configuration.enabled.nil?
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                  yield(configuration)
         | 
| 66 | 
            -
                end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                def scope(options = {})
         | 
| 69 | 
            -
                  self.class.new(self, nil, options)
         | 
| 70 | 
            -
                end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                def scope!(options = {})
         | 
| 73 | 
            -
                  Rollbar::Util.deep_merge(scope_object, options)
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  self
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                # Returns a new notifier with same configuration options
         | 
| 79 | 
            -
                # but it sets Configuration#safely to true.
         | 
| 80 | 
            -
                # We are using this flag to avoid having inifite loops
         | 
| 81 | 
            -
                # when evaluating some custom user methods.
         | 
| 82 | 
            -
                def safely
         | 
| 83 | 
            -
                  new_notifier = scope
         | 
| 84 | 
            -
                  new_notifier.configuration.safely = true
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                  new_notifier
         | 
| 87 | 
            -
                end
         | 
| 88 | 
            -
             | 
| 89 | 
            -
                # Turns off reporting for the given block.
         | 
| 90 | 
            -
                #
         | 
| 91 | 
            -
                # @example
         | 
| 92 | 
            -
                #   Rollbar.silenced { raise }
         | 
| 93 | 
            -
                #
         | 
| 94 | 
            -
                # @yield Block which exceptions won't be reported.
         | 
| 95 | 
            -
                def silenced
         | 
| 96 | 
            -
                  yield
         | 
| 97 | 
            -
                rescue => e
         | 
| 98 | 
            -
                  e.instance_variable_set(:@_rollbar_do_not_report, true)
         | 
| 99 | 
            -
                  raise
         | 
| 100 | 
            -
                end
         | 
| 101 | 
            -
             | 
| 102 | 
            -
                # Sends a report to Rollbar.
         | 
| 103 | 
            -
                #
         | 
| 104 | 
            -
                # Accepts any number of arguments. The last String argument will become
         | 
| 105 | 
            -
                # the message or description of the report. The last Exception argument
         | 
| 106 | 
            -
                # will become the associated exception for the report. The last hash
         | 
| 107 | 
            -
                # argument will be used as the extra data for the report.
         | 
| 108 | 
            -
                #
         | 
| 109 | 
            -
                # @example
         | 
| 110 | 
            -
                #   begin
         | 
| 111 | 
            -
                #     foo = bar
         | 
| 112 | 
            -
                #   rescue => e
         | 
| 113 | 
            -
                #     Rollbar.log(e)
         | 
| 114 | 
            -
                #   end
         | 
| 115 | 
            -
                #
         | 
| 116 | 
            -
                # @example
         | 
| 117 | 
            -
                #   Rollbar.log('This is a simple log message')
         | 
| 118 | 
            -
                #
         | 
| 119 | 
            -
                # @example
         | 
| 120 | 
            -
                #   Rollbar.log(e, 'This is a description of the exception')
         | 
| 121 | 
            -
                #
         | 
| 122 | 
            -
                def log(level, *args)
         | 
| 123 | 
            -
                  return 'disabled' unless configuration.enabled
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                  message, exception, extra = extract_arguments(args)
         | 
| 126 | 
            -
                  use_exception_level_filters = extra && extra.delete(:use_exception_level_filters) == true
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                  return 'ignored' if ignored?(exception, use_exception_level_filters)
         | 
| 129 | 
            -
             | 
| 130 | 
            -
                  begin
         | 
| 131 | 
            -
                    call_before_process(:level => level,
         | 
| 132 | 
            -
                                        :exception => exception,
         | 
| 133 | 
            -
                                        :message => message,
         | 
| 134 | 
            -
                                        :extra => extra)
         | 
| 135 | 
            -
                  rescue Rollbar::Ignore
         | 
| 136 | 
            -
                    return 'ignored'
         | 
| 137 | 
            -
                  end
         | 
| 138 | 
            -
             | 
| 139 | 
            -
                  level = lookup_exception_level(level, exception,
         | 
| 140 | 
            -
                                                 use_exception_level_filters)
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                  begin
         | 
| 143 | 
            -
                    report(level, message, exception, extra)
         | 
| 144 | 
            -
                  rescue Exception => e
         | 
| 145 | 
            -
                    report_internal_error(e)
         | 
| 146 | 
            -
             | 
| 147 | 
            -
                    'error'
         | 
| 148 | 
            -
                  end
         | 
| 149 | 
            -
                end
         | 
| 150 | 
            -
             | 
| 151 | 
            -
                # See log() above
         | 
| 152 | 
            -
                def debug(*args)
         | 
| 153 | 
            -
                  log('debug', *args)
         | 
| 154 | 
            -
                end
         | 
| 155 | 
            -
             | 
| 156 | 
            -
                # See log() above
         | 
| 157 | 
            -
                def info(*args)
         | 
| 158 | 
            -
                  log('info', *args)
         | 
| 159 | 
            -
                end
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                # See log() above
         | 
| 162 | 
            -
                def warn(*args)
         | 
| 163 | 
            -
                  log('warning', *args)
         | 
| 164 | 
            -
                end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
                # See log() above
         | 
| 167 | 
            -
                def warning(*args)
         | 
| 168 | 
            -
                  log('warning', *args)
         | 
| 169 | 
            -
                end
         | 
| 170 | 
            -
             | 
| 171 | 
            -
                # See log() above
         | 
| 172 | 
            -
                def error(*args)
         | 
| 173 | 
            -
                  log('error', *args)
         | 
| 174 | 
            -
                end
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                # See log() above
         | 
| 177 | 
            -
                def critical(*args)
         | 
| 178 | 
            -
                  log('critical', *args)
         | 
| 179 | 
            -
                end
         | 
| 180 | 
            -
             | 
| 181 | 
            -
                def process_item(item)
         | 
| 182 | 
            -
                  if configuration.write_to_file
         | 
| 183 | 
            -
                    if configuration.use_async
         | 
| 184 | 
            -
                      @file_semaphore.synchronize {
         | 
| 185 | 
            -
                        write_item(item)
         | 
| 186 | 
            -
                      }
         | 
| 187 | 
            -
                    else
         | 
| 188 | 
            -
                      write_item(item)
         | 
| 189 | 
            -
                    end
         | 
| 190 | 
            -
                  else
         | 
| 191 | 
            -
                    send_item(item)
         | 
| 192 | 
            -
                  end
         | 
| 193 | 
            -
                rescue => e
         | 
| 194 | 
            -
                  log_error("[Rollbar] Error processing the item: #{e.class}, #{e.message}. Item: #{item.payload.inspect}")
         | 
| 195 | 
            -
                  raise e
         | 
| 196 | 
            -
                end
         | 
| 197 | 
            -
             | 
| 198 | 
            -
                # We will reraise exceptions in this method so async queues
         | 
| 199 | 
            -
                # can retry the job or, in general, handle an error report some way.
         | 
| 200 | 
            -
                #
         | 
| 201 | 
            -
                # At same time that exception is silenced so we don't generate
         | 
| 202 | 
            -
                # infinite reports. This example is what we want to avoid:
         | 
| 203 | 
            -
                #
         | 
| 204 | 
            -
                # 1. New exception in a the project is raised
         | 
| 205 | 
            -
                # 2. That report enqueued to Sidekiq queue.
         | 
| 206 | 
            -
                # 3. The Sidekiq job tries to send the report to our API
         | 
| 207 | 
            -
                # 4. The report fails, for example cause a network failure,
         | 
| 208 | 
            -
                #    and a exception is raised
         | 
| 209 | 
            -
                # 5. We report an internal error for that exception
         | 
| 210 | 
            -
                # 6. We reraise the exception so Sidekiq job fails and
         | 
| 211 | 
            -
                #    Sidekiq can retry the job reporting the original exception
         | 
| 212 | 
            -
                # 7. Because the job failed and Sidekiq can be managed by rollbar we'll
         | 
| 213 | 
            -
                #    report a new exception.
         | 
| 214 | 
            -
                # 8. Go to point 2.
         | 
| 215 | 
            -
                #
         | 
| 216 | 
            -
                # We'll then push to Sidekiq queue indefinitely until the network failure
         | 
| 217 | 
            -
                # is fixed.
         | 
| 218 | 
            -
                #
         | 
| 219 | 
            -
                # Using Rollbar.silenced we avoid the above behavior but Sidekiq
         | 
| 220 | 
            -
                # will have a chance to retry the original job.
         | 
| 221 | 
            -
                def process_from_async_handler(payload)
         | 
| 222 | 
            -
                  payload = Rollbar::JSON.load(payload) if payload.is_a?(String)
         | 
| 223 | 
            -
             | 
| 224 | 
            -
                  item = Item.build_with(payload,
         | 
| 225 | 
            -
                                         :notifier => self,
         | 
| 226 | 
            -
                                         :configuration => configuration,
         | 
| 227 | 
            -
                                         :logger => logger)
         | 
| 228 | 
            -
             | 
| 229 | 
            -
                  Rollbar.silenced do
         | 
| 230 | 
            -
                    begin
         | 
| 231 | 
            -
                      process_item(item)
         | 
| 232 | 
            -
                    rescue => e
         | 
| 233 | 
            -
                      report_internal_error(e)
         | 
| 234 | 
            -
             | 
| 235 | 
            -
                      raise
         | 
| 236 | 
            -
                    end
         | 
| 237 | 
            -
                  end
         | 
| 238 | 
            -
                end
         | 
| 239 | 
            -
             | 
| 240 | 
            -
                def send_failsafe(message, exception)
         | 
| 241 | 
            -
                  exception_reason = failsafe_reason(message, exception)
         | 
| 242 | 
            -
             | 
| 243 | 
            -
                  log_error "[Rollbar] Sending failsafe response due to #{exception_reason}"
         | 
| 244 | 
            -
             | 
| 245 | 
            -
                  body = failsafe_body(exception_reason)
         | 
| 246 | 
            -
             | 
| 247 | 
            -
                  failsafe_data = {
         | 
| 248 | 
            -
                    :level => 'error',
         | 
| 249 | 
            -
                    :environment => configuration.environment.to_s,
         | 
| 250 | 
            -
                    :body => {
         | 
| 251 | 
            -
                      :message => {
         | 
| 252 | 
            -
                        :body => body
         | 
| 253 | 
            -
                      }
         | 
| 254 | 
            -
                    },
         | 
| 255 | 
            -
                    :notifier => {
         | 
| 256 | 
            -
                      :name => 'rollbar-gem',
         | 
| 257 | 
            -
                      :version => VERSION
         | 
| 258 | 
            -
                    },
         | 
| 259 | 
            -
                    :internal => true,
         | 
| 260 | 
            -
                    :failsafe => true
         | 
| 261 | 
            -
                  }
         | 
| 262 | 
            -
             | 
| 263 | 
            -
                  failsafe_payload = {
         | 
| 264 | 
            -
                    'access_token' => configuration.access_token,
         | 
| 265 | 
            -
                    'data' => failsafe_data
         | 
| 266 | 
            -
                  }
         | 
| 267 | 
            -
             | 
| 268 | 
            -
                  begin
         | 
| 269 | 
            -
                    item = Item.build_with(failsafe_payload,
         | 
| 270 | 
            -
                                           :notifier => self,
         | 
| 271 | 
            -
                                           :configuration => configuration,
         | 
| 272 | 
            -
                                           :logger => logger)
         | 
| 273 | 
            -
                    schedule_item(item)
         | 
| 274 | 
            -
                  rescue => e
         | 
| 275 | 
            -
                    log_error "[Rollbar] Error sending failsafe : #{e}"
         | 
| 276 | 
            -
                  end
         | 
| 277 | 
            -
             | 
| 278 | 
            -
                  failsafe_payload
         | 
| 279 | 
            -
                end
         | 
| 280 | 
            -
             | 
| 281 | 
            -
                private
         | 
| 282 | 
            -
             | 
| 283 | 
            -
                def call_before_process(options)
         | 
| 284 | 
            -
                  options = {
         | 
| 285 | 
            -
                    :level => options[:level],
         | 
| 286 | 
            -
                    :scope => scope_object,
         | 
| 287 | 
            -
                    :exception => options[:exception],
         | 
| 288 | 
            -
                    :message => options[:message],
         | 
| 289 | 
            -
                    :extra => options[:extra]
         | 
| 290 | 
            -
                  }
         | 
| 291 | 
            -
                  handlers = configuration.before_process
         | 
| 292 | 
            -
             | 
| 293 | 
            -
                  handlers.each do |handler|
         | 
| 294 | 
            -
                    begin
         | 
| 295 | 
            -
                      handler.call(options)
         | 
| 296 | 
            -
                    rescue Rollbar::Ignore
         | 
| 297 | 
            -
                      raise
         | 
| 298 | 
            -
                    rescue => e
         | 
| 299 | 
            -
                      log_error("[Rollbar] Error calling the `before_process` hook: #{e}")
         | 
| 300 | 
            -
             | 
| 301 | 
            -
                      break
         | 
| 302 | 
            -
                    end
         | 
| 303 | 
            -
                  end
         | 
| 304 | 
            -
                end
         | 
| 305 | 
            -
             | 
| 306 | 
            -
                def extract_arguments(args)
         | 
| 307 | 
            -
                  message = nil
         | 
| 308 | 
            -
                  exception = nil
         | 
| 309 | 
            -
                  extra = nil
         | 
| 310 | 
            -
             | 
| 311 | 
            -
                  args.each do |arg|
         | 
| 312 | 
            -
                    if arg.is_a?(String)
         | 
| 313 | 
            -
                      message = arg
         | 
| 314 | 
            -
                    elsif arg.is_a?(Exception)
         | 
| 315 | 
            -
                      exception = arg
         | 
| 316 | 
            -
                    elsif arg.is_a?(Hash)
         | 
| 317 | 
            -
                      extra = arg
         | 
| 318 | 
            -
                    end
         | 
| 319 | 
            -
                  end
         | 
| 320 | 
            -
             | 
| 321 | 
            -
                  [message, exception, extra]
         | 
| 322 | 
            -
                end
         | 
| 323 | 
            -
             | 
| 324 | 
            -
                def lookup_exception_level(orig_level, exception, use_exception_level_filters)
         | 
| 325 | 
            -
                  return orig_level unless use_exception_level_filters
         | 
| 326 | 
            -
             | 
| 327 | 
            -
                  exception_level = filtered_level(exception)
         | 
| 328 | 
            -
                  return exception_level if exception_level
         | 
| 329 | 
            -
             | 
| 330 | 
            -
                  orig_level
         | 
| 331 | 
            -
                end
         | 
| 332 | 
            -
             | 
| 333 | 
            -
                def ignored?(exception, use_exception_level_filters = false)
         | 
| 334 | 
            -
                  return false unless exception
         | 
| 335 | 
            -
                  return true if use_exception_level_filters && filtered_level(exception) == 'ignore'
         | 
| 336 | 
            -
                  return true if exception.instance_variable_get(:@_rollbar_do_not_report)
         | 
| 337 | 
            -
             | 
| 338 | 
            -
                  false
         | 
| 339 | 
            -
                end
         | 
| 340 | 
            -
             | 
| 341 | 
            -
                def filtered_level(exception)
         | 
| 342 | 
            -
                  return unless exception
         | 
| 343 | 
            -
             | 
| 344 | 
            -
                  filter = configuration.exception_level_filters[exception.class.name]
         | 
| 345 | 
            -
                  if filter.respond_to?(:call)
         | 
| 346 | 
            -
                    filter.call(exception)
         | 
| 347 | 
            -
                  else
         | 
| 348 | 
            -
                    filter
         | 
| 349 | 
            -
                  end
         | 
| 350 | 
            -
                end
         | 
| 351 | 
            -
             | 
| 352 | 
            -
                def report(level, message, exception, extra)
         | 
| 353 | 
            -
                  unless message || exception || extra
         | 
| 354 | 
            -
                    log_error '[Rollbar] Tried to send a report with no message, exception or extra data.'
         | 
| 355 | 
            -
             | 
| 356 | 
            -
                    return 'error'
         | 
| 357 | 
            -
                  end
         | 
| 358 | 
            -
             | 
| 359 | 
            -
                  item = build_item(level, message, exception, extra)
         | 
| 360 | 
            -
             | 
| 361 | 
            -
                  return 'ignored' if item.ignored?
         | 
| 362 | 
            -
             | 
| 363 | 
            -
                  schedule_item(item)
         | 
| 364 | 
            -
             | 
| 365 | 
            -
                  data = item['data']
         | 
| 366 | 
            -
                  log_instance_link(data)
         | 
| 367 | 
            -
                  Rollbar.last_report = data
         | 
| 368 | 
            -
             | 
| 369 | 
            -
                  data
         | 
| 370 | 
            -
                end
         | 
| 371 | 
            -
             | 
| 372 | 
            -
                # Reports an internal error in the Rollbar library. This will be reported within the configured
         | 
| 373 | 
            -
                # Rollbar project. We'll first attempt to provide a report including the exception traceback.
         | 
| 374 | 
            -
                # If that fails, we'll fall back to a more static failsafe response.
         | 
| 375 | 
            -
                def report_internal_error(exception)
         | 
| 376 | 
            -
                  log_error "[Rollbar] Reporting internal error encountered while sending data to Rollbar."
         | 
| 377 | 
            -
             | 
| 378 | 
            -
                  begin
         | 
| 379 | 
            -
                    item = build_item('error', nil, exception, {:internal => true})
         | 
| 380 | 
            -
                  rescue => e
         | 
| 381 | 
            -
                    send_failsafe("build_item in exception_data", e)
         | 
| 382 | 
            -
                    return
         | 
| 383 | 
            -
                  end
         | 
| 384 | 
            -
             | 
| 385 | 
            -
                  begin
         | 
| 386 | 
            -
                    process_item(item)
         | 
| 387 | 
            -
                  rescue => e
         | 
| 388 | 
            -
                    send_failsafe("error in process_item", e)
         | 
| 389 | 
            -
                    return
         | 
| 390 | 
            -
                  end
         | 
| 391 | 
            -
             | 
| 392 | 
            -
                  begin
         | 
| 393 | 
            -
                    log_instance_link(item['data'])
         | 
| 394 | 
            -
                  rescue => e
         | 
| 395 | 
            -
                    send_failsafe("error logging instance link", e)
         | 
| 396 | 
            -
                    return
         | 
| 397 | 
            -
                  end
         | 
| 398 | 
            -
                end
         | 
| 399 | 
            -
             | 
| 400 | 
            -
                ## Payload building functions
         | 
| 401 | 
            -
             | 
| 402 | 
            -
                def build_item(level, message, exception, extra)
         | 
| 403 | 
            -
                  options = {
         | 
| 404 | 
            -
                    :level => level,
         | 
| 405 | 
            -
                    :message => message,
         | 
| 406 | 
            -
                    :exception => exception,
         | 
| 407 | 
            -
                    :extra => extra,
         | 
| 408 | 
            -
                    :configuration => configuration,
         | 
| 409 | 
            -
                    :logger => logger,
         | 
| 410 | 
            -
                    :scope => scope_object,
         | 
| 411 | 
            -
                    :notifier => self
         | 
| 412 | 
            -
                  }
         | 
| 413 | 
            -
             | 
| 414 | 
            -
                  item = Item.new(options)
         | 
| 415 | 
            -
                  item.build
         | 
| 416 | 
            -
             | 
| 417 | 
            -
                  item
         | 
| 418 | 
            -
                end
         | 
| 419 | 
            -
             | 
| 420 | 
            -
                ## Delivery functions
         | 
| 421 | 
            -
             | 
| 422 | 
            -
                def send_item_using_eventmachine(item)
         | 
| 423 | 
            -
                  body = item.dump
         | 
| 424 | 
            -
                  return unless body
         | 
| 425 | 
            -
             | 
| 426 | 
            -
                  headers = { 'X-Rollbar-Access-Token' => item['access_token'] }
         | 
| 427 | 
            -
                  req = EventMachine::HttpRequest.new(configuration.endpoint).post(:body => body, :head => headers)
         | 
| 428 | 
            -
             | 
| 429 | 
            -
                  req.callback do
         | 
| 430 | 
            -
                    if req.response_header.status == 200
         | 
| 431 | 
            -
                      log_info '[Rollbar] Success'
         | 
| 432 | 
            -
                    else
         | 
| 433 | 
            -
                      log_warning "[Rollbar] Got unexpected status code from Rollbar.io api: #{req.response_header.status}"
         | 
| 434 | 
            -
                      log_info "[Rollbar] Response: #{req.response}"
         | 
| 435 | 
            -
                    end
         | 
| 436 | 
            -
                  end
         | 
| 437 | 
            -
             | 
| 438 | 
            -
                  req.errback do
         | 
| 439 | 
            -
                    log_warning "[Rollbar] Call to API failed, status code: #{req.response_header.status}"
         | 
| 440 | 
            -
                    log_info "[Rollbar] Error's response: #{req.response}"
         | 
| 441 | 
            -
                  end
         | 
| 442 | 
            -
                end
         | 
| 443 | 
            -
             | 
| 444 | 
            -
                def send_item(item)
         | 
| 445 | 
            -
                  log_info '[Rollbar] Sending item'
         | 
| 446 | 
            -
             | 
| 447 | 
            -
                  if configuration.use_eventmachine
         | 
| 448 | 
            -
                    send_item_using_eventmachine(item)
         | 
| 449 | 
            -
                    return
         | 
| 450 | 
            -
                  end
         | 
| 451 | 
            -
             | 
| 452 | 
            -
                  body = item.dump
         | 
| 453 | 
            -
                  return unless body
         | 
| 454 | 
            -
             | 
| 455 | 
            -
                  uri = URI.parse(configuration.endpoint)
         | 
| 456 | 
            -
             | 
| 457 | 
            -
                  handle_response(do_post(uri, body, item['access_token']))
         | 
| 458 | 
            -
                end
         | 
| 459 | 
            -
             | 
| 460 | 
            -
                def do_post(uri, body, access_token)
         | 
| 461 | 
            -
                  http = Net::HTTP.new(uri.host, uri.port)
         | 
| 462 | 
            -
                  http.open_timeout = configuration.open_timeout
         | 
| 463 | 
            -
                  http.read_timeout = configuration.request_timeout
         | 
| 464 | 
            -
             | 
| 465 | 
            -
                  if uri.scheme == 'https'
         | 
| 466 | 
            -
                    http.use_ssl = true
         | 
| 467 | 
            -
                    # This is needed to have 1.8.7 passing tests
         | 
| 468 | 
            -
                    http.ca_file = ENV['ROLLBAR_SSL_CERT_FILE'] if ENV.has_key?('ROLLBAR_SSL_CERT_FILE')
         | 
| 469 | 
            -
                    http.verify_mode = ssl_verify_mode
         | 
| 470 | 
            -
                  end
         | 
| 471 | 
            -
             | 
| 472 | 
            -
                  request = Net::HTTP::Post.new(uri.request_uri)
         | 
| 473 | 
            -
             | 
| 474 | 
            -
                  request.body = body
         | 
| 475 | 
            -
                  request.add_field('X-Rollbar-Access-Token', access_token)
         | 
| 476 | 
            -
             | 
| 477 | 
            -
                  handle_net_retries { http.request(request) }
         | 
| 478 | 
            -
                end
         | 
| 479 | 
            -
             | 
| 480 | 
            -
                def handle_net_retries
         | 
| 481 | 
            -
                  return yield if skip_retries?
         | 
| 482 | 
            -
             | 
| 483 | 
            -
                  retries = configuration.net_retries - 1
         | 
| 484 | 
            -
             | 
| 485 | 
            -
                  begin
         | 
| 486 | 
            -
                    yield
         | 
| 487 | 
            -
                  rescue *LanguageSupport.timeout_exceptions
         | 
| 488 | 
            -
                    raise if retries <= 0
         | 
| 489 | 
            -
             | 
| 490 | 
            -
                    retries -= 1
         | 
| 491 | 
            -
             | 
| 492 | 
            -
                    retry
         | 
| 493 | 
            -
                  end
         | 
| 494 | 
            -
                end
         | 
| 495 | 
            -
             | 
| 496 | 
            -
                def skip_retries?
         | 
| 497 | 
            -
                  Rollbar::LanguageSupport.ruby_18? || Rollbar::LanguageSupport.ruby_19?
         | 
| 498 | 
            -
                end
         | 
| 499 | 
            -
             | 
| 500 | 
            -
                def handle_response(response)
         | 
| 501 | 
            -
                  if response.code == '200'
         | 
| 502 | 
            -
                    log_info '[Rollbar] Success'
         | 
| 503 | 
            -
                  else
         | 
| 504 | 
            -
                    log_warning "[Rollbar] Got unexpected status code from Rollbar api: #{response.code}"
         | 
| 505 | 
            -
                    log_info "[Rollbar] Response: #{response.body}"
         | 
| 506 | 
            -
                  end
         | 
| 507 | 
            -
                end
         | 
| 508 | 
            -
             | 
| 509 | 
            -
                def ssl_verify_mode
         | 
| 510 | 
            -
                  if configuration.verify_ssl_peer
         | 
| 511 | 
            -
                    OpenSSL::SSL::VERIFY_PEER
         | 
| 512 | 
            -
                  else
         | 
| 513 | 
            -
                    OpenSSL::SSL::VERIFY_NONE
         | 
| 514 | 
            -
                  end
         | 
| 515 | 
            -
                end
         | 
| 516 | 
            -
             | 
| 517 | 
            -
                def write_item(item)
         | 
| 518 | 
            -
                  if configuration.use_async
         | 
| 519 | 
            -
                    @file_semaphore.synchronize {
         | 
| 520 | 
            -
                      do_write_item(item)
         | 
| 521 | 
            -
                    }
         | 
| 522 | 
            -
                  else
         | 
| 523 | 
            -
                    do_write_item(item)
         | 
| 524 | 
            -
                  end
         | 
| 525 | 
            -
                end
         | 
| 526 | 
            -
             | 
| 527 | 
            -
                def do_write_item(item)
         | 
| 528 | 
            -
                  log_info '[Rollbar] Writing item to file'
         | 
| 529 | 
            -
             | 
| 530 | 
            -
                  body = item.dump
         | 
| 531 | 
            -
                  return unless body
         | 
| 532 | 
            -
             | 
| 533 | 
            -
                  begin
         | 
| 534 | 
            -
                    unless @file
         | 
| 535 | 
            -
                      @file = File.open(configuration.filepath, "a")
         | 
| 536 | 
            -
                    end
         | 
| 537 | 
            -
             | 
| 538 | 
            -
                    @file.puts(body)
         | 
| 539 | 
            -
                    @file.flush
         | 
| 540 | 
            -
                    log_info "[Rollbar] Success"
         | 
| 541 | 
            -
                  rescue IOError => e
         | 
| 542 | 
            -
                    log_error "[Rollbar] Error opening/writing to file: #{e}"
         | 
| 543 | 
            -
                  end
         | 
| 544 | 
            -
                end
         | 
| 545 | 
            -
             | 
| 546 | 
            -
                def failsafe_reason(message, exception)
         | 
| 547 | 
            -
                  body = ''
         | 
| 548 | 
            -
             | 
| 549 | 
            -
                  if exception
         | 
| 550 | 
            -
                    begin
         | 
| 551 | 
            -
                      backtrace = exception.backtrace || []
         | 
| 552 | 
            -
                      nearest_frame = backtrace[0]
         | 
| 553 | 
            -
             | 
| 554 | 
            -
                      exception_info = exception.class.name
         | 
| 555 | 
            -
                      # #to_s and #message defaults to class.to_s. Add message only if add valuable info.
         | 
| 556 | 
            -
                      exception_info += %Q{: "#{exception.message}"} if exception.message != exception.class.to_s
         | 
| 557 | 
            -
                      exception_info += " in #{nearest_frame}" if nearest_frame
         | 
| 558 | 
            -
             | 
| 559 | 
            -
                      body += "#{exception_info}: #{message}"
         | 
| 560 | 
            -
                    rescue
         | 
| 561 | 
            -
                    end
         | 
| 562 | 
            -
                  else
         | 
| 563 | 
            -
                    begin
         | 
| 564 | 
            -
                      body += message.to_s
         | 
| 565 | 
            -
                    rescue
         | 
| 566 | 
            -
                    end
         | 
| 567 | 
            -
                  end
         | 
| 568 | 
            -
             | 
| 569 | 
            -
                  body
         | 
| 570 | 
            -
                end
         | 
| 571 | 
            -
             | 
| 572 | 
            -
                def failsafe_body(reason)
         | 
| 573 | 
            -
                  "Failsafe from rollbar-gem. #{reason}"
         | 
| 574 | 
            -
                end
         | 
| 575 | 
            -
             | 
| 576 | 
            -
                def schedule_item(item)
         | 
| 577 | 
            -
                  return unless item
         | 
| 578 | 
            -
             | 
| 579 | 
            -
                  log_info '[Rollbar] Scheduling item'
         | 
| 580 | 
            -
             | 
| 581 | 
            -
                  if configuration.use_async
         | 
| 582 | 
            -
                    process_async_item(item)
         | 
| 583 | 
            -
                  else
         | 
| 584 | 
            -
                    process_item(item)
         | 
| 585 | 
            -
                  end
         | 
| 586 | 
            -
                end
         | 
| 587 | 
            -
             | 
| 588 | 
            -
                def default_async_handler
         | 
| 589 | 
            -
                  return Rollbar::Delay::GirlFriday if defined?(GirlFriday)
         | 
| 590 | 
            -
             | 
| 591 | 
            -
                  Rollbar::Delay::Thread
         | 
| 592 | 
            -
                end
         | 
| 593 | 
            -
             | 
| 594 | 
            -
                def process_async_item(item)
         | 
| 595 | 
            -
                  configuration.async_handler ||= default_async_handler
         | 
| 596 | 
            -
                  configuration.async_handler.call(item.payload)
         | 
| 597 | 
            -
                rescue => e
         | 
| 598 | 
            -
                  if configuration.failover_handlers.empty?
         | 
| 599 | 
            -
                    log_error '[Rollbar] Async handler failed, and there are no failover handlers configured. See the docs for "failover_handlers"'
         | 
| 600 | 
            -
                    return
         | 
| 601 | 
            -
                  end
         | 
| 602 | 
            -
             | 
| 603 | 
            -
                  async_failover(item)
         | 
| 604 | 
            -
                end
         | 
| 605 | 
            -
             | 
| 606 | 
            -
                def async_failover(item)
         | 
| 607 | 
            -
                  log_warning '[Rollbar] Primary async handler failed. Trying failovers...'
         | 
| 608 | 
            -
             | 
| 609 | 
            -
                  failover_handlers = configuration.failover_handlers
         | 
| 610 | 
            -
             | 
| 611 | 
            -
                  failover_handlers.each do |handler|
         | 
| 612 | 
            -
                    begin
         | 
| 613 | 
            -
                      handler.call(item.payload)
         | 
| 614 | 
            -
                    rescue
         | 
| 615 | 
            -
                      next unless handler == failover_handlers.last
         | 
| 616 | 
            -
             | 
| 617 | 
            -
                      log_error "[Rollbar] All failover handlers failed while processing item: #{Rollbar::JSON.dump(item.payload)}"
         | 
| 618 | 
            -
                    end
         | 
| 619 | 
            -
                  end
         | 
| 620 | 
            -
                end
         | 
| 621 | 
            -
             | 
| 622 | 
            -
                ## Logging
         | 
| 623 | 
            -
                %w(debug info warn error).each do |level|
         | 
| 624 | 
            -
                  define_method(:"log_#{level}") do |message|
         | 
| 625 | 
            -
                    logger.send(level, message)
         | 
| 626 | 
            -
                  end
         | 
| 627 | 
            -
                end
         | 
| 628 | 
            -
             | 
| 629 | 
            -
                alias_method :log_warning, :log_warn
         | 
| 630 | 
            -
             | 
| 631 | 
            -
                def log_instance_link(data)
         | 
| 632 | 
            -
                  if data[:uuid]
         | 
| 633 | 
            -
                    uuid_url = Util.uuid_rollbar_url(data, configuration)
         | 
| 634 | 
            -
                    log_info "[Rollbar] Details: #{uuid_url} (only available if report was successful)"
         | 
| 635 | 
            -
                  end
         | 
| 636 | 
            -
                end
         | 
| 637 | 
            -
             | 
| 638 | 
            -
                def logger
         | 
| 639 | 
            -
                  @logger ||= LoggerProxy.new(configuration.logger)
         | 
| 640 | 
            -
                end
         | 
| 641 | 
            -
              end
         | 
| 25 | 
            +
                                           process_item process_from_async_handler scope
         | 
| 26 | 
            +
                                           send_failsafe log_info log_debug log_warning
         | 
| 27 | 
            +
                                           log_error silenced scope_object with_config).freeze
         | 
| 642 28 |  | 
| 643 29 | 
             
              class << self
         | 
| 644 30 | 
             
                extend Forwardable
         | 
| @@ -646,43 +32,57 @@ module Rollbar | |
| 646 32 | 
             
                def_delegators :notifier, *PUBLIC_NOTIFIER_METHODS
         | 
| 647 33 |  | 
| 648 34 | 
             
                attr_writer :plugins
         | 
| 35 | 
            +
                attr_writer :root_notifier
         | 
| 649 36 |  | 
| 650 | 
            -
                 | 
| 651 | 
            -
             | 
| 652 | 
            -
             | 
| 653 | 
            -
                   | 
| 37 | 
            +
                def notifier
         | 
| 38 | 
            +
                  # Use the global instance @root_notifier so we don't fall
         | 
| 39 | 
            +
                  # in a infinite loop
         | 
| 40 | 
            +
                  Thread.current[:_rollbar_notifier] ||= Notifier.new(@root_notifier)
         | 
| 41 | 
            +
                end
         | 
| 654 42 |  | 
| 655 | 
            -
             | 
| 43 | 
            +
                def notifier=(notifier)
         | 
| 44 | 
            +
                  Thread.current[:_rollbar_notifier] = notifier
         | 
| 656 45 | 
             
                end
         | 
| 657 46 |  | 
| 658 | 
            -
                 | 
| 659 | 
            -
             | 
| 660 | 
            -
             | 
| 47 | 
            +
                # It's the first notifier instantiated in the
         | 
| 48 | 
            +
                # process. We store it so all the next per-thread
         | 
| 49 | 
            +
                # notifiers can inherit its configuration
         | 
| 50 | 
            +
                # The methods Rollbar.configure, Rollbar.reconfigure,
         | 
| 51 | 
            +
                # Rollbar.preconfigure and Rollbar.unconfigure work
         | 
| 52 | 
            +
                # on this notifier.
         | 
| 53 | 
            +
                # Before v2.13.0 these methods worked on the global
         | 
| 54 | 
            +
                # configuration, so in the practice the behavior is the same,
         | 
| 55 | 
            +
                # since they work on the root notifier's configuration
         | 
| 56 | 
            +
                def root_notifier
         | 
| 57 | 
            +
                  @root_notifier ||= notifier
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def preconfigure(&block)
         | 
| 61 | 
            +
                  root_notifier.preconfigure(&block)
         | 
| 62 | 
            +
                end
         | 
| 661 63 |  | 
| 662 | 
            -
             | 
| 64 | 
            +
                # Configures the root notifier and loads the plugins
         | 
| 65 | 
            +
                def configure(&block)
         | 
| 66 | 
            +
                  root_notifier.configure(&block)
         | 
| 663 67 |  | 
| 664 68 | 
             
                  plugins.load!
         | 
| 665 | 
            -
                  reset_notifier!
         | 
| 666 69 | 
             
                end
         | 
| 667 70 |  | 
| 668 | 
            -
                 | 
| 669 | 
            -
             | 
| 670 | 
            -
                   | 
| 671 | 
            -
                  yield(configuration)
         | 
| 672 | 
            -
             | 
| 673 | 
            -
                  reset_notifier!
         | 
| 71 | 
            +
                # Reconfigures the root notifier
         | 
| 72 | 
            +
                def reconfigure(&block)
         | 
| 73 | 
            +
                  root_notifier.reconfigure(&block)
         | 
| 674 74 | 
             
                end
         | 
| 675 75 |  | 
| 76 | 
            +
                # Unconfigures the root notifier
         | 
| 676 77 | 
             
                def unconfigure
         | 
| 677 | 
            -
                   | 
| 78 | 
            +
                  root_notifier.unconfigure
         | 
| 678 79 | 
             
                end
         | 
| 679 80 |  | 
| 81 | 
            +
                # Returns the configuration for the current notifier.
         | 
| 82 | 
            +
                # The current notifier is Rollbar.notifier and exists
         | 
| 83 | 
            +
                # one per thread.
         | 
| 680 84 | 
             
                def configuration
         | 
| 681 | 
            -
                   | 
| 682 | 
            -
                end
         | 
| 683 | 
            -
             | 
| 684 | 
            -
                def scope_object
         | 
| 685 | 
            -
                  @scope_obejct ||= ::Rollbar::LazyStore.new({})
         | 
| 85 | 
            +
                  notifier.configuration
         | 
| 686 86 | 
             
                end
         | 
| 687 87 |  | 
| 688 88 | 
             
                def safely?
         | 
| @@ -693,14 +93,6 @@ module Rollbar | |
| 693 93 | 
             
                  @plugins ||= Rollbar::Plugins.new
         | 
| 694 94 | 
             
                end
         | 
| 695 95 |  | 
| 696 | 
            -
                def notifier
         | 
| 697 | 
            -
                  Thread.current[:_rollbar_notifier] ||= Notifier.new(self)
         | 
| 698 | 
            -
                end
         | 
| 699 | 
            -
             | 
| 700 | 
            -
                def notifier=(notifier)
         | 
| 701 | 
            -
                  Thread.current[:_rollbar_notifier] = notifier
         | 
| 702 | 
            -
                end
         | 
| 703 | 
            -
             | 
| 704 96 | 
             
                def last_report
         | 
| 705 97 | 
             
                  Thread.current[:_rollbar_last_report]
         | 
| 706 98 | 
             
                end
         | 
| @@ -709,8 +101,24 @@ module Rollbar | |
| 709 101 | 
             
                  Thread.current[:_rollbar_last_report] = report
         | 
| 710 102 | 
             
                end
         | 
| 711 103 |  | 
| 104 | 
            +
                # Resets the scope for the current thread notifier. The notifier
         | 
| 105 | 
            +
                # reference is kept so we reuse the notifier.
         | 
| 106 | 
            +
                # This is a change from version 2.13.0. Before this version
         | 
| 107 | 
            +
                # this method clears the notifier.
         | 
| 108 | 
            +
                #
         | 
| 109 | 
            +
                # It was used in order to reset the scope and reusing the global
         | 
| 110 | 
            +
                # configuration Rollbar.configuration. Since now Rollbar.configuration
         | 
| 111 | 
            +
                # points to the current notifier configuration, we can resue the
         | 
| 112 | 
            +
                # notifier instance and just reset the scope.
         | 
| 712 113 | 
             
                def reset_notifier!
         | 
| 114 | 
            +
                  notifier.reset!
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                # Clears the current thread notifier and the root notifier.
         | 
| 118 | 
            +
                # In the practice this should be used only on the specs
         | 
| 119 | 
            +
                def clear_notifier!
         | 
| 713 120 | 
             
                  self.notifier = nil
         | 
| 121 | 
            +
                  self.root_notifier = nil
         | 
| 714 122 | 
             
                end
         | 
| 715 123 |  | 
| 716 124 | 
             
                # Create a new Notifier instance using the received options and
         | 
| @@ -721,16 +129,18 @@ module Rollbar | |
| 721 129 | 
             
                # @example
         | 
| 722 130 | 
             
                #
         | 
| 723 131 | 
             
                #   new_scope = { job_type: 'scheduled' }
         | 
| 724 | 
            -
                #    | 
| 132 | 
            +
                #   new_config = { use_async: false }
         | 
| 133 | 
            +
                #
         | 
| 134 | 
            +
                #   Rollbar.scoped(new_scope, new_config) do
         | 
| 725 135 | 
             
                #     begin
         | 
| 726 136 | 
             
                #       # do stuff
         | 
| 727 137 | 
             
                #     rescue => e
         | 
| 728 | 
            -
                #       Rollbar. | 
| 138 | 
            +
                #       Rollbar.error(e)
         | 
| 729 139 | 
             
                #     end
         | 
| 730 140 | 
             
                #   end
         | 
| 731 | 
            -
                def scoped(options = {})
         | 
| 141 | 
            +
                def scoped(options = {}, config_overrides = {})
         | 
| 732 142 | 
             
                  old_notifier = notifier
         | 
| 733 | 
            -
                  self.notifier = old_notifier.scope(options)
         | 
| 143 | 
            +
                  self.notifier = old_notifier.scope(options, config_overrides)
         | 
| 734 144 |  | 
| 735 145 | 
             
                  result = yield
         | 
| 736 146 | 
             
                  result
         | 
| @@ -738,6 +148,12 @@ module Rollbar | |
| 738 148 | 
             
                  self.notifier = old_notifier
         | 
| 739 149 | 
             
                end
         | 
| 740 150 |  | 
| 151 | 
            +
                # Create a new Notifier instance with a new configuration
         | 
| 152 | 
            +
                # using the current one but merging the passed options.
         | 
| 153 | 
            +
                def with_config(overrides, &block)
         | 
| 154 | 
            +
                  scoped(nil, overrides, &block)
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
             | 
| 741 157 | 
             
                def scope!(options = {})
         | 
| 742 158 | 
             
                  notifier.scope!(options)
         | 
| 743 159 | 
             
                end
         |